怎么才能创建个人网站,wordpress 地图xml生成,asp.net 当前网站,延安做网站电话文章目录 等待队列头实现阻塞 IO(BIO)模型等待队列头init_waitqueue_headDECLARE_WAIT_QUEUE_HEAD 等待队列项使用方法驱动程序应用程序模块使用参考 等待队列头实现阻塞 IO(BIO)
等待队列是内核实现阻塞和唤醒的内核机制。 等待队列以循环链表为基础结构#xff0c;链表头和… 文章目录 等待队列头实现阻塞 IO(BIO)模型等待队列头init_waitqueue_headDECLARE_WAIT_QUEUE_HEAD 等待队列项使用方法驱动程序应用程序模块使用参考 等待队列头实现阻塞 IO(BIO)
等待队列是内核实现阻塞和唤醒的内核机制。 等待队列以循环链表为基础结构链表头和链表项分别为等待队列头和等待队列元素。 整个等待队列由等待队列头进行管理。
模型 等待队列头
等待队列头使用结构体 wait_queue_head_t定义在 linux/wait.h结构体原型如下
struct wait_queue_head {spinlock_t lock;struct list_head head;
};
typedef struct wait_queue_head wait_queue_head_t;等待队列头的初始化有两种方法
init_waitqueue_head
定义一个等待队列头 wait_queue_head_t read_wait等待 队列头初始化 init_waitqueue_head(read_wait)
DECLARE_WAIT_QUEUE_HEAD
DECLARE_WAIT_QUEUE_HEAD 宏一次性完成等待队列头的定义和初始化
等待队列项
等待队列项使用结构体 struct wait_queue_entry定义在 linux/wait.h结构体原型如下
struct wait_queue_entry {unsigned int flags;void *private;wait_queue_func_t func;struct list_head entry;
};使用方法
初始化等待队列头并将条件设置为假的(condition0)在需要阻塞的地方调用 wait_event 或者 wait_event_interruptible使进程进入休眠当条件满足时需要解除休眠先将条件设置为真(condition1)然后调用 wake_up 或者 wake_up_interruptible函数唤醒等待队列中的休眠进程。
驱动程序
#include linux/device/class.h
#include linux/export.h
#include linux/uaccess.h
#include linux/types.h
#include linux/kernel.h
#include linux/init.h
#include linux/module.h
#include linux/fs.h
#include linux/device.h
#include linux/cdev.h
#include linux/wait.h#define CHRDEVBASE_NAME chrdevbase /* 设备名 */
#define CHRDEVBASE_NUM 1 /* 设备数目 */static char *string_test kernel data this tyustli test;typedef struct {dev_t dev_id; /* 设备号 */struct cdev c_dev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */int flag; /* read flag */char write_buf[100];char read_buf[100];wait_queue_head_t read_wait; /* 读等待队列头 */
} new_chrdev_t;static new_chrdev_t new_chrdev1;static int chrdevbase_open(struct inode *inode, struct file *file)
{file-private_data container_of(inode-i_cdev, new_chrdev_t, c_dev); /* 设置私有数据 */printk(k: chrdevbase open\r\n);return 0;
}static ssize_t chrdevbase_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
{unsigned long ret 0;new_chrdev_t *dev (new_chrdev_t *)file-private_data;wait_event_interruptible(dev-read_wait, dev-flag);memcpy(dev-read_buf, string_test, strlen(string_test));ret copy_to_user(buf, dev-read_buf, count);if (ret 0) {printk(k: read data success\r\n);} else {printk(k: read data failed ret %ld\r\n, ret);}return ret;
}static ssize_t chrdevbase_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{unsigned long ret 0;new_chrdev_t *dev (new_chrdev_t *)file-private_data;ret copy_from_user(dev-write_buf, buf, count);if (ret 0) {printk(k: write data success write data is: %s\r\n, dev-write_buf);} else {printk(k: write data failed ret %ld\r\n, ret);}dev-flag 1;wake_up_interruptible(dev-read_wait);return count;
}static int chrdevbase_release(struct inode *inode, struct file *file)
{printk(k: chrdevbase release\r\n);return 0;
}static struct file_operations chrdevbase_fops {.owner THIS_MODULE,.open chrdevbase_open,.read chrdevbase_read,.write chrdevbase_write,.release chrdevbase_release,
};static int __init chrdevbase_init(void)
{int err 0;err alloc_chrdev_region(new_chrdev1.dev_id, 0, CHRDEVBASE_NUM,CHRDEVBASE_NAME);if (err 0) {printk(k: alloc chrdev region failed err %d\r\n, err);goto err_chrdev;}/* get major 1 and minor 1 */new_chrdev1.major MAJOR(new_chrdev1.dev_id);new_chrdev1.minor MINOR(new_chrdev1.dev_id);printk(k: newcheled major%d,minor%d\r\n, new_chrdev1.major,new_chrdev1.minor);new_chrdev1.c_dev.owner THIS_MODULE;cdev_init(new_chrdev1.c_dev, chrdevbase_fops);err cdev_add(new_chrdev1.c_dev, new_chrdev1.dev_id, 1);if (err 0) {printk(k: cdev add failed err %d\r\n, err);goto err_cdev_add;}new_chrdev1.class class_create(chr_test1);if (IS_ERR(new_chrdev1.class)) {err PTR_ERR(new_chrdev1.class);goto err_class_create;}new_chrdev1.device device_create(new_chrdev1.class, NULL,new_chrdev1.dev_id, NULL, chr_test1);if (IS_ERR(new_chrdev1.device)) {err PTR_ERR(new_chrdev1.device);goto err_device_create;}/* 初始化等待队列头 */init_waitqueue_head(new_chrdev1.read_wait);new_chrdev1.flag 0;printk(k: base module init\r\n);return 0;err_device_create:class_destroy(new_chrdev1.class);
err_class_create:cdev_del(new_chrdev1.c_dev);
err_cdev_add:unregister_chrdev_region(new_chrdev1.dev_id, CHRDEVBASE_NUM);
err_chrdev:return err;
}static void __exit chrdevbase_exit(void)
{device_destroy(new_chrdev1.class, new_chrdev1.dev_id);class_destroy(new_chrdev1.class);cdev_del(new_chrdev1.c_dev);unregister_chrdev_region(new_chrdev1.dev_id, CHRDEVBASE_NUM);printk(k: base module exit!\r\n);
}module_init(chrdevbase_init);
module_exit(chrdevbase_exit);MODULE_LICENSE(GPL);
MODULE_AUTHOR(tyustli);
MODULE_INFO(intree, Y); /* loading out-of-tree module taints kernel */
应用程序
应用程序使用 O_RDWR 默认以阻塞的方式打开
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdlib.h
#include string.hstatic char usrdata[] { user data! };int main(int argc, char *argv[])
{int fd, retvalue;char *filename;char readbuf[100], writebuf[100];if (argc ! 3) {printf(u: error Usage!\r\n);return -1;}filename argv[1];/* 打开驱动文件 */fd open(filename, O_RDWR);if (fd 0) {printf(u: cant open file %s\r\n, filename);return -1;}/* 从驱动文件读取数据 */if (atoi(argv[2]) 1) {retvalue read(fd, readbuf, 50);if (retvalue 0) {printf(u: read file %s failed!\r\n, filename);} else {/* 读取成功打印出读取成功的数据 */printf(u: read data:%s\r\n, readbuf);}}/* 向设备驱动写数据 */if (atoi(argv[2]) 2) {memcpy(writebuf, usrdata, sizeof(usrdata));retvalue write(fd, writebuf, 50);if (retvalue 0) {printf(u: write file %s failed!\r\n, filename);}}/* 关闭设备 */retvalue close(fd);if (retvalue 0) {printf(u: cant close file %s\r\n, filename);return -1;}return 0;
}
模块使用
模块安装
modprobe my_module查看设备节点
ls /dev~ # ls /dev/
chr_test1 ptypc tty32 tty7
console ptypd tty33 tty8
cpu_dma_latency ptype tty34 tty9
full ptypf tty35 ttyAMA0
gpiochip0 random tty36 ttyAMA1
gpiochip1 root tty37 ttyAMA2
gpiochip2 rtc0 tty38 ttyAMA3
gpiochip3 snd tty39 ttyp0
hwrng tty tty4 ttyp1
input tty0 tty40 ttyp2
kmsg tty1 tty41 ttyp3模块使用
~ # /lib/modules/6.5.7/my_app /dev/chr_test1 1
~ # k: chrdevbase open~ # /lib/modules/6.5.7/my_app /dev/chr_test1 2
k: chrdevbase open
k: write data success write data is: user data!
k: read data success
k: chrdevbase release
~ # u: read data:kernel data this tyustli test
k: chrdevbase release[1] Done /lib/modules/6.5.7/my_app /dev/chr_test1 1参考
https://juejin.cn/post/7129070726249709599#heading-0