blocking and unblocking mechanism for linux drivern code
概念:
1> 阻塞操作 是指在执行设备操作时,若不能获得资源,则挂起进程直到满足操作条件后再进行操作。被挂起的进程进入休眠,被从调度器移走,直到条件满足;
2> 非阻塞操作 在不能进行设备操作时,并不挂起,它或者放弃,或者不停地查询,直到可以进行操作。非阻塞应用程序通常使用select系统调用查询是否可以对设备进行无阻塞的访问最终会引发设备驱动中poll函数执行。
- 1 /*
- * Theme for understanding the blocking and unblocking mechanism in device
- * driven module and difference of both modes
- *
- * Two aspects should be considered,firstly, when reading process is proceeding,
- * data must be existed in FIFO. Secconly, FIFO is non-full is prerequisite for
- * the writing process.
- *
- *Copyright (C) Continential- weizhen.diao@conti.engineering.com
- *
- */
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/sched.h>
- #include <linux/init.h>
- #include <linux/cdev.h>
- #include <linux/slab.h>
- #include <linux/poll.h>
- #define conti_globalfifo_SIZE 0x1000
- #define FIFO_CLEAR 0x1
- /*major devive number*/
- #define conti_globalfifo_MAJOR 231
- static int conti_globalfifo_major = conti_globalfifo_MAJOR;
- module_param(conti_globalfifo_major, int, S_IRUGO);
- /*conti_globalfifo device struct*/
- struct conti_globalfifo_dev {
- struct cdev cdev;
- unsigned int current_len;
- unsigned char mem[conti_globalfifo_SIZE];
- struct mutex mutex; //signal for concurrency control
- wait_queue_head_t r_wait; //list of kernel bidirectional loops for blocking reading
- wait_queue_head_t w_wait; //list of kernel bidirectional loops for blocking writing
- };
- struct conti_globalfifo_dev *conti_globalfifo_devp;
- static int conti_globalfifo_open(struct inode *inode, struct file *filp)
- {
- filp->private_data = conti_globalfifo_devp;
- return ;
- }
- static int conti_globalfifo_release(struct inode *inode, struct file *filp)
- {
- return ;
- }
- static long conti_globalfifo_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
- {
- struct conti_globalfifo_dev *dev = filp->private_data;
- switch (cmd) {
- case FIFO_CLEAR:
- mutex_lock(&dev->mutex);
- dev->current_len = ;
- memset(dev->mem, , conti_globalfifo_SIZE);
- mutex_unlock(&dev->mutex);
- printk(KERN_INFO "conti_globalfifo is set to zero\n");
- break;
- default:
- return -EINVAL;
- }
- return ;
- }
- static unsigned int conti_globalfifo_poll(struct file *filp, poll_table * wait)
- {
- unsigned int mask = ;
- struct conti_globalfifo_dev *dev = filp->private_data;
- mutex_lock(&dev->mutex);
- poll_wait(filp, &dev->r_wait, wait);
- poll_wait(filp, &dev->w_wait, wait);
- if (dev->current_len != ) {
- mask |= POLLIN | POLLRDNORM;
- }
- if (dev->current_len != conti_globalfifo_SIZE) {
- mask |= POLLOUT | POLLWRNORM;
- }
- mutex_unlock(&dev->mutex);
- return mask;
- }
- static ssize_t conti_globalfifo_read(struct file *filp, char __user *buf,
- size_t count, loff_t *ppos)
- {
- int ret;
- struct conti_globalfifo_dev *dev = filp->private_data;
- DECLARE_WAITQUEUE(wait, current);
- mutex_lock(&dev->mutex);
- add_wait_queue(&dev->r_wait, &wait);
- while (dev->current_len == ) {
- if (filp->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- goto out;
- }
- __set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&dev->mutex);
- schedule();
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- goto out2;
- }
- mutex_lock(&dev->mutex);
- }
- if (count > dev->current_len)
- count = dev->current_len;
- if (copy_to_user(buf, dev->mem, count)) {
- ret = -EFAULT;
- goto out;
- } else {
- memcpy(dev->mem, dev->mem + count, dev->current_len - count);
- dev->current_len -= count;
- printk(KERN_INFO "read %d bytes(s),current_len:%d\n", count,
- dev->current_len);
- wake_up_interruptible(&dev->w_wait);
- ret = count;
- }
- out:
- mutex_unlock(&dev->mutex);
- out2:
- remove_wait_queue(&dev->w_wait, &wait);
- set_current_state(TASK_RUNNING);
- return ret;
- }
- static ssize_t conti_globalfifo_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *ppos)
- {
- struct conti_globalfifo_dev *dev = filp->private_data;
- int ret;
- DECLARE_WAITQUEUE(wait, current);
- mutex_lock(&dev->mutex);
- add_wait_queue(&dev->w_wait, &wait);
- while (dev->current_len == conti_globalfifo_SIZE) {
- if (filp->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- goto out;
- }
- __set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&dev->mutex);
- schedule();
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- goto out2;
- }
- mutex_lock(&dev->mutex);
- }
- if (count > conti_globalfifo_SIZE - dev->current_len)
- count = conti_globalfifo_SIZE - dev->current_len;
- if (copy_from_user(dev->mem + dev->current_len, buf, count)) {
- ret = -EFAULT;
- goto out;
- } else {
- dev->current_len += count;
- printk(KERN_INFO "written %d bytes(s),current_len:%d\n", count,
- dev->current_len);
- wake_up_interruptible(&dev->r_wait);
- ret = count;
- }
- out:
- mutex_unlock(&dev->mutex);
- out2:
- remove_wait_queue(&dev->w_wait, &wait);
- set_current_state(TASK_RUNNING);
- return ret;
- }
- static const struct file_operations conti_globalfifo_fops = {
- .owner = THIS_MODULE,
- .read = conti_globalfifo_read,
- .write = conti_globalfifo_write,
- .unlocked_ioctl = conti_globalfifo_ioctl,
- .poll = conti_globalfifo_poll,
- .open = conti_globalfifo_open,
- .release = conti_globalfifo_release,
- };
- static void conti_globalfifo_setup_cdev(struct conti_globalfifo_dev *dev, int index)
- {
- int err, devno = MKDEV(conti_globalfifo_major, index);
- cdev_init(&dev->cdev, &conti_globalfifo_fops);
- dev->cdev.owner = THIS_MODULE;
- err = cdev_add(&dev->cdev, devno, );
- if (err)
- printk(KERN_NOTICE "Error %d adding conti_globalfifo%d", err, index);
- }
- static int __init conti_globalfifo_init(void)
- {
- int ret;
- dev_t devno = MKDEV(conti_globalfifo_major, );
- if (conti_globalfifo_major)
- ret = register_chrdev_region(devno, , "conti_globalfifo");
- else {
- ret = alloc_chrdev_region(&devno, , , "conti_globalfifo");
- conti_globalfifo_major = MAJOR(devno);
- }
- if (ret < )
- return ret;
- conti_globalfifo_devp = kzalloc(sizeof(struct conti_globalfifo_dev), GFP_KERNEL);
- if (!conti_globalfifo_devp) {
- ret = -ENOMEM;
- goto fail_malloc;
- }
- conti_globalfifo_setup_cdev(conti_globalfifo_devp, );
- mutex_init(&conti_globalfifo_devp->mutex);
- init_waitqueue_head(&conti_globalfifo_devp->r_wait);
- init_waitqueue_head(&conti_globalfifo_devp->w_wait);
- return ;
- fail_malloc:
- unregister_chrdev_region(devno, );
- return ret;
- }
- module_init(conti_globalfifo_init);
- static void __exit conti_globalfifo_exit(void)
- {
- cdev_del(&conti_globalfifo_devp->cdev);
- kfree(conti_globalfifo_devp);
- unregister_chrdev_region(MKDEV(conti_globalfifo_major, ), );
- }
- module_exit(conti_globalfifo_exit);
- MODULE_AUTHOR(" <Hemingway <weizhen.diao@conti.engineering.com>>");
- MODULE_LICENSE("GPL v2");
blocking and unblocking mechanism for linux drivern code的更多相关文章
- linux source code search
https://elixir.bootlin.com/linux/latest/source/fs/eventpoll.c#L1120
- The Select mechanism in linux for block mechanism
Today, some one mention theknowledge of Select Mechanism. It's better to konw something about it ! O ...
- Whats meaning of “EXPORT_SYMBOL” in Linux kernel code?
EXPORT_SYMBOL的作用是什么? EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一 ...
- [linux]安装code::blocks
1.安装基本编译环境 $sudo apt-get install build-essential $sudo apt-get install gdb 2.安装codeblock $sudo apt-g ...
- [转] KVM Internals, code and more
KVM Kernel-based Virtual Machine Internals, code and more http://slides.com/braoru/kvm#/ What behind ...
- linux内核设计模式
原文来自:http://lwn.net/Articles/336224/ 选择感兴趣内容简单翻译了下: 在内核社区一直以来的兴趣是保证质量.我们需要保证和改善质量是显而易见的.但是如何做到却不是那么简 ...
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
- Process Kill Technology && Process Protection Against In Linux
目录 . 引言 . Kill Process By Kill Command && SIGNAL . Kill Process By Resource Limits . Kill Pr ...
- 【转载】关于Embedded Linux启动的经典问题
转载自:http://linux.chinaunix.net/techdoc/install/2009/04/13/1107608.shtml 发信人: armlinux (armlinux), 信区 ...
随机推荐
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
- 在传统.NET Framework 上运行ASP.NET Core项目
新的项目我们想用ASP.NET Core来开发,但是苦于我们历史的遗产很多,比如<使用 JavaScriptService 在.NET Core 里实现DES加密算法>,我们要估计等到.N ...
- JavaScript性能优化
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...
- Dapper.Contrib:GetAsync<T> only supports an entity with a [Key] or an [ExplicitKey] property
异常处理:http://www.cnblogs.com/dunitian/p/4523006.html#dapper 原来Model是这样滴 修改后是这样滴 注意点:Model里面的Table和Key ...
- HTML5 语义元素(二)文本内容
上一篇介绍的是关于页面结构方面的语义元素,本篇介绍文本内容方面,包含:<bdi>.<details>.<summary>.<mark>.<outp ...
- Velocity笔记--使用Velocity获取动态Web项目名的问题
以前使用jsp开发的时候,可以通过request很轻松的获取到根项目名,现在换到使用velocity渲染视图,因为已经不依赖servlet,request等一些类的环境,而Web项目的根项目名又不是写 ...
- C++随笔:.NET CoreCLR之corleCLR核心探索之coreconsole(1)
一看这个标题,是不去取名有点绕呢?或者是,还有些问题?报告LZ...你的标题取得有问题,是个病句!↖(^ω^)↗!!!先不要急,其实我今天带给大家的就是CoreCLR中的coreclr.其中它是在名字 ...
- H3 BPM引擎API接口
引擎API接口通过 Engine 对象进行访问,这个是唯一入口. 示例1:获取组织机构对象 this.Engine.Organization.GetUnit("组织ID"); 示例 ...
- Android—万能ListView适配器
ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义. 最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家. 首先有一个自定义的 ...
- docker4dotnet #4 使用Azure云存储构建高速 Docker registry
使用Docker来构建应用程序最常见的操作就是 docker run 或者 docker pull了,但是由于众所周知的原因,在国内想要高速稳定的获取docker hub上面的资源并不是件容易的事情, ...