Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志【转】

简介: 转自:http://blog.csdn.net/yikai2009/article/details/8653697 版权声明:本文为博主原创文章,未经博主允许不得转载。   目录(?)[-] 阻塞 阻塞操作 非阻塞操作 阻塞方式-read- 实现 阻塞方式-writ...

转自:http://blog.csdn.net/yikai2009/article/details/8653697

 
 

阻塞:

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

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

          例如:调用 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 为 非阻塞方式
[cpp]  view plain  copy
 
  1. if (file->f_flags & O_NONBLOCK)  /* 非 阻塞操作 */  
  2. {  
  3.     if (down_trylock(&button_lock))   /* 无法获取信号量,down_trylock 立马返回 一个 非零值 */  
  4.         return -EBUSY;  
  5. }  
  6. else                             /* 阻塞操作 */  
  7. {  
  8.     /* 获取信号量 */  
  9.     down(&button_lock);   /* 获取不到  睡眠 */  
  10. }  

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

[cpp]  view plain  copy
 
  1. if (file->f_flags & O_NONBLOCK)       /* 非 阻塞操作 */  
  2. {  
  3.     if (!ev_press)                 /* ev_press 为 1 表示有按键按下,为 0 if 成立 ,没有按键按下, */  
  4.         return -EAGAIN;        /* 返回 -EAGAIN 让再次来执行 */  
  5. }  
  6. else                                   /* 阻塞操作 */  
  7. {  
  8.     /* 如果没有按键动作, 休眠 */  
  9.     wait_event_interruptible(button_waitq, ev_press);  
  10. }  

3,应用程序中:

1,以阻塞方式运行:

后台执行应用程序,进程处于睡眠状态,按下按键,立马打印按键号;
[cpp]  view plain  copy
 
  1. int main(int argc, char **argv)  
  2. {  
  3.     unsigned char key_val;  
  4.     int Oflags;  
  5.                                                      
  6.     fd = open("/dev/buttons", O_RDWR );  
  7.     if (fd < 0)  
  8.     {  
  9.         printf("can't open!\n");  
  10.         return -1;  
  11.     }  
  12.   
  13.     while (1)  
  14.     {  
  15.         read(fd, &key_val, 1);  
  16.         printf("key_val: 0x%x\n", key_val);  
  17.     }  
  18.       
  19.     return 0;  
  20. }  


2,以非阻塞方式运行:

open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;
后台执行应用程序:
[cpp]  view plain  copy
 
  1. int main(int argc, char **argv)  
  2. {  
  3.     unsigned char key_val;  
  4.     int ret;  
  5.     int Oflags;  
  6.   
  7.     fd = open("/dev/buttons", O_RDWR | O_NONBLOCK);  
  8.     if (fd < 0)  
  9.     {  
  10.         printf("can't open!\n");  
  11.         return -1;  
  12.     }  
  13.   
  14.     while (1)  
  15.     {  
  16.         ret = read(fd, &key_val, 1);  
  17.         printf("key_val: 0x%x, ret = %d\n", key_val, ret);  
  18.         sleep(5);  
  19.     }  
  20.       
  21.     return 0;  
  22. }  
 
非阻塞方式,没有按键值按下,程序立马返回;
read 返回值 为 -1;
【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
|
1月前
|
安全 Linux 网络虚拟化
Linux网络名称空间和Veth虚拟设备的关系
在讨论Linux网络名称空间和veth(虚拟以太网对)之间的关系时,我们必须从Linux网络虚拟化的核心概念开始。Linux网络名称空间和veth是Linux网络虚拟化和容器化技术的重要组成部分,它们之间的关系密不可分,对于构建隔离、高效的网络环境至关重要。😊
|
1月前
|
Cloud Native Linux 网络虚拟化
深入理解Linux veth虚拟网络设备:原理、应用与在容器化架构中的重要性
在Linux网络虚拟化领域,虚拟以太网设备(veth)扮演着至关重要的角色🌐。veth是一种特殊类型的网络设备,它在Linux内核中以成对的形式存在,允许两个网络命名空间之间的通信🔗。这篇文章将从多个维度深入分析veth的概念、作用、重要性,以及在容器和云原生环境中的应用📚。
深入理解Linux veth虚拟网络设备:原理、应用与在容器化架构中的重要性
|
22小时前
|
网络协议 Shell Linux
LabVIEW 在NI Linux实时设备上访问Shell
LabVIEW 在NI Linux实时设备上访问Shell
|
4天前
|
Linux
linux驱动层输出dev_dbg打印信息
linux驱动层输出dev_dbg打印信息
8 0
|
12天前
|
存储 监控 Linux
【专栏】在 Linux 中,了解已安装驱动器是系统管理的关键
【4月更文挑战第28天】在 Linux 中,了解已安装驱动器是系统管理的关键。本文介绍了三种方法:1) 使用 `lsblk` 命令显示设备名、大小和类型;2) `fdisk -l` 命令提供详细分区信息;3) `gnome-disks` 等系统管理工具展示驱动器信息。此外,还讨论了驱动器类型识别、挂载点概念及其应用。通过这些方法,用户能有效地监控和管理 Linux 系统中的驱动器。
|
20天前
|
存储 Linux
如何查看Linux设备的硬盘信息?
【4月更文挑战第12天】在Linux系统中,查看硬盘信息的常用命令。
26 4
|
25天前
|
Linux Go
Linux命令Top 100驱动人生! 面试必备
探索Linux命令不再迷茫!本文分10部分详解20个基础命令,带你由浅入深掌握文件、目录管理和文本处理。 [1]: <https://cloud.tencent.com/developer/article/2396114> [2]: <https://pan.quark.cn/s/865a0bbd5720> [3]: <https://yv4kfv1n3j.feishu.cn/docx/MRyxdaqz8ow5RjxyL1ucrvOYnnH>
76 0
|
1月前
|
监控 Linux 网络虚拟化
从入门到精通:系统性学习Linux虚拟网络设备的全面指南
学习一个从未接触过的Linux虚拟网络设备是一个分阶段的过程,从最初的认识到最后的精通,需要系统性和逐步深入的学习策略。以下是一个全面的指南📚,旨在帮助初学者通过多角度分析🔍,一步一步地学习和掌握新的Linux虚拟网络设备。
从入门到精通:系统性学习Linux虚拟网络设备的全面指南
|
1天前
|
安全 Linux 测试技术
|
1天前
|
安全 Linux Windows
Linux中Shutdown命令使用介绍
Linux中Shutdown命令使用介绍