linux设备驱动开发-设备阻塞访问的简单实现
2014-06-23 10:46
351 查看
当我们读取一个空的命名管道文件是,会阻塞等待,知道有新数据写入管道中。访问阻塞在设备驱动中非常常见,而且也是非常必要的一种功能。
而我们实现设备驱动的阻塞访问通常是通过等待队列的机制实现。
等待队列的使用比较简单。下面是申明和定义一个等待队列的两种方法:
1.静态
DECLARE_WAIT_QUEUE_HEAD(wq);
2.动态
wait_queue_head_t wq;
init_waitqueue_head(&wq);
3.使用
wait_event_interruptible(wq, condition);//加入等待 或者其他等价的接口
wake_up_interruptible(&wq); //唤醒等待队列 或者其他等价的接口
下面的例子能够更好的说明等待队列的用法
而我们实现设备驱动的阻塞访问通常是通过等待队列的机制实现。
等待队列的使用比较简单。下面是申明和定义一个等待队列的两种方法:
1.静态
DECLARE_WAIT_QUEUE_HEAD(wq);
2.动态
wait_queue_head_t wq;
init_waitqueue_head(&wq);
3.使用
wait_event_interruptible(wq, condition);//加入等待 或者其他等价的接口
wake_up_interruptible(&wq); //唤醒等待队列 或者其他等价的接口
下面的例子能够更好的说明等待队列的用法
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/uaccess.h> #define SIZE 1024 #define NR 4 static int major = 100, minor = 0; module_param(major, int, 0400); module_param(minor, int, 0400); // ================================================================= struct mypipe_t { char buf[SIZE]; int in, out; }; static void mypipe_init(struct mypipe_t *pipe) { pipe->in = pipe->out = 0; } static int mypipe_is_full(struct mypipe_t *pipe) { return (pipe->in + 1) % SIZE == pipe->out; } static int mypipe_is_empty(struct mypipe_t *pipe) { return pipe->in == pipe->out; } static int mypipe_read_one_char(struct mypipe_t *pipe, char *ch) { if (mypipe_is_empty(pipe)) { return -1; } *ch = pipe->buf[pipe->out]; pipe->out = (pipe->out + 1) % SIZE; return 0; } static int mypipe_write_one_char(struct mypipe_t *pipe, char ch) { if (mypipe_is_full(pipe)) { return -1; } pipe->buf[pipe->in] = ch; pipe->in = (pipe->in + 1) % SIZE; return 0; } // ================================================================= struct mydev_t { dev_t devno; struct cdev cdev; wait_queue_head_t rq, wq; struct mypipe_t pipe; }; struct mydev_t mydev[NR]; //================================================================== static int myopen(struct inode *inode, struct file *filp) { #if 0 //MINOR(inode->i_rdev); int index = iminor(inode); filp->private_data = &mydev[index]; #else filp->private_data = container_of(inode->i_cdev, struct mydev_t, cdev); #endif return 0; } static ssize_t myread(struct file *filp, char __user *buf, size_t len, loff_t *off) { int i, ret; char ch; struct mydev_t *devp = filp->private_data; ret = wait_event_interruptible(devp->rq, !mypipe_is_empty(&devp->pipe)); if (ret != 0) { return -EINTR; } for (i = 0; i < len; ++i) { ret = mypipe_read_one_char(&devp->pipe, &ch); if (ret != 0) break; //buf[i] = ch; //copy_to_user(&buf[i], &ch, 1); put_user(ch, &buf[i]); } wake_up_interruptible(&devp->wq); return i; } static ssize_t mywrite(struct file *filp, const char __user *buf, size_t len, loff_t *off) { int i, ret; char ch; struct mydev_t *devp = filp->private_data; ret = wait_event_interruptible(devp->wq, !mypipe_is_full(&devp->pipe)); if (ret != 0) { return -EINTR; } for (i = 0; i < len; ++i) { get_user(ch, &buf[i]); ret = mypipe_write_one_char(&devp->pipe, ch); if (ret != 0) break; } wake_up_interruptible(&devp->rq); return i; } static int myrelease(struct inode *inode, struct file *filp) { return 0; } struct file_operations pipe_ops = { .open = myopen, .release = myrelease, .read = myread, .write = mywrite, }; //================================================================== static int __init test_init(void) { int i; dev_t devno; struct mydev_t *devp; devno = MKDEV(major, minor); register_chrdev_region(devno, NR, "mypipe"); for (i = 0; i < NR; ++i) { devp = &mydev[i]; init_waitqueue_head(&devp->rq); init_waitqueue_head(&devp->wq); mypipe_init(&devp->pipe); cdev_init(&devp->cdev, &pipe_ops); devno = MKDEV(major, minor + i); cdev_add(&devp->cdev, devno, 1); } return 0; } static void __exit test_exit(void) { int i; dev_t devno; struct mydev_t *devp; for (i = 0; i < NR; ++i) { devp = &mydev[i]; cdev_del(&devp->cdev); } devno = MKDEV(major, minor); unregister_chrdev_region(devno, NR); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL");
相关文章推荐
- Hasen的linux设备驱动开发学习之旅--支持阻塞的设备驱动
- linux设备驱动第三篇:如何实现一个简单的字符设备驱动
- Linux设备驱动开发-linux驱动中的阻塞访问方式
- linux设备驱动开发学习之旅--支持阻塞的设备驱动
- Linux驱动开发-11、设备阻塞访问-等待队列
- Linux设备驱动开发-linux驱动中的阻塞访问方式
- linux设备驱动第三篇:如何实现简单的字符设备驱动
- linux设备驱动第三篇:如何实现一个简单的字符设备驱动
- Linux设备驱动开发-linux驱动中的非阻塞访问方式
- Linux设备驱动开发-linux驱动中的非阻塞访问方式
- LDD3《Linux设备驱动》中的最简单的字符设备驱动实现与测试
- 开发直接访问SQL Server的智能设备应用程序
- 谈虚拟环境中设备访问的实现方法(中)
- 在asp.net2.0中提供了新一代的数据访问工具--DataSource。它为简单的数据库开发提供了便捷的方式
- FleaPHP 开发指南 - 8. 如何使用 RBAC 组件实现访问控制
- 深入浅出Linux设备驱动编程--设备的阻塞与非阻塞操作
- 开发直接访问SQL Server的智能设备应用程序
- FleaPHP 开发指南 - 8. 如何使用 RBAC 组件实现访问控制
- 基于SNMP的MIB库访问实现两个简单的画验证码图形程序
- FleaPHP 开发指南 - 8. 如何使用 RBAC 组件实现访问控制