非同步通知:
之前的三種讀取按鍵電平狀態的方法分別是:查詢法、中斷法、中斷+poll機制。
這三種方法都需要應用程式主動去讀取,我們可以進一步改進,
如果應用程式可以休眠或者做別的事情,當發生按鍵中斷時,驅動中的中斷服務函式來主動提醒應用程式去讀取就好了。
這個設想可以通過驅動程式給應用程式發訊號的方法來實現。
首先明確,目的?
當按鍵按下時,驅動程式去提醒應用程式讀取按鍵值。(即實現驅動和應用之間的非同步通知)
1.怎麼做?
使用訊號機制來實現,也就是發訊號。
2.誰發?
驅動程式發訊號。
3.怎麼發?
使用kill_fasync
4.發給誰?
發給應用程式。(應用程式事先要告訴驅動自己的pid)
5.收到後做什麼? 應用程式在訊號處理函式中處理要做的工作。
根據以上幾點來寫出支援非同步通知功能的驅動和應用程式。
當中斷發生時,進入中斷服務函式,將按鍵值記錄下來,然後喚醒程序,並且使用kill_fasync(&buttons_async, sigio, poll_in)給程序發訊號。
第乙個引數是乙個結構體,buttons_async結構體中顯然包含應用程式發給驅動的那個pid;第二個引數表示訊號的類別,sigio只是乙個數字29;
第三個引數表示原因,poll_in表示有資料等待讀取。
那麼在中斷發生之前,需要對buttons_async結構體進行初始化。
我們在驅動fasync函式中使用fasync_helper(fd, file, on, &buttons_async)函式來初始化buttons_async結構體。
這就是「誰發」和「怎麼發」。
接下來,「發給誰」。
當然是發給應用程式,那應用程式首先得把自己的pid告訴驅動,應用程式通過fcntl這個系統呼叫把程序id告訴驅動,fcntl(fd, f_setown, getpid());
oflags = fcntl(fd, f_getfl);
fcntl(fd, f_setfl, oflags | fasync); // 改變fasync標記,最終會呼叫到驅動的faync > fasync_helper:初始化/釋放buttons_async結構體
最後,「收到後做什麼」
應用程式處於休眠狀態,當驅動喚醒程序,並傳送訊號時,應用程式就會呼叫訊號處理函式,我們需要先呼叫signal函式來指定我們自己實現的訊號處理函式。
signal(sigio, my_signal_fun);
在my_signal_fun函式中使用read函式來讀取我們在中斷服務函式中記錄好的按鍵電平。
Linux非同步通知 fasync
要弄明白這個問題,我們得從最基本的原理開始。我們知道,驅動程式執行在核心空間中,應用程式執行在使用者空間中,兩者是不能直接通訊的。但在實際應用中,在裝置已經準備好的時候,我們希望通知使用者程式裝置已經ok,使用者程式可以讀取了,這樣應用程式就不需要一直查詢該裝置的狀態,從而節約資源,這就是非同步通知...
Linux非同步通知fasync
實現非同步通知,核心需要知道幾個東西 哪個檔案 filp 什麼訊號 sigiio 發給哪個程序 pid 收到訊號後做什麼 sig handler 這些都由前兩個步驟完成了。在這裡,同樣需要把乙個結構體 struct fasync struct 新增到核心的非同步佇列頭 名字是我自己取的 中。這個結構...
Linux核心的非同步通知
非同步通知類似於中斷,主要用於實現驅動通過傳送訊號通知應用程式。應用層 void my signal fun int signum int main int argc,char argv fcntl fd,f setown,getpid 告訴驅動要發訊號給本應用程式。oflags fcntl fd,...