本文是分別重應用程式層面、驅動程式層面講解linux非同步通知I/O的機制,希望給讀者帶來協助。由於本人知識有限,如有錯誤請大家指出,謝謝!
/******************************
author:徐福成
date :2011.01.01
******************************/
1)應用程式層面:
linux非同步通知I/O 就是我們應用程式中經常用到的訊號的處理方法,如:signal(),和sigaction()兩個函數用來註冊一個訊號的處理方法。
如:
#include ...//接收到非同步讀訊號的動作void input_handler(int signum){ printf("Receive a signal from globalfifo,signalnum:%d/n",signum);}int main(){ int fd, oflags; fd = open("/dev/globalfifo", O_RDWR, S_IRUSR | S_IWUSR); if (fd != - 1) { //啟動訊號驅動機制 signal(SIGIO, input_handler); //讓input_handler()處理SIGIO訊號 fcntl(fd, F_SETOWN, getpid()); oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | FASYNC); while(1) { sleep(100); } } else { printf("device open failure/n"); }}
上面就是一個簡單的非同步通知I/O 的例子,當該程式收到SIGIO訊號的時候,就調用input_handler()函數。
說明:什麼時候收到SIGIO訊號該進程是不知道的,只要收到該訊號,就會調用上面的訊號處理函數,這就是非同步通知I/O的應用原理。
2)裝置驅動層面1.非同步通知I/O的組成
非同步通知I/O故名思議就需要一個訊號的寄件者,和一個訊號的接受者;
寄件者:往往是一個外圍裝置,當該外圍裝置資源可用的時候會給對應需要獲得該資源的進程發送一個可用的訊號,提醒這個進程
接受者:就是我們的應用程式,也就是一個進程;
2.驅動程式中涉及到的三個工作
(1)支援F_SETOWN命令,能在這個控制命令處理中設定filp->f_owner為對應進程ID。此工作已由核心完成,裝置驅動程式不需要來處理。
(2)支援F_SETFL命令,每當FASYNC標誌狀態改變時,linux裝置驅動程式中的fasync()函數將得以執行。(前提linux裝置驅動程式需要實現這個函數,否則一切都是空談)
(3)在裝置資源可獲得時,調用kill_fasync()函數激發相應的訊號
3.主要用的API
(1)fasync_helper()
說明:該函數處理FASYNC標誌更改的函數,fasync()函數中調用;
(2)kill_fasync()
說明:該函數用來釋放訊號,往往在讀寫函數中調用,相應的資源可用;
當然要在release函數中釋放非同步通知這個標誌,fasync(-1,filp,0)
希望本文對大家有協助,謝謝!