fasync

異步通知fasync套用於系統調用signal和sigaction函式,簡單的說,signal函式就是讓一個信號與一個函式對應,每當接收到這個信號就會調用相應的函式。

函式概括,使用方式,注意事項,

函式概括

異步通知fasync套用於系統調用signal和sigaction函式,簡單的說,signal函式就是讓一個信號與一個函式對應,每當接收到這個信號就會調用相應的函式。
那么什麼是異步通知?異步通知類似於中斷的機制,當設備可寫時,設備驅動函式傳送一個信號給核心,告知核心有數據可讀,在條件不滿足之前,並不會造成阻塞。而不像之前學的阻塞型IO和poll,它們是調用函式進去檢查,條件不滿足時還會造成阻塞。

使用方式

其實在套用層啟用異步通知只三個步驟:
1)signal(SIGIO, sig_handler);
調用signal函式,讓指定的信號SIGIO與處理函式sig_handler對應。
2)fcntl(fd, F_SET_OWNER, getpid());
指定一個進程作為檔案的“屬主(filp->owner)”,這樣核心才知道信號要發給哪個進程。
3)f_flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, f_flags | FASYNC);
在設備檔案中添加FASYNC標誌,驅動中就會調用將要實現的test_fasync函式。
三個步驟執行後,一旦有信號產生,相應的進程就會收到。

注意事項

3.1 異步通知核心實現
實現異步通知,核心需要知道幾個東西:哪個檔案(filp),什麼信號(SIGIIO),發給哪個進程(pid),收到信號後做什麼(sig_handler)。這些都由上述前兩個步驟完成了,而這前兩個步驟核心幫忙實現了,所以,我們只需要實現第三個步驟的一個簡單的傳參。
3.2 fasync_struct結構體
要實現傳參,我們需要把一個結構體struct fasync_struct添加到核心的異步佇列中,這個結構體用來存放對應設備檔案的信息(如fd, filp)並交給核心來管理。一但收到信號,核心就會在這個所謂的異步佇列頭找到相應的檔案(fd),並在filp->owner中找到對應的進程PID,並且調用對應的sig_handler了。
struct fasync_struct {
int magic;
int fa_fd;
struct fasync_struct *fa_next; /* singly linked list */
struct file *fa_file;
};
3.3 核心中我們的工作
上面說了前兩個步驟會由核心完成,所以我們只要做兩件事情:
1)定義結構體fasync_struct。
struct fasync_struct *async_queue;
2)實現test_fasync,把函式fasync_helper將fd,filp和定義的結構體傳給核心。
int test_fasync (int fd, struct file *filp, int mode)
{
struct _test_t *dev = filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}
函式fasync_helper的定義為:
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
前面的三個參數其實就是teat_fasync的三個參數,所以只要我們定義好的fasync_struct結構體也傳進去就可以了。
3.4 其餘的工作
另外還有兩件事:
3)當設備可寫時,調用函式kill_fasync傳送信號SIGIO給核心。
if (dev->async_queue){
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
}
講解一下這個函式:
void kill_fasync(struct fasync_struct **fp, int sig, int band)
sig就是我們要傳送的信號。
band(頻寬),一般都是使用POLL_IN,表示設備可讀,如果設備可寫,使用POLL_OUT
4)當設備關閉時,需要將fasync_struct從異步佇列中刪除:
test_fasync(-1, filp, 0);
刪除也是調用test_fasync,不過改了一下參數而已。

相關詞條

熱門詞條

聯絡我們