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

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

          当一个设备没法马上知足用户的读写请求时应当如何处理?程序员

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

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

          应用程序一般不关心这种问题,应用程序只是调用 read 或 write 并获得返回值.队列

          驱动程序应当 ( 缺省地 ) 阻塞进程,使它进入睡眠,直到请求能够获得知足.进程

阻塞操做:
          是指在执行设备操做时,若不能得到资源则挂起进程,直到知足可操做的条件后进行操做,资源

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

非阻塞操做:
          进程不能进行设备操做时并不挂起,他或者放弃,或者不停的查询,直到能够进行操做为止.event

 

阻塞方式-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;

相关文章
相关标签/搜索