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


    转自: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! ");  
    10.         return -1;  
    11.     }  
    12.   
    13.     while (1)  
    14.     {  
    15.         read(fd, &key_val, 1);  
    16.         printf("key_val: 0x%x ", 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! ");  
    11.         return -1;  
    12.     }  
    13.   
    14.     while (1)  
    15.     {  
    16.         ret = read(fd, &key_val, 1);  
    17.         printf("key_val: 0x%x, ret = %d ", key_val, ret);  
    18.         sleep(5);  
    19.     }  
    20.       
    21.     return 0;  
    22. }  
     
    非阻塞方式,没有按键值按下,程序立马返回;
    read 返回值 为 -1;
  • 相关阅读:
    【数据分享】学生受欢迎程度评价数据集
    拓端tecdat|Matlab用Copula模型进行蒙特卡洛(Monte Carlo)模拟和拟合股票收益数据分析
    聊一聊并行文件系统的客户端优化之道
    从Redis7.0发布看Redis的过去与未来
    辛辛苦苦原创的网站,被抄袭了怎么办?
    常用Yum镜像源
    Wget/httrack 爬取整站资源
    Maven:第二章:去中央仓库下载包到本地引入依赖到项目中
    消息队列:第五章:RabbitMQ的使用
    我的分享:第一章:SpringBoot专栏
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/6985362.html
Copyright © 2020-2023  润新知