1.sigaction函數
原型:int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
參數:
act:傳入參數,新的處理方式。
oldact:傳出參數,舊的處理方式。
作用:修改信号處理動作(通常在 Linux 用其來注冊一個信号的捕捉函數)
傳回值:成功:0;失敗:-1,設定 errno
struct sigaction 結構體
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
重點掌握:
(1)sa_handler:指定信号捕捉後的處理函數名(即注冊函數)。也可指派為 SIG_IGN 表忽略 或 SIG_DFL 表執行預設動作
(2)sa_mask: 調用信号處理函數時,所要屏蔽的信号集合(信号屏蔽字)。注意:僅在處理函數被調用期間屏蔽生效,是臨時性設定。
(3)sa_flags:通常設定為 0,表使用預設屬性。
2.信号捕捉特性
(1)程序正常運作時,預設 PCB 中有一個信号屏蔽字,假定為☆,它決定了程序自動屏蔽哪些信号。當注冊了某個信号捕捉函數,捕捉到該信号以後,要調用該函數。而該函數有可能執行很長時間,在這期間所屏蔽的信号不由☆來指定。而是用 sa_mask 來指定。調用完信号處理函數,再恢複為☆。
(2)XXX 信号捕捉函數執行期間,XXX 信号自動被屏蔽。
(3)阻塞的正常信号不支援排隊,産生多次隻記錄一次。(後 32 個實時信号支援排隊)
3.代碼: test_sigac.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
//本程式要實作:在使用sigaction函數捕捉信号SIGINT,在執行信号捕捉後的處理函數時,屏蔽信号SIGQUIT。
//測試:執行程式後,ctrl + c後,輸出 2 signal is catched
//此時 ctrl + \ 後,程序并沒有退出。需要重開終端,手動殺死該程序
void docatch(int signo)
{
printf("%d signal is catched\n",signo);
while(1);
}
int main()
{
int ret;
struct sigaction act;
act.sa_handler = docatch; //指定信号捕捉後的處理函數名(注冊函數)
//act.sa_mask是調用信号處理函數時,所要屏蔽的信号集合(信号屏蔽字)
sigemptyset(&act.sa_mask); //将信号集act.sa_mask清0
sigaddset(&act.sa_mask,SIGQUIT); //添加信号SIGQUIT到集合act.sa_mask中
act.sa_flags = 0; //預設屬性,信号捕捉函數執行期間,自動屏蔽本信号
ret = sigaction(SIGINT,&act,NULL);//捕捉SIGINT信号
if(ret < 0){
perror("sigaction error");
exit(1);
}
while(1);
return 0;
}
結果: