1. 程式人生 > >Linux 設備驅動--- 阻塞型字符設備驅動 --- O_NONBLOCK --- 非阻塞標誌【轉】

Linux 設備驅動--- 阻塞型字符設備驅動 --- O_NONBLOCK --- 非阻塞標誌【轉】

ble 進程阻塞 例如 缺省 tracking 問題 href 字符驅動 調度

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

目錄(?)[-]

  1. 阻塞
    1. 阻塞操作
    2. 非阻塞操作
  2. 阻塞方式-read- 實現
  3. 阻塞方式-write- 實現
  4. 非阻塞方式的讀寫操作
  5. 實例 --- 讀阻塞的實現
  6. 實例 --- 按鍵驅動阻塞實現
    1. 1在 open 函數 查看看是 阻塞方式 還是 非阻塞方式
    2. 2在 read 函數中同樣查看
    3. 3應用程序中
      1. 1以阻塞方式運行
      2. 2以非阻塞方式運行

阻塞:

在設計簡單字符驅動程序時,要註意一個重要問題.

當一個設備無法立刻滿足用戶的讀寫請求時應當如何處理?

例如:調用 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. 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 非阻塞; 後臺執行應用程序: [cpp] view plain copy
  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 --- 非阻塞標誌【轉】