概念:


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的更多相关文章

  1. linux source code search

    https://elixir.bootlin.com/linux/latest/source/fs/eventpoll.c#L1120

  2. 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 ...

  3. Whats meaning of “EXPORT_SYMBOL” in Linux kernel code?

    EXPORT_SYMBOL的作用是什么? EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一 ...

  4. [linux]安装code::blocks

    1.安装基本编译环境 $sudo apt-get install build-essential $sudo apt-get install gdb 2.安装codeblock $sudo apt-g ...

  5. [转] KVM Internals, code and more

    KVM Kernel-based Virtual Machine Internals, code and more http://slides.com/braoru/kvm#/ What behind ...

  6. linux内核设计模式

    原文来自:http://lwn.net/Articles/336224/ 选择感兴趣内容简单翻译了下: 在内核社区一直以来的兴趣是保证质量.我们需要保证和改善质量是显而易见的.但是如何做到却不是那么简 ...

  7. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  8. Process Kill Technology && Process Protection Against In Linux

    目录 . 引言 . Kill Process By Kill Command && SIGNAL . Kill Process By Resource Limits . Kill Pr ...

  9. 【转载】关于Embedded Linux启动的经典问题

    转载自:http://linux.chinaunix.net/techdoc/install/2009/04/13/1107608.shtml 发信人: armlinux (armlinux), 信区 ...

随机推荐

  1. 微软发布正式版SQL Server 2016

    微软于今天在SQL 官方博客上宣布 SQL Server 数据库软件的正式发布版本(GA),历时一年多,微软为该软件发布了多个公共预览版和候选版本,而今天最终版本终于上线了.在博客中,微软数据集团的企 ...

  2. 一看就懂的ReactJs入门教程-精华版

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...

  3. 在.Net中实现自己的简易AOP

    RealProxy基本代理类 RealProxy类提供代理的基本功能.这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理.这是我们AOP实现的主要依赖. 新建一 ...

  4. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  5. C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

    第一次接触HtmlAgilityPack是在5年前,一些意外,让我从技术部门临时调到销售部门,负责建立一些流程和寻找潜在客户,最后在阿里巴巴找到了很多客户信息,非常全面,刚开始是手动复制到Excel, ...

  6. 【原创经验分享】WCF之消息队列

    最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...

  7. Anders Hejlsberg 技术理想架构开发传奇

    Anders Hejlsberg(安德斯-海森博格) 坐在自己的办公室,双眼直直的盯着前方.他要做一个决定,决定自己未来的命运和理想.这是1996年一个普通的下午,几个小时前,他刚与比尔-盖茨结束了 ...

  8. 最好的.NET开源免费ZIP库DotNetZip(.NET组件介绍之三)

    在项目开发中,除了对数据的展示更多的就是对文件的相关操作,例如文件的创建和删除,以及文件的压缩和解压.文件压缩的好处有很多,主要就是在文件传输的方面,文件压缩的好处就不需要赘述,因为无论是开发者,还是 ...

  9. 《Ansible权威指南》笔记(2)——Inventory配置

    四.Inventory配置ansible通过Inventory来定义主机和组,使用时通过-i指定读取,默认/etc/ansible/hosts.可以存在多个Inventory,支持动态生成.1.定义主 ...

  10. Linux设备管理(二)_从cdev_add说起

    我在Linux字符设备驱动框架一文中已经简单的介绍了字符设备驱动的基本的编程框架,这里我们来探讨一下Linux内核(以4.8.5内核为例)是怎么管理字符设备的,即当我们获得了设备号,分配了cdev结构 ...