信號導致的問題

不是任何信號我們都需要的,如果遇到我們不想處理的信號,我們怎麼避免這個信號?

 

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函數才返回。