概念:


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. “.Net 社区虚拟大会”(dotnetConf) 2016 Day 3 Keynote: Scott Hanselman

    美国时间 6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开,美国时间6.9 是第三天, Scott Hanselman 做Keynote.今天主题围绕的是.NET ...

  2. 05.LoT.UI 前后台通用框架分解系列之——漂亮的时间选择器

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  3. Android 工具-adb

    Android 工具-adb 版权声明:本文为博主原创文章,未经博主允许不得转载. Android 开发中, adb 是开发者经常使用的工具,是 Android 开发者必须掌握的. Android D ...

  4. C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程

    前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...

  5. 在你的ASP.NET MVC中使用查找功能

    在程序中,使用查找功能是少之不了.今天在ASP.NET环境下演示一回. 在cshtml视图中,有三个文本框,让用户输入关键词,然后点击最右连的“搜索”铵钮,如果有结果将显示于下面. Html: 表格放 ...

  6. ASP.Net MVC——使用 ITextSharp 完美解决HTML转PDF(中文也可以)

    前言: 最近在做老师交代的一个在线写实验报告的小项目中,有这么个需求:把学生提交的实验报告(HTML形式)直接转成PDF,方便下载和打印. 以前都是直接用rdlc报表实现的,可这次牵扯到图片,并且更为 ...

  7. NGINX引入线程池 性能提升9倍

    1. 引言 正如我们所知,NGINX采用了异步.事件驱动的方法来处理连接.这种处理方式无需(像使用传统架构的服务器一样)为每个请求创建额外的专用进程或者线程,而是在一个工作进程中处理多个连接和请求.为 ...

  8. ORACLE从共享池删除指定SQL的执行计划

    Oracle 11g在DBMS_SHARED_POOL包中引入了一个名为PURGE的新存储过程,用于从对象库缓存中刷新特定对象,例如游标,包,序列,触发器等.也就是说可以删除.清理特定SQL的执行计划 ...

  9. [PHP源码阅读]empty和isset函数

    近日被问到PHP中empty和isset函数时怎么判断变量的,刚开始我是一脸懵逼的,因为我自己也只是一知半解,为了弄懂其真正的原理,赶紧翻开源码研究研究.经过分析可发现两个函数调用的都是同一个函数,因 ...

  10. 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记

    前言 网购已经不再是现在的时髦,而变成了我们每天的日常生活.上网已经和买买买紧密地联系在了一起,成为了我们的人生信条.而逛街一词,越来越多地变成了一种情怀.有时候我们去逛街,要么是为了打发时间,要么是 ...