編寫Linux驅(qū)動的過程中性芬,需要考慮與應(yīng)用程序交互的情況褪那。當(dāng)設(shè)備驅(qū)動完成某項任務(wù)或者達(dá)到某種狀態(tài)的時候(如設(shè)備文件可以寫入或讀攘头堋)蔫缸,此時可以讓驅(qū)動程序主動通知應(yīng)用程序進(jìn)行相應(yīng)的處理(個人感覺類似于Android應(yīng)用程序中的廣播)哪轿。這種在Linux內(nèi)核中使用的“廣播”就是本文要詳細(xì)介紹的“信號”。
1. Linux信號類型
使用信號進(jìn)行進(jìn)程間通信(IPC)是LInux系統(tǒng)的重要通信機(jī)制华烟。在Linux系統(tǒng)中坑鱼,異步通知使用信號來實現(xiàn)。以下是Linux系統(tǒng)支持的信號及其含義:(asm/signal.h)
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL SIGIO
#define SIGPWR 30
#define SIGSYS 31
/* These should not be considered constants from userland. */
#define SIGRTMIN 32
#define SIGRTMAX _NSIG
#define SIGSWI 32
注:以上除了SISSTOP和SIGKILL兩個信號外动漾,進(jìn)程可以忽略或捕獲其他的全部信號丁屎。
如果其中一個信號被捕獲,說明在應(yīng)用程序中為該信號指定了一個處理函數(shù)晨川。如果一個信號沒有被某個進(jìn)程捕獲,Linux內(nèi)核會對該信號采用默認(rèn)處理方式進(jìn)行處理共虑。
2. 接收Linux信號
在用戶程序中,為了捕捉信號妈拌,需要使用signal函數(shù)來設(shè)置信號接收的回調(diào)函數(shù):
void (*signal(int signum, void (* handler)(int)))(int);
從signal函數(shù)原型上看有些復(fù)雜, 但主要有兩個參數(shù):signum和handler蓬蝶,signum表示信號代碼尘分,handler表示回調(diào)函數(shù)。
在應(yīng)用程序中捕獲信號比較簡單音诫,如下例子:
void signal_handler(int signo)
{
printf("捕獲到%d信號\n",signo);
}
main()
{
printf("信號ID是%d\n"竭钝,getpid());
signal(SIGINT, signal_handler); //設(shè)置SIGINT信號的處理函數(shù)
signal(SIGHUP, signal_handler); //設(shè)置SIGHUP信號的處理函數(shù)
signal(SIGQUIT, signal_handler); //設(shè)置SIGQUIT信號的處理函數(shù)
getchar();
}
以上代碼示例了如何捕捉信號,并設(shè)置相應(yīng)的處理函數(shù)雹洗。
3香罐、發(fā)送信號
在設(shè)備驅(qū)動和應(yīng)用程序的異步通知過程中,驅(qū)動程序需要向應(yīng)用程序發(fā)出信號时肿,為了完成發(fā)送信號的任務(wù)庇茫,需要完成以下工作:
- 支持F_SETDOWN命令螃成。通過這個命令可以設(shè)置file_f_owner為對應(yīng)進(jìn)程的ID。
- 支持F_SETFL命令的處理寸宏。每當(dāng)FASYNC標(biāo)志改變時,驅(qū)動程序中的fasync函數(shù)就會執(zhí)行氮凝。
- 再滿足條件時,調(diào)用kill_fasync函數(shù)發(fā)送相應(yīng)的信號。
接收信號可以用signal函數(shù)和sigaction函數(shù)來完成启摄,他們之間有以下幾個區(qū)別:
signal函數(shù)
1、signal在調(diào)用handler之前先把信號的handler指針恢復(fù)歉备;sigaction調(diào)用之后不會恢復(fù)handler指針,直到再次調(diào)用sigaction修改handler指針威创。
:這樣谎懦,(1)signal就會丟失信號肚豺,而且不能處理重復(fù)的信號界拦,而sigaction就可以。因為signal在得到信號和調(diào)用handler之間有個時間把handler恢復(fù)了享甸,這樣再次接收到此信號就會執(zhí)行默認(rèn)的handler。(雖然有些調(diào)用蛉威,在handler的以開頭再次置handler,這樣只能保證丟信號的概率降低蚯嫌,但是不能保證所有的信號都能正確處理)
2、signal在調(diào)用過程不支持信號block束凑;sigaction調(diào)用后在handler調(diào)用之前會把屏蔽信號(屏蔽信號中自動默認(rèn)包含傳送的該信號)加入信號中,handler調(diào)用后會自動恢復(fù)信號到原先的值汪诉。
(2)signal處理過程中就不能提供阻塞某些信號的功能,sigaction就可以阻指定的信號和本身處理的信號谈秫,直到handler處理結(jié)束扒寄。這樣就可以阻塞本身處理的信號,到handler結(jié)束就可以再次接受重復(fù)的信號拟烫。
在驅(qū)動程序編寫過程中與應(yīng)用程序進(jìn)行交互是非常重要的,他可以確保用戶程序能夠順利執(zhí)行构灸,也能保證驅(qū)動能夠更好地服務(wù)于用戶。以上是本人學(xué)習(xí)中的一些總結(jié)喜颁,希望對大家有幫助~~