news 2026/6/9 18:44:43

非阻塞 IO 实验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
非阻塞 IO 实验
非阻塞 IO 简介
在非阻塞IO模型中,内核数据还未就绪时,应用进程也可以做其他事情,应用进程需要
不断询问内核数据是否就绪,并不会被直接挂起。
如果应用程序要采用非阻塞的方式来访问驱动设备文件,在使用open()函数打开
/dev/xxx_dev”设备文件的时候需要添加参数“O_NONBLOCK”,O_NONBLOCK表示以非阻
塞方式打开设备,这样从设备中读取数据的时候就是非阻塞方式了。
首先来编写应用测试代码read.c,在此代码中使用非阻塞的方式打开设备
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[]) { int fd; char buf1[32] = {0}; char buf2[32] = {0}; fd = open("/dev/test", O_RDWR | O_NONBLOCK); // 打开 led 驱动 if (fd < 0) { perror("open error \n"); return fd; } printf("read before \n"); while (1) { read(fd, buf1, sizeof(buf1)); // 从/dev/test 文件读取数据 printf("buf is %s \n", buf1); // 打印读取的数据 sleep(1); } printf("read after \n"); close(fd); // 关闭文件 return 0; }
接着编写应用程序write.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { int fd; char buf1[32] = {0}; char buf2[32] = "nihao"; fd = open("/dev/test", O_RDWR | O_NONBLOCK); // 打开 led 驱动 if (fd < 0) { perror("open error \n"); return fd; } printf("write before \n"); write(fd, buf2, sizeof(buf2)); // 向/dev/test 文件写入数据 printf("write after\n"); close(fd); // 关闭文件 return 0; }

nwq.c

#include <linux/cdev.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/io.h> #include <linux/kdev_t.h> #include <linux/module.h> #include <linux/uaccess.h> #include <linux/wait.h> struct device_test { dev_t dev_num; // 设备号 int major; // 主设备号 int minor; // 次设备号 struct cdev cdev_test; // cdev struct class *class; // 类 struct device *device; // 设备 char kbuf[32]; int flag; // 标志位 }; struct device_test dev1; DECLARE_WAIT_QUEUE_HEAD(read_wq); // 声明等待队列头 /*打开设备函数*/ static int cdev_test_open(struct inode *inode, struct file *file) { file->private_data = &dev1; // 设置私有数据 printk("This is cdev_test_open\r\n"); return 0; } /*向设备写入数据函数*/ static ssize_t cdev_test_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct device_test *test_dev = (struct device_test *)file->private_data; if (copy_from_user(test_dev->kbuf, buf, size) != 0) { printk("copy_from_user error\r\n"); return -1; } test_dev->flag = 1; // 将条件置 1 wake_up_interruptible(&read_wq); // 唤醒等待队列中的休眠进程 return size; } /*从设备读取数据*/ static ssize_t cdev_test_read(struct file *file, char __user *buf, size_t size, loff_t *off) { struct device_test *test_dev = (struct device_test *)file->private_data; // 可中断的阻塞等待,使进程进入休眠态 wait_event_interruptible(read_wq, test_dev->flag); if (copy_to_user(buf, test_dev->kbuf, size) != 0) { printk("copy_to_user error\r\n"); return -1; } test_dev->flag = 0; // 重置标志位 return size; } static int cdev_test_release(struct inode *inode, struct file *file) { return 0; } /*设备操作函数*/ struct file_operations cdev_test_fops = { .owner = THIS_MODULE, .open = cdev_test_open, .read = cdev_test_read, .write = cdev_test_write, .release = cdev_test_release, }; static int __init chr_fops_init(void) // 驱动入口函数 { int ret; /*1 创建设备号*/ ret = alloc_chrdev_region(&dev1.dev_num, 0, 1, "alloc_name"); if (ret < 0) { goto err_chrdev; } printk("alloc_chrdev_region is ok\n"); dev1.major = MAJOR(dev1.dev_num); // 获取主设备号 dev1.minor = MINOR(dev1.dev_num); // 获取次设备号 printk("major is %d \r\n", dev1.major); printk("minor is %d \r\n", dev1.minor); /*2 初始化 cdev*/ dev1.cdev_test.owner = THIS_MODULE; cdev_init(&dev1.cdev_test, &cdev_test_fops); /*3 添加一个 cdev,完成字符设备注册到内核*/ ret = cdev_add(&dev1.cdev_test, dev1.dev_num, 1); if (ret < 0) { goto err_chr_add; } /*4 创建类*/ dev1.class = class_create(THIS_MODULE, "test"); if (IS_ERR(dev1.class)) { ret = PTR_ERR(dev1.class); goto err_class_create; } /*5 创建设备*/ dev1.device = device_create(dev1.class, NULL, dev1.dev_num, NULL, "test"); if (IS_ERR(dev1.device)) { ret = PTR_ERR(dev1.device); goto err_device_create; } return 0; err_device_create: class_destroy(dev1.class); err_class_create: cdev_del(&dev1.cdev_test); err_chr_add: unregister_chrdev_region(dev1.dev_num, 1); err_chrdev: return ret; } static void __exit chr_fops_exit(void) // 驱动出口函数 { device_destroy(dev1.class, dev1.dev_num); class_destroy(dev1.class); cdev_del(&dev1.cdev_test); unregister_chrdev_region(dev1.dev_num, 1); } module_init(chr_fops_init); module_exit(chr_fops_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("topeet");

Makefile

export ARCH=arm64#设置平台架构 export CROSS_COMPILE=/home/alientek/rk3568_linux5.10_sdk/buildroot/output/rockchip_atk_dlrk3568/host/bin/aarch64-buildroot-linux-gnu-#交叉编译器前缀 obj-m += nwq.o #此处要和你的驱动源文件同名 KDIR :=/home/alientek/rk3568_linux5.10_sdk/kernel #这里是你的内核目录 PWD ?= $(shell pwd) all: make -C $(KDIR) M=$(PWD) modules #make 操作 clean: make -C $(KDIR) M=$(PWD) clean

输入./read命令运行read可执行文件

应用程序进程非阻塞,读取不到
数据便返回,然后一直轮询查看是否有数据

在使用可执行程序write向缓冲区写入数据时,read可执行程序读取到了缓冲区的数据并
打印
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/7 3:36:55

【收藏级干货】构建企业级客服Agent的5大核心设计原则与落地架构

【收藏级干货】玄姐亲授&#xff1a;构建企业级客服Agent的5大核心设计原则与落地架构 本文阐述了客服Agent系统设计的核心理念与方法&#xff0c;强调其本质是自动化业务执行系统而非聊天机器人。文章详细介绍了风险分层架构设计、三层状态管理模型、模糊意图处理策略及工程化…

作者头像 李华
网站建设 2026/6/9 18:34:19

收藏必备!大模型知识蒸馏技术调研:黑盒、白盒与混合方法全解析

文章调研了大模型知识蒸馏近年工作&#xff0c;分为黑盒和白盒两种类型。黑盒蒸馏在工业界应用更广&#xff0c;白盒蒸馏在学术界研究较多。文章介绍了代表性文献&#xff0c;包括DeepSeek-R1、MiniPLM等黑盒方法&#xff0c;以及DistilQwen2.5等黑白盒结合方法&#xff0c;并讨…

作者头像 李华
网站建设 2026/6/9 18:35:53

如何搭建一个GPU训练集群——把手教你从零开始

大家好&#xff0c;我是V哥。 话说AI运维工程师的成长路径&#xff0c;GPU集群到底怎么搭&#xff1f;公司让我搞这个&#xff0c;我连从哪下手都不知道啊&#xff01; 行&#xff0c;今天V哥就把这事儿给你掰开了、揉碎了讲清楚。不整那些高大上的概念轰炸&#xff0c;就用大白…

作者头像 李华
网站建设 2026/6/7 3:36:49

文本补全软件 espanso 配置某个应用单独使用某个补全

espanso 官网&#xff1a;https://espanso.org/ &#xff08;1&#xff09; config是配置文件目录 match是放补全规则的地方 &#xff08;2&#xff09; 先在match文件夹建补全规则 注意文件名以下划线开头&#xff0c;代表这个文件默认不生效 matches:- trigger: "s…

作者头像 李华
网站建设 2026/6/9 17:41:02

基于AI的政府审计监管系统对比:哪家更值得信赖?

基于AI的政府审计监管系统对比&#xff1a;哪家更值得信赖&#xff1f;在数字化转型的浪潮中&#xff0c;政府审计监管系统正逐渐引入人工智能技术&#xff0c;以提升审计效率和准确性。本文将对市场上主流的基于AI的政府审计监管系统进行对比分析&#xff0c;帮助读者了解各家…

作者头像 李华
网站建设 2026/6/9 17:41:28

Java+AI 核心指南:大模型丝滑接入与多模型统一范式

在人工智能技术深入企业业务的当下&#xff0c;Java作为企业级应用开发的主流技术栈&#xff0c;如何高效集成AI能力、实现业务系统智能化升级&#xff0c;成为众多技术团队面临的核心课题。不同于Python在AI算法研发领域的优势&#xff0c;Java技术栈的核心价值在于稳定的工程…

作者头像 李华