Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志__借我你的一生_的博客-程序员秘密

技术标签: 阻塞设备驱动  Linux  Linux Device Driver  

阻塞:

          在设计简单字符驱动程序时,要注意一个重要问题.

          当一个设备无法立刻满足用户的读写请求时应当如何处理?

          例如:调用 read 时没有数据可读,但以后可能会有;

          或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据.

          应用程序通常不关心这种问题,应用程序只是调用 read 或 write 并得到返回值.

          驱动程序应当 ( 缺省地 ) 阻塞进程使它进入睡眠直到请求可以得到满足.

阻塞操作:

          是指在执行设备操作时,若不能获得资源挂起进程直到满足可操作的条件后进行操作

          被挂起的进程进入睡眠状态,被从调度器的运行队列移走,直到等待的条件被满足.

非阻塞操作:

          进程不能进行设备操作时并不挂起,他或者放弃,或者不停的查询,直到可以进行操作为止.


阻塞方式-read- 实现:

          在阻塞型驱动程序中,read 实现方式如下:

          如果进程调用 read ,但设备 没有数据 数据不足进程阻塞.

          当新数据到达后,唤醒被阻塞进程.


阻塞方式-write- 实现:

          在阻塞型驱动程序中,write 实现方式如下:
          如果进程调用了 write ,但设备 没有足够的空间供其写入数据进程阻塞.
          当设备中的数据被读走后,缓冲区中 空出部分空间,则 唤醒进程.

非阻塞方式的读写操作:

          阻塞方式是文件读写操作的 默认方式,但是应用程序员可通过使用 O_NONBLOCK 标志来人为
          的 设置读写操作为 非阻塞方式 .( 该标志定义在 < linux/fcntl.h > 中,在打开文件时指定 ) .

          如果 设置了 O_NONBLOCK 标志,read 和 write 的行为是不同的 ,如果进程没有数据就绪时调用了 read ,
          或者在缓冲区没有空间时调用了 write ,系统只是 简单的返回 -EAGAIN,而 不会阻塞进程.

实例 --- 读阻塞的实现:

          
          

用 while 是因为可能别的信号唤醒了睡眠,我们要通过while 重新检测是否真有数据了....


          


实例 --- 按键驱动阻塞实现:

1,在 open 函数 查看看是 阻塞方式 还是 非阻塞方式:

         file 结构体中含有 f_flags 标志位,看是 阻塞方式 还是 非阻塞方式:
          O_NONBLOCK 为 非阻塞方式
	if (file->f_flags & O_NONBLOCK)  /* 非 阻塞操作 */
	{
		if (down_trylock(&button_lock))   /* 无法获取信号量,down_trylock 立马返回 一个 非零值 */
			return -EBUSY;
	}
	else                             /* 阻塞操作 */
	{
		/* 获取信号量 */
		down(&button_lock);   /* 获取不到  睡眠 */
	}

2,在 read 函数中同样查看:

	if (file->f_flags & O_NONBLOCK)       /* 非 阻塞操作 */
	{
		if (!ev_press)                 /* ev_press 为 1 表示有按键按下,为 0 if 成立 ,没有按键按下, */
			return -EAGAIN;        /* 返回 -EAGAIN 让再次来执行 */
	}
	else                                   /* 阻塞操作 */
	{
		/* 如果没有按键动作, 休眠 */
		wait_event_interruptible(button_waitq, ev_press);
	}

3,应用程序中:

1,以阻塞方式运行:

后台执行应用程序,进程处于睡眠状态,按下按键,立马打印按键号;
int main(int argc, char **argv)
{
	unsigned char key_val;
	int Oflags;
                                                   
	fd = open("/dev/buttons", O_RDWR );
	if (fd < 0)
	{
		printf("can't open!\n");
		return -1;
	}

	while (1)
	{
		read(fd, &key_val, 1);
		printf("key_val: 0x%x\n", key_val);
	}
	
	return 0;
}


2,以非阻塞方式运行:

open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;
后台执行应用程序:
int main(int argc, char **argv)
{
	unsigned char key_val;
	int ret;
	int Oflags;

	fd = open("/dev/buttons", O_RDWR | O_NONBLOCK);
	if (fd < 0)
	{
		printf("can't open!\n");
		return -1;
	}

	while (1)
	{
		ret = read(fd, &key_val, 1);
		printf("key_val: 0x%x, ret = %d\n", key_val, ret);
		sleep(5);
	}
	
	return 0;
}

非阻塞方式,没有按键值按下,程序立马返回;
read 返回值 为 -1;











版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yikai2009/article/details/8653697

智能推荐

SpringBoot项目搭建集成_voaycc的博客-程序员秘密_tomcat配置redis

