概念:


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. JavaScript Date对象

    本篇主要介绍 Date 日期和时间对象的操作. 目录 1. 介绍:阐述 Date 对象. 2. 构造函数:介绍 Date 对象的构造函数new Date()几种方式. 3. 实例方法:介绍 Date ...

  2. Python标准模块--ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  3. OVS local network 连通性分析 - 每天5分钟玩转 OpenStack(132)

    前面已经创建了两个 OVS local network,今天详细分析它们之间的连通性. launch 新的 instance "cirros-vm3",网络选择 second_lo ...

  4. WebApi接口 - 响应输出xml和json

    格式化数据这东西,主要看需要的运用场景,今天和大家分享的是webapi格式化数据,这里面的例子主要是输出json和xml的格式数据,测试用例很接近实际常用情况:希望大家喜欢,也希望各位多多扫码支持和点 ...

  5. 现代3D图形编程学习-基础简介(3)-什么是opengl (译)

    本书系列 现代3D图形编程学习 OpenGL是什么 在我们编写openGL程序之前,我们首先需要知道什么是OpenGL. 将OpenGL作为一个API OpenGL 通常被认为是应用程序接口(API) ...

  6. golang语言构造函数

    1.构造函数定义 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个 ...

  7. Android—自定义开关按钮实现

    我们在应用中经常看到一些选择开关状态的配置文件,做项目的时候用的是android的Switch控件,但是感觉好丑的样子………… 个人认为还是自定义的比较好,先上个效果图:

  8. listview下拉刷新和上拉加载更多的多种实现方案

    listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明. 方案一:添加头布局和脚布局        android系统为listview提供了addfootview ...

  9. 递归实现n(经典的8皇后问题)皇后的问题

    问题描述:八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后, 使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上 ...

  10. 机器指令翻译成 JavaScript —— No.5 指令变化

    上一篇,我们通过内置解释器的方案,解决任意跳转的问题.同时,也提到另一个问题:如果指令发生变化,又该如何应对. 指令自改 如果指令加载到 RAM 中,那就和普通数据一样,也是可以随意修改的.然而,对应 ...