转自: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 为 非阻塞方式
  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 函数中同样查看:

  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,以阻塞方式运行:

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

2,以非阻塞方式运行:

open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;
后台执行应用程序:
  1. int main(int argc, char **argv)
  2. {
  3. unsigned char key_val;
  4. int ret;
  5. int Oflags;
  6. fd = open("/dev/buttons", O_RDWR | O_NONBLOCK);
  7. if (fd < 0)
  8. {
  9. printf("can't open!\n");
  10. return -1;
  11. }
  12. while (1)
  13. {
  14. ret = read(fd, &key_val, 1);
  15. printf("key_val: 0x%x, ret = %d\n", key_val, ret);
  16. sleep(5);
  17. }
  18. return 0;
  19. }
 

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

Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志【转】的更多相关文章

  1. 【转】linux设备驱动程序之简单字符设备驱动

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...

  2. Linux 驱动框架---cdev字符设备驱动和misc杂项设备驱动

    字符设备 Linux中设备常见分类是字符设备,块设备.网络设备,其中字符设备也是Linux驱动中最常用的设备类型.因此开发Linux设备驱动肯定是要先学习一下字符设备的抽象的.在内核中使用struct ...

  3. 驱动开发--【字符设备、块设备简介】【sky原创】

    驱动开发   字符设备,块设备,网络设备   字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问   EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是 ...

  4. Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程

    /*********************************************************************************** * * 字符设备驱动基本操作及 ...

  5. LCD驱动分析(一)字符设备驱动框架分析

    参考:S3C2440 LCD驱动(FrameBuffer)实例开发<一>   S3C2440 LCD驱动(FrameBuffer)实例开发<二> LCD驱动也是字符设备驱动,也 ...

  6. Linux驱动开发2——字符设备驱动

    1.申请设备号 #include <linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char ...

  7. 【linux驱动笔记】字符设备驱动相关数据结构与算法

    欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...

  8. 初入android驱动开发之字符设备(一)

    大学毕业,初入公司,招进去的是android驱动开发工程师的岗位,那时候刚进去,首先学到的就是如何搭建kernel.android的编译环境,然后就是了解如何刷设备以及一些最基本的工具.如adb.fa ...

  9. Linux驱动开发之字符设备模板

    /***************************** ** 驱动程序模板* 版本:V1* 使用方法(末行模式下):* :%s/xxx/"你的驱动名称"/g********* ...

随机推荐

  1. git rebase -i

    git rebase -i 作用: 合并提交 示例: 如图所示: 原因: 出现了两个第十一章的提交信息, 其实提交内容是一样的, 但是提交概述不一样. 这就让我很不爽. 我想把两次的概述信息合并为一个 ...

  2. spark中的RDD以及DAG

    今天,我们就先聊一下spark中的DAG以及RDD的相关的内容 1.DAG:有向无环图:有方向,无闭环,代表着数据的流向,这个DAG的边界则是Action方法的执行 2.如何将DAG切分stage,s ...

  3. 3 web框架

    web框架 Web框架(Web framework)是一种开发框架,用来支持动态网站.网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法. ...

  4. hihocoder1014 : Trie树

    #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助, ...

  5. Go实现try-catch-finally机制

    前言 许多主流语言诸如:Java.Python都实现了try-catch-finally机制,而Go处理错误的方式却与前两种语言不同.关于Go处理异常的方式是好是坏仁者见仁智者见智,笔者还是更喜欢tr ...

  6. 剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列

    剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列2013-11-23 03:16 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出 ...

  7. Lazarus教程 中文版后续给出

    市面上有介绍Delphi的书籍(近来Delphi的书也是越来越少了),但没有一本系统的介绍Lazarus的书,这本书是网上的仅有的一本Lazarus教程,目前全部是英文,不过我已经着手开始翻译,争取尽 ...

  8. 【APUE】Chapter8 Process Control

    这章的内容比较多.按照小节序号来组织笔记的结构:再结合函数的示例带代码标注出来需要注意的地方. 下面的内容只是个人看书时思考内容的总结,并不能代替看书(毕竟APUE是一本大多数人公认的UNIX圣经). ...

  9. 解决Navicat for MySQL 连接 Mysql 8.0.11 出现1251- Client does not support authentication protocol 错误

    安装MySQL8.0之后,使用Navicat连接数据库,报1251错误. 上网搜索解决方案,网上说出现这种情况的原因是:mysql8 之前的版本中加密规则是mysql_native_password, ...

  10. 新建git仓库--留

    1.git config 配置配置息,查看配置信息