異步通知:
驅動程序的所謂異步通知,指的是應用程序不是主動對驅動程序進行操作,而是驅動程序查詢到有事件發生或者有數據發生變化的時候通知應用程序。角色發生了變化,應用程序由主動改爲被動執行。
比如按鍵驅動:
1、要不斷進行查詢引腳狀態的,CPU資源消耗非常的大;
2、有中斷操作的,發生按鍵事件後採取執行相關事件處理函數,需要應用程序不斷執行read函數,使得不能去幹其它事情;
3、poll機制,改善了中斷方式操作,在應用程序上當沒有事件發生時,會跳去read函數繼續執行其它的任務,知道有事件發生才返回;
4、異步通知,也即我們本次講的,讓驅動程序自己告訴我們事件發生,我們採取執行。
目標:按下按鍵時,驅動程序通知應用程序。(以前是應用程序主動讀取按鍵值)
1,應用程序中要註冊“信號處理函數”。因爲通知它做什麼事情,這要一個函數來做。
2,誰發:是驅動程序發送信號。
3,發給誰:信號發送給應用程序。應用程序要告訴驅動程序它自已的 PID,
4,如何發:驅動程序中調用某個函數(kill_fasync())
操作步驟
在驅動程序裏:
1.首先聲明一個“fasync_struct”結構變量。
例:static struct fasync_struct *button_async;
2.初始化button_async結構變量
- 在file_operations多定義一個成員函數 例:.fasync = fifth_drv_fasync
- 定義這個函數
static int fifth_drv_fasync (int fd, struct file *filp, int on)
{
return fasync_helper (fd, filp, on, &button_async);
}
所以顯然是應用程序要調用“.fasync”來設置那個“發給誰”
3.在中斷函數中調用kill_fasync (&button_async, SIGIO, POLL_IN)來發送信號
有按鍵按下了就發一個信號給應用程序。其中要定義一個結構,取名爲“button_async” .
以上便可以發送信號出去了
在應用程序裏:
1.定義信號signal(SIGIO, my_signal_fun);
定義my_signal_fun(int signum)// 驅動程序發送信號後,應用程序接收到信號做相應處理 讀取硬件數據
2. fcntl(fd, F_SETOWN, getpid()); // 告訴內核,發給誰
應用程序會調用“fcntl()”這個函數,把進程的 PID 號告訴給驅動程序。
3. Oflags = fcntl(fd, F_GETFL); //應用程序通過“F_GETFL”讀出“flags”
4. fcntl(fd, F_SETFL, Oflags | FASYNC);
改變 fasync 標記,最終會調用到驅動的 faync > fasync_helpe()r:初始化 fasync_struct
如上面“fcntl(fd, F_SETFL, Oflags | FASYNC);”接口被調用時,在函數中的“fasync_helper()”就會被調用
static int fifth_drv_fasync (int fd, struct file *filp, int on) // 初始化 “button_async”
{
return fasync_helper (fd, filp, on, &button_async);
}