異步通知是一種通知,相當(dāng)于用于應(yīng)用程序的中斷??捎糜隍?qū)動通知進(jìn)程,也可以進(jìn)程通知進(jìn)程。
異步通知接收步驟
默認(rèn)信號的接收
默認(rèn)的異步IO信號是SIGIO,使用這個信號的接收程序如下:
static void signal_handler(int sig)
{
...
}
...int fd,oflags;
signal(SIGIO,signal_handler); //
fcntl(fd,F_SETOWN,getpid()); //
oflags = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,oflags|FASYNC);
...
}
...
signal_handler 是通知要運(yùn)行的函數(shù);
signal(SIGIO,signal_handler); 是注冊信號對應(yīng)的函數(shù)
fcntl(fd,F_SETOWN,getpid()); ? ?這句是設(shè)置異步通知要通知給誰
oflags = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,oflags|FASYNC); ?這兩句是使能異步通知。
重點就是使能這部要放在最后。原因如下:如果使能放在前面,異步通知發(fā)生在使能之后,注冊信號函數(shù)之前的話。由于找不到注冊函數(shù),系統(tǒng)會執(zhí)行默認(rèn)處理函數(shù)。就是會將進(jìn)程終止。這樣就發(fā)生故障,與預(yù)期不符。
實時信號的接收
實時信號就是更換默認(rèn)信號SIGIO為實時信號。默認(rèn)信號SIGIO有些缺點,不支持排隊,在信號處理函數(shù)進(jìn)行過程中如果來了多次SIGIO信號的話會被忽略的。實時信號有很多,SIGRTMIN~SIGRTMAX的都是實時信號。
實時信號程序如下:
static void test_handler(int sig, siginfo_t *info, void *context)
...
struct sigaction test;
int flag;fd = open(xxx,xxx);
test.sa_sigaction = test_handler;
test.sa_flags = SA_SIGINFO;
sigemptyset(&test.sa_mask);
sigaction(SIGRTMIN, &test, NULL);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETSIG, SIGRTMIN);
oflags = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,oflags|FASYNC);
test_handler是通知要運(yùn)行的函數(shù);
sigaction(SIGRTMIN, &test, NULL); ? 是注冊信號對應(yīng)的函數(shù)
fcntl(fd,F_SETOWN,getpid()); ? ?這句是設(shè)置異步通知要通知給誰
fcntl(fd, F_SETSIG, SIGRTMIN); ? 是設(shè)置異步通知使用的信號是什么
oflags = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,oflags|FASYNC); ? 這兩句是使能異步通知。
重點如上,使能放在最后。
異步通知發(fā)送
異步通知發(fā)送分為兩種,進(jìn)程向進(jìn)程發(fā)送和驅(qū)動向進(jìn)程發(fā)送。
進(jìn)程向進(jìn)程發(fā)送
這個比較簡單,使用kill函數(shù)就可以。
kill的函數(shù)pid是正數(shù)的時候是目標(biāo)的進(jìn)程,負(fù)數(shù)分幾種情況可以查閱相關(guān)資料。
驅(qū)動向進(jìn)程發(fā)送
驅(qū)動向進(jìn)程發(fā)送主要分兩步
1 編寫驅(qū)動得fasync函數(shù),這個函數(shù)里要包括fasync_helper,注冊異步通知
2 在需要發(fā)送異步通知的位置,先判斷異步通知申請成功并可以獲得進(jìn)程號,然后使用kill_fasync發(fā)送通知