概念:


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. ASP.NET Core 中文文档 第四章 MVC(4.3)过滤器

    原文:Filters 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:何镇汐 ASP.NET MVC 过滤器 可在执行管道的前后特定阶段执行代码.过滤器可以配置为全局有效.仅对控 ...

  2. Ajax使用WCF实现小票pos机打印源码

    通过ajax跨域方式调用WCF服务,实现小票pos机的打印,源码提供web方式,客户端方式测试,服务驻留右侧底部任务栏,可控制服务开启暂停,用户可自定义小票打印模板,配合零售录入. qq  22945 ...

  3. JSP 标准标签库(JSTL)

    JSP 标准标签库(JSTL) JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签, ...

  4. Lind.DDD.LindAspects方法拦截的介绍

    回到目录 什么是LindAspects 之前写了关于Aspects的文章<Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP>,今天主要在设计思想上进 ...

  5. JavaScript学习笔记(一)——延迟对象、跨域、模板引擎、弹出层、AJAX示例

    一.AJAX示例 AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML) 是指一种创建交互式网页应用的开发技术.改善用户体验,实现无刷新效 ...

  6. x01.os.23: 制作 linux LiveCD

    1.首先运行如下命令  sudo apt-get install wget bc build-essential gawk genisoimage 2.下载如下资源,make all 即可 http: ...

  7. js月份,日期加一天

    js没有直接可以用的函数,所以只能自己写,其中需要涉及到每个月天数的判断,如果是2月份的话,还要涉及到闰年的判断 var addDate = { //日期,在原有日期基础上,增加days天数,默认增加 ...

  8. Akka.NET v1.0 已发布,支持Mono

    Akka.NET 是Java/Scala 流行框架Akka的一个 .NET 开源移植.可用于构建高并发,分布式和容错事件驱动的应用在 .NET 和 Mono 平台之上.Akka.NET 经过一年多的努 ...

  9. 【腾讯优测干货分享】安卓专项测试之GPU测试探索

    本文来自于Dev Club 开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ffdc0569a1191bce8a63 作者:章未哲——腾讯SNG质 ...

  10. Angular2学习笔记——NgModule

    在Angular2中一个Module指的是使用@NgModule修饰的class.@NgModule利用一个元数据对象来告诉Angular如何去编译和运行代码.一个模块内部可以包含组件.指令.管道,并 ...