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;

相關文章
相關標籤/搜索