在linux裏面使用kill -l
命令可以顯示系統的信號列表
這裏的1~31是普通信號,34~64是實時信號,這裏只研究普通信號
內核裏面的信號
信號的產生
- 用戶在鍵盤上按下某些鍵的時候,驅動會發送信號給前臺進程。
- 硬件產生信號,當硬件檢測到異常的時候會通知內核,內核給進程發送適當的信號。
- 進程使用kill函數向進程發送信號
軟件條件產生
信號處理的方式
忽略此信號
- 執行該信號默認的處理動作
提供一個信號處理函數,當處理自信好的時候按照用戶定義的動作完成
int kill(pid_t pid,int signo);
int raise(int signo);
兩個函數都是成功返回0,失敗返回-1。
阻塞信號
在每個信號都含有兩個標誌位,分別是block和pending,還有一個函數指針當信號產生的時候內核進程控制塊會設置信號的未決標誌,知道信號被遞達之後纔會消除該標誌。如果在信號被阻塞時候同時產生多個該信號,那麼在linux裏面只執行一次該信號的動作。但是如果該信號是實時信號,那麼信號就會被全部放在一個隊列裏面。
在表示信號得有效和無效只需要一個bit就夠了,所以在信號產生的時候只需要改變進程裏面的信號位圖的某個位就好了。在系統裏面提供了sigset_t數據類型來存儲,sigset_t成爲信號集。
信號集操作函數:
#include <signal.h>
int sigemptyset(sigset_t *set);//將信號集全部初始化成0
int sigfillset(sigset_t *set);//將信號集全部初始化成1
int sigaddset(sigset_t *set, int signum);//設置指定的信號
int sigdelset(sigset_t *set, int signum);//刪除指定的信號
int sigismember(const sigset_t *set, int signum);//判斷signum是否包含與信號集
讀取和更改進程的信號屏蔽字
int sigprocmask(int how,sigset_t *set,sigset_t *oset);
int sigpending(sigset_t *set);
實例
打印信號集裏面的信號
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void printsig(sigset_t *set){
int i = 0;
for(;i<32;i++){
if(sigismember(set,i))
printf("1");
else
printf("0");
}
printf("\n");
}
int main(){
sigset_t s,p;
sigemptyset(&s);
sigaddset(&s,SIGINT);
sigprocmask(SIG_BLOCK,&s,NULL);
while(1){
sigpending(&p);
printsig(&p);
sleep(1);
}
return 0;
}