信號導致的問題
不是任何信號我們都需要的,如果遇到我們不想處理的信號,我們怎麼避免這個信號?
1. 信號屏蔽
intsigprocmask(int how,//操作方式
SIG_BLOCK屏蔽信號
SIG_UNBLOCK剪除屏蔽信號
SIG_SETMASK修改屏蔽信號
constsigset_t *sigs,//操作的信號集合
sigset_t*oldsigs);//返回原來操作的信號集合
返回值:執行成功返回0,失敗返回-1。
屏蔽信號的步驟:
1. 聲明信號集
sigset_t sigs;
2. 加入屏蔽信號
一組信號集合維護函數
2.1. 清空集合sigemptyset
int sigemptyset( sigset_t *set);
2.2. 添加信號到集合sigaddset
int sigaddset( sigset_t *set ,int signum);
2.3. 從集合刪除信號sigdelset
int sigdelset(sigset_t *set,int signum);
2.4. 添加所有信號到集合sigfillset
int sigfillset( sigset_t*set);
2.5. 判定信號是否在集合sigismember
int sigismember(const sigset_t *set ,int signum);
3. 屏蔽信號
4. 接觸屏蔽
例子:
#include<stdio.h>
#include<signal.h>
void main()
{
int sum=0;
//聲明信號集
sigset_t sigs;
//清空信號集
sigemptyset(&sigs);
//添加信號到信號集
sigaddset(&sigs,SIGINT); //
//屏蔽信號
sigprocmask( SIG_BLOCK,&sigs,0);
for(i=1;i<=10;i++)
{
sum+=i;
sleep(1);
}
printf(“sum=%d\n”,sum);
//撿出屏蔽
sigprocmask(SIG_UNBLOCK,&sigs,0);//撿出屏蔽,信號立即觸犯,打印over不能//執行,如果沒有撿出屏蔽信號,over正常打印
printf(“OVER!\n”);
}
説明:當屏蔽了某個信號,這個信號將不會觸發,直到我們撿出了該信號,信號才會觸發。
2.查詢被屏蔽的信號
intsigpending(sigset_t *sets); 返回0成功,-1失敗
例子:
#include<stdio.h>
#include<signal.h>
void main()
{
int sum=0;
//聲明信號集
sigset_t sigs;
sigset_t sigp;
//清空信號集
sigemptyset(&sigs);
//添加信號到信號集
sigaddset(&sigs,SIGINT); //
//屏蔽信號
sigprocmask( SIG_BLOCK,&sigs,0);
for(i=1;i<=10;i++)
{
sum+=i;
sigpending(&sigp);//得到屏蔽的信號
if(sigismemeber(&sigp,SIGINT))
{
printf(“信號SIGINT在排隊\n”);
}
sleep(1);
}
printf(“sum=%d\n”,sum);
//撿出屏蔽
sigprocmask(SIG_UNBLOCK,&sigs,0);
printf(“OVER!\n”);
}
2. 信號屏蔽的切換
int sigsuspend(sigset_t *sigs);
屏蔽新的信號,原來的信號失效.
sigsuspend是阻塞函數.對參數信號屏蔽.
對參數沒有指定的信號不屏蔽,但當沒有屏蔽信號處理函數調用完畢
sigsuspend返回條件:
1.信號發生,並且信號是非屏蔽信號
2.信號必須要處理,而且處理函數返回後,sigsuspend才返回.
sigsuspend設置新的屏蔽信號,保存舊的屏蔽信號
而且當sigsuspend返回的時候,恢復舊的屏蔽信號.
函數sigsuspend將進程的信號屏蔽碼設置為sigs,然後與pause()函數一樣等待信號的發生並執行完信號處理函數。信號處理函數執行完後再把進程的信號屏蔽碼設置為原來的屏蔽字,然後sigsuspend函數才返回。 Sigsuspend總是返回-1。
例子:
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void deal()
{
printf(“處理信號SIGINT\n”);
}
void main()
{
signal(SIGINT,deal);
int sum=0;
//聲明信號集
sigset_t sigs;
sigset_t sigp;
sigset_t newsig=NULL;
//清空信號集
sigemptyset(&sigs);
//添加信號到信號集
sigaddset(&sigs,SIGINT); //
//屏蔽信號
sigprocmask( SIG_BLOCK,&sigs,0);
for(i=1;i<=10;i++)
{
sum+=i;
sigpending(&sigp);//得到屏蔽的信號
if(sigismemeber(&sigp,SIGINT))
{
printf(“信號SIGINT在排隊\n”);
sigsuspend(&newsig);//切換屏蔽信號,等待SIGINT信號,並調用處//理函數後函數返回。
}
sleep(1);
}
printf(“sum=%d\n”,sum);
}
説明:程序檢查到屏蔽信號中有SIGINT信號在排隊,就調用sigsuspend函數切換屏蔽信號,程序處理SIGINT信號後,sigsuspend函數才返回。