首頁>技術>

本文字數:2344,閱讀時長:4分鐘

1.適用場景

在前面引入中斷時,我們曾經舉過一個例子:

媽媽怎麼知道臥室裡小孩醒了?

時不時進房間看一下:查詢方式簡單,但是累進去房間陪小孩一起睡覺,小孩醒了會吵醒她:休眠-喚醒不累,但是媽媽幹不了活了媽媽要幹很多活,但是可以陪小孩睡一會,定個鬧鐘:poll方式要浪費點時間,但是可以繼續幹活。媽媽要麼是被小孩吵醒,要麼是被鬧鐘吵醒。媽媽在客廳幹活,小孩醒了他會自己走出房門告訴媽媽:非同步通知媽媽、小孩互不耽誤

使用休眠-喚醒的方式等待某個事件發生時,有一個缺點:等待的時間可能很久。我們可以加上一個超時時間,這時就可以使用poll機制。

APP不知道驅動程式中是否有資料,可以先呼叫poll函式查詢一下,poll函式可以傳入超時時間;APP進入核心態,呼叫到驅動程式的poll函式,如果有資料的話立刻返回;如果發現沒有資料時就休眠一段時間;當有資料時,比如當按下按鍵時,驅動程式的中斷服務程式被呼叫,它會記錄資料、喚醒APP;當超時時間到了之後,核心也會喚醒APP;APP根據poll函式的返回值就可以知道是否有資料,如果有資料就呼叫read得到資料2.使用流程

媽媽進入房間時,會先看小孩醒沒醒,鬧鐘響之後走出房間之前又會再看小孩醒沒醒。注意:看了2次小孩!POLL機制也是類似的,流程如下:

③ APP呼叫poll之後,進入核心態;④ 導致驅動程式的drv_poll被呼叫:注意,drv_poll要把自己這個執行緒掛入等待佇列wq中;假設不放入佇列裡,那以後發生中斷時,中斷服務程式去哪裡找到你嘛?drv_poll還會判斷一下:有沒有資料啊?返回這個狀態。⑤ 假設當前沒有資料,則休眠一會;⑥ 在休眠過程中,按下了按鍵,發生了中斷:在中斷服務程式裡記錄了按鍵值,並且從wq中把執行緒喚醒了。⑦ 執行緒從休眠中被喚醒,繼續執行for迴圈,再次呼叫drv_poll:drv_poll返回資料狀態⑧ 哦,你有資料,那從核心態返回到應用態吧⑨ APP呼叫read函式讀資料如果一直沒有資料,呼叫流程也是類似的,重點從③開始看,如下:③ APP呼叫poll之後,進入核心態;④ 導致驅動程式的drv_poll被呼叫:注意,drv_poll要把自己這個執行緒掛入等待佇列wq中;假設不放入佇列裡,那以後發生中斷時,中斷服務程式去哪裡找到你嘛?drv_poll還會判斷一下:有沒有資料啊?返回這個狀態。⑤ 假設當前沒有資料,則休眠一會;⑥ 在休眠過程中,一直沒有按下了按鍵,超時時間到:核心把這個執行緒喚醒;⑦ 執行緒從休眠中被喚醒,繼續執行for迴圈,再次呼叫drv_poll:drv_poll返回資料狀態⑧ 哦,你還是沒有資料,但是超時時間到了,那從核心態返回到應用態吧⑨ APP不能呼叫read函式讀資料

注意幾點:

drv_poll要把執行緒掛入佇列wq,但是並不是在drv_poll中進入休眠,而是在呼叫drv_poll之後休眠drv_poll要返回資料狀態APP呼叫一次poll,有可能會導致drv_poll被呼叫2次執行緒被喚醒的原因有2:中斷髮生了去佇列wq中把它喚醒,超時時間到了核心把它喚醒APP要判斷poll返回的原因:有資料,還是超時。有資料時再去呼叫read函式。3. 驅動程式設計

使用poll機制時,驅動程式的核心就是提供對應的drv_poll函式。在drv_poll函式中要做2件事:

把當前執行緒掛入佇列wq:poll_waitAPP呼叫一次poll,可能導致drv_poll被呼叫2次,但是我們並不需要把當前執行緒掛入佇列2次。可以使用核心的函式poll_wait把執行緒掛入佇列,如果執行緒已經在佇列裡了,它就不會再次掛入。返回裝置狀態:APP呼叫poll函式時,有可能是查詢“有沒有資料可以讀”:POLLIN,也有可能是查詢“你有沒有空間給我寫資料”:POLLOUT。所以drv_poll要返回自己的當前狀態:(POLLIN | POLLRDNORM) 或 (POLLOUT | POLLWRNORM)。POLLRDNORM等同於POLLIN,為了相容某些APP把它們一起返回。POLLWRNORM等同於POLLOUT ,為了相容某些APP把它們一起返回。

APP呼叫poll後,很有可能會休眠。對應的,在按鍵驅動的中斷服務程式中,也要有喚醒操作。驅動程式中poll的程式碼如下:

static unsigned int gpio_key_drv_poll(struct file *fp, poll_table * wait){\tprintk("%s %s line %d\\n", __FILE__, __FUNCTION__, __LINE__);\tpoll_wait(fp, &gpio_key_wait, wait);\treturn is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;}
4 應用程式設計

注意:APP可以呼叫poll或select函式,這2個函式的作用是一樣的。poll/select函式可以監測多個檔案,可以監測多種事件:事件型別 說明POLLIN 有資料可讀POLLRDNORM 等同於POLLINPOLLRDBAND Priority band data can be read,有優先順序較較高的“band data”可讀Linux系統中很少使用這個事件POLLPRI 高優先順序資料可讀POLLOUT 可以寫資料POLLWRNORM 等同於POLLOUTPOLLWRBAND Priority data may be writtenPOLLERR 發生了錯誤POLLHUP 掛起POLLNVAL 無效的請求,一般是fd未open

47

Linux

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Docker Compose 容器編排實現應用的自動部署