1、如何创建SpringBoot项目方式一: 采用IDEA 自带的插件创建 或者 使用eclipse的Spring Tool Suite (STS) 插件创建;方式二:直接使用 Maven 创建项目的方式创建,然后手动添加依赖;(无网络的情况)2、认识Springboot项目结构及Maven依赖也是一个标准的maven结构,多了一个前端模板技术的static和template文件夹;3、SpringBoot项目使用JSP在Spring boot中使用jsp,按如下步骤进行:1、在pom.x

wxwidget onpaint_benny5609的博客-程序员秘密

1.  //  wxWidgets documentation: Note that In a paint event handler,    // the application must *always* create a wxPaintDC object, even    // if you do not use it. Otherwise, under MS Windows,

SSD对工件裂纹进行检测_MIge_的博客-程序员秘密_ssd裂缝检测

SSD深度学习模型对工件裂纹进行检测一、介绍本博文主要介绍实现通过SSD物体检测方式实现工件裂纹检测。裂纹图像如下所示:二、关于SSD算法具体算法不再阐述,详细请参考:https://blog.csdn.net/u013989576/article/details/73439202https://blog.csdn.net/xiaohu2022/article/details/79833786https://www.sohu.com/a/168738025_717210三、训

C++11右值引用的用法_XHumble的博客-程序员秘密

什么是右值引用C++98提出引用,引用就是起别名,引用变量和被引用实体公用一块内存空间,C++11新提出了右值引用这一概念,右值引用也是起别名,只是它只能对右值引用区别引用和右值引用引用的表现形式:T&amp; REF = 实体; T&amp;&amp; REF = 右值;什么是右值左值与右值是C语言中的概念,但C标准并没有给出严格的区分方式,一般认为:可以放在=左边的,或者能 够取地址的称为左值,只能放在=右边的,或者不能取地址的称为右值,但是也不一定完全正确。 ...

[Qt] Mask 蒙版_dgmfu28224的博客-程序员秘密

[Qt] Mask 蒙版Mask能够覆盖在其他的widget上面,实现一些动态图片的加载效果。下面给出代码。mask.h#ifndef MASK_HJ#define MASK_HJ#include &lt;QWidget&gt;#include &lt;QStyleOption&gt;#include &lt;QPainter&gt;#include &lt;QLabe...

关于马尔科夫随机场MRF的思考_Quebradawill的博客-程序员秘密

Markov Random Fields(MRF)是undirected graph的概率表示,下面说说它在computer vision中的应用。MRF应用在视觉中,相当于一个Labeling问题,更具体点,是通过MAP inference来确定图中每个节点的label。MRF相比其他方法的优势是:1)提供了一种principled method来

随便推点

High Efficiency_seclu的博客-程序员秘密

In the past two hours, I got some inspiration. Comparing with my English teacher Chengming Lis completing  more than harf of the text, I finished reading the whole text and harf of further reading wh

Python: jupyter notebook配置初始目录_Eswai的博客-程序员秘密

Python: jupyter notebook配置初始目录进入控制台 > jupyter notebook –generate-config生成配置文件,默认路径为~\.jupyter\jupyter_notebook_config.py修改配置文件查找c.NotebookApp.notebook_dir项,输入路径,注意去掉最前面的注释符号#

永久激活(破解) IntelliJ IDEA 2018.2_0945v1的博客-程序员秘密

1、去官网下载并安装 idea地址:https://www.jetbrains.com/idea/download文件有点大,耐心等待一会儿。2、下载破解(crack) jar 包地址http://idea.lanyus.com/jar/JetbrainsCrack-2.7-release-str.jar如果失效,去下面这个网站http://idea.lanyus.com...

Java Web笔记_巨兔12306的博客-程序员秘密

这里整理的是在编写JavaWeb时会出现的一些错误,以及解决方案。期间也会借鉴一些百度,CSDN等网站的知识,不妥之处还请见谅!同时呢,我也会在接下来的学习中不断完善整理出更多的问题和解决方案。                                                                                               

java多线程买票实例_司天宏的博客-程序员秘密

3个窗口同时买票** 同步:* 1:同步代码块* synchronized(锁对象(唯一)){** …需要被同步的代码** }* 2:同步方法* 修饰符 synchronized 返回值 方法名(){* …需要被同步的代码* }** 3:Lock锁* lock.lock() 上锁* …需要被同步的代码* ...

<day001>存储到Mysql、mongoDB数据库+简单的Ajax请求+os模块+进程池+MD5_weixin_30410119的博客-程序员秘密

任务1:记住如何存储到Mysql、mongoDB数据库'''存储到Mysql'''import pymysql.cursorsclass QuotePipeline(object): def __init__(self): self.connect = pymysql.connect( host='localhost', user='roo...

推荐文章

热门文章

相关标签