一:信號集
//一個進程,必須能夠記住 這個進程 當前阻塞了哪些信號
//000000000000000000000
//我們需要 “信號集 ”的這麼一種數據類型(結構),能夠把這60多個信號都表示下(都裝下)。
//0000000000,0000000000,0000000000,00,0000000000,0000000000,0000000000,00 (64個二進制位)
//linux 是用sigset_t結構類型來表示信號集的;
//typedef struct{
// unsigned long sig[2];
//}sigset_t
//信號集的定義:信號集表示一組信號的來(1)或者沒來(0)
//信號集相關的數據類型: sigset_t;
二:信號相關函數
//a)sigemtpyset():把信號集中的所有信號都清0,表示這60多個信號都沒有來;
//00000000000000000000000000.....
//b)sigfillset();把信號集中的所有信號都設置爲1,跟sigemptyset()正好相反;
//11111111111111111111111111.....
//c)用sigaddset(),sigdelset()就可以往信號集中增加信號,或者從信號集中刪除特定信號;
//d)sigprocmask,sigmember
//一個進程,裏邊會有一個信號集,用來記錄當前屏蔽(阻塞)了哪些信號;
//如果我們把這個信號集中的某個信號位設置爲1,就表示屏蔽了同類信號,此時再來個同類信號,那麼同類信號會被屏蔽,不能傳遞給進程;
//如果這個信號集中有很多個信號位都被設置爲1,那麼所有這些被設置爲1的信號都是屬於當前被阻塞的而不能傳遞到該進程的信號;
//sigprocmask()函數,就能夠設置該進程所對應的信號集中的內容;
三:sigprocmask等信號函數範例演示
//sleep()函數能夠被打斷:
//(1)時間到達了;
//(2)來了某個信號,使sleep()提前結束,此時sleep會返回一個值,這個值就是未睡夠的時間;
//sigaction()函數;
#include <stdio.h>
#include <stdlib.h> //malloc
#include <unistd.h>
#include <signal.h>
//信號處理函數
void sig_quit(int signo)
{
printf("收到了SIGQUIT信號!\n");
if(signal(SIGQUIT,SIG_DFL) == SIG_ERR)
{
printf("無法爲SIGQUIT信號設置缺省處理(終止進程)!\n");
exit(1);
}
}
int main(int argc, char *const *argv)
{
sigset_t newmask,oldmask; //信號集,新的信號集,原有的信號集,掛起的信號集
if(signal(SIGQUIT,sig_quit) == SIG_ERR) //註冊信號對應的信號處理函數,"ctrl+\"
{
printf("無法捕捉SIGQUIT信號!\n");
exit(1); //退出程序,參數是錯誤代碼,0表示正常退出,非0表示錯誤,但具體什麼錯誤,沒有特別規定,這個錯誤代碼一般也用不到,先不管他;
}
sigemptyset(&newmask); //newmask信號集中所有信號都清0(表示這些信號都沒有來);
sigaddset(&newmask,SIGQUIT); //設置newmask信號集中的SIGQUIT信號位爲1,說白了,再來SIGQUIT信號時,進程就收不到,設置爲1就是該信號被阻塞掉唄
//sigprocmask():設置該進程所對應的信號集
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0) //第一個參數用了SIG_BLOCK表明設置 進程 新的信號屏蔽字 爲 “當前信號屏蔽字 和 第二個參數指向的信號集的並集
{ //一個 ”進程“ 的當前信號屏蔽字,剛開始全部都是0的;所以相當於把當前 "進程"的信號屏蔽字設置成 newmask(屏蔽了SIGQUIT);
//第三個參數不爲空,則進程老的(調用本sigprocmask()之前的)信號集會保存到第三個參數裏,用於後續,這樣後續可以恢復老的信號集給線程
printf("sigprocmask(SIG_BLOCK)失敗!\n");
exit(1);
}
printf("我要開始休息10秒了--------begin--,此時我無法接收SIGQUIT信號!\n");
sleep(10); //這個期間無法收到SIGQUIT信號的;
printf("我已經休息了10秒了--------end----!\n");
if(sigismember(&newmask,SIGQUIT)) //測試一個指定的信號位是否被置位(爲1),測試的是newmask
{
printf("SIGQUIT信號被屏蔽了!\n");
}
else
{
printf("SIGQUIT信號沒有被屏蔽!!!!!!\n");
}
if(sigismember(&newmask,SIGHUP)) //測試另外一個指定的信號位是否被置位,測試的是newmask
{
printf("SIGHUP信號被屏蔽了!\n");
}
else
{
printf("SIGHUP信號沒有被屏蔽!!!!!!\n");
}
//現在我要取消對SIGQUIT信號的屏蔽(阻塞)--把信號集還原回去
if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0) //第一個參數用了SIGSETMASK表明設置 進程 新的信號屏蔽字爲 第二個參數 指向的信號集,第三個參數沒用
{
printf("sigprocmask(SIG_SETMASK)失敗!\n");
exit(1);
}
printf("sigprocmask(SIG_SETMASK)成功!\n");
if(sigismember(&oldmask,SIGQUIT)) //測試一個指定的信號位是否被置位,這裏測試的當然是oldmask
{
printf("SIGQUIT信號被屏蔽了!\n");
}
else
{
printf("SIGQUIT信號沒有被屏蔽,您可以發送SIGQUIT信號了,我要sleep(10)秒鐘!!!!!!\n");
int mysl = sleep(10);
if(mysl > 0)
{
printf("sleep還沒睡夠,剩餘%d秒\n",mysl);
}
}
printf("再見了!\n");
return 0;
}