概念:


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. 微信企业号 获取AccessToken

    目录 1. AccessToken介绍 2. 示例代码 1. AccessToken介绍 1.1 什么是AccessToken AccessToken即访问凭证,业务服务器每次主动调用企业号接口时需要 ...

  2. 【.net 深呼吸】细说CodeDom(4):类型定义

    上一篇文章中说了命名空间,你猜猜接下来该说啥.是了,命名空间下面就是类型,知道了如何生成命名空间的定义代码,之后就该学会如何声明类型了. CLR的类型通常有这么几种:类.接口.结构.枚举.委托.是这么 ...

  3. 对抗假人 —— 前后端结合的 WAF

    前言 之前介绍了一些前后端结合的中间人攻击方案.由于 Web 程序的特殊性,前端脚本的参与能大幅弥补后端的不足,从而达到传统难以实现的效果. 攻防本为一体,既然能用于攻击,类似的思路同样也可用于防御. ...

  4. Python高手之路【四】python函数装饰器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

  5. 【Net跨平台第一步】逆天带你零基础Linux入门【更新完毕】

    部分讲义:(视频已删,后期以文档形式发布)

  6. HTML5 介绍

    本篇主要介绍HTML5规范的内容和页面上的架构变动. 目录 1. HTML5介绍 1.1 介绍 1.2 内容 1.3 浏览器支持情况 2. 创建HTML5页面 2.1 <!DOCTYPE> ...

  7. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  8. C++随笔:从Hello World 探秘CoreCLR的内部(1)

    紧接着上次的问题,上次的问题其实很简单,就是HelloWorld.exe运行失败,而本文的目的,就是成功调试HelloWorld这个控制台应用程序. 通过我的寻找,其实是一个名为TryRun的文件出了 ...

  9. trigger事件模拟

    事件模拟trigger 在操作DOM元素中,大多数事件都是用户必须操作才会触发事件,但有时,需要模拟用户的操作,来达到效果. 需求:页面初始化时触发搜索事件并获取input控件值,并打印输出(效果图如 ...

  10. 【JavaScript】javascript中伪协议(javascript:)使用探讨

    javascript:这个特殊的协议类型声明了URL的主体是任意的javascript代码,它由javascript的解释器运行. 比如下面这个死链接: <a href="javasc ...