2026/3/27 6:46:17
网站建设
项目流程
最新建设招聘信息网站,男女生做爰视频网站,pycharm做网站,怎样在微信做产品网站非阻塞 IO 简介 在非阻塞 IO 模型中#xff0c;内核数据还未就绪时#xff0c;应用进程也可以做其他事情#xff0c;应用进程需要 不断询问内核数据是否就绪#xff0c;并不会被直接挂起。 如果应用程序要采用非阻塞的方式来访问驱动设备文件#xff0c;在使用 open()函数…非阻塞 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);Makefileexport ARCHarm64#设置平台架构 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可执行程序读取到了缓冲区的数据并打印