Linux驅(qū)動編程之信號機制

編寫Linux驅(qū)動的過程中,需要考慮與應(yīng)用程序交互的情況。當(dāng)設(shè)備驅(qū)動完成某項任務(wù)或者達到某種狀態(tài)的時候(如設(shè)備文件可以寫入或讀取),此時可以讓驅(qū)動程序主動通知應(yīng)用程序進行相應(yīng)的處理(個人感覺類似于Android應(yīng)用程序中的廣播)。這種在Linux內(nèi)核中使用的“廣播”就是本文要詳細介紹的“信號”。

1. Linux信號類型

使用信號進行進程間通信(IPC)是LInux系統(tǒng)的重要通信機制。在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兩個信號外,進程可以忽略或捕獲其他的全部信號。

如果其中一個信號被捕獲,說明在應(yīng)用程序中為該信號指定了一個處理函數(shù)。如果一個信號沒有被某個進程捕獲,Linux內(nèi)核會對該信號采用默認處理方式進行處理。

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ù),需要完成以下工作:

  1. 支持F_SETDOWN命令。通過這個命令可以設(shè)置file_f_owner為對應(yīng)進程的ID。
  2. 支持F_SETFL命令的處理。每當(dāng)FASYNC標志改變時,驅(qū)動程序中的fasync函數(shù)就會執(zhí)行。
  3. 再滿足條件時,調(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í)行默認的handler。(雖然有些調(diào)用,在handler的以開頭再次置handler,這樣只能保證丟信號的概率降低,但是不能保證所有的信號都能正確處理)
2、signal在調(diào)用過程不支持信號block;sigaction調(diào)用后在handler調(diào)用之前會把屏蔽信號(屏蔽信號中自動默認包含傳送的該信號)加入信號中,handler調(diào)用后會自動恢復(fù)信號到原先的值。
(2)signal處理過程中就不能提供阻塞某些信號的功能,sigaction就可以阻指定的信號和本身處理的信號,直到handler處理結(jié)束。這樣就可以阻塞本身處理的信號,到handler結(jié)束就可以再次接受重復(fù)的信號。

在驅(qū)動程序編寫過程中與應(yīng)用程序進行交互是非常重要的,他可以確保用戶程序能夠順利執(zhí)行,也能保證驅(qū)動能夠更好地服務(wù)于用戶。以上是本人學(xué)習(xí)中的一些總結(jié),希望對大家有幫助~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容