1. 程式人生 > >12.訊號集函式:sigemptyset;sigfillset;sigaddset;sigdelset;sigismember;sigpending

12.訊號集函式:sigemptyset;sigfillset;sigaddset;sigdelset;sigismember;sigpending

訊號處理的工作原理:阻塞訊號集/未決訊號集

未決訊號集:
	沒有被當前程序處理的訊號集
阻塞訊號集:
	將某個訊號放到阻塞訊號集,這個訊號就不會被程序處理
	阻塞解除後,訊號被處理
---------------------------------------------------------------
訊號處理的工作原理:核心PCB中,存放著未決訊號集/阻塞訊號集
1.當產生訊號XXX時,將在[未決訊號集]中將XXX訊號的標誌位設為1
2.放入[未決訊號集]中的XXX訊號等待處理,在處理之前需要做一件事:判斷
[阻塞訊號集]中的XXX訊號的標誌位是否為1(如果為1,不處理XXX訊號;如
果為0,處理XXX訊號)

訊號集函式

int sigemptyset(sigset_t *set);   //將set集合置空
int sigfillset(sigset_t *set); //將所有訊號加入set集合

int sigaddset(sigset_t *set, int signum); //將signum訊號加入set集合
int sigdelset(sigset_t *set, int signum); //從set集合中移除signum訊號

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); //將自定義訊號集放在核心中的[阻塞訊號集]中
引數:
	how取值,假設當前的訊號遮蔽字為mask
		SIG_BLOCK:mask=mask|set      新增遮蔽字
		SIG_UNBLOCK:mask=mask|~set    解除遮蔽字
		SIG_SETMASK:mask=set
	set:傳出的新的set
	oldset:設定之前的當前的訊號遮蔽字集合
	使用:sigprocmask(___,&set,NULL);
	
int sigpending(sigset_t *set); //讀取當前程序的未決訊號集sigpendset
	
int sigismember(const sigset_t *set, int signum); //判斷set集合中是否存在signum訊號

案例1:[獲取]當前程序的未決訊號集

int main(){        
  //每隔1s獲取一次記憶體的未決訊號集
  while(1){                                                                                                                      
    sigset_t pendset;                                                                                                            
    sigpending(&pendset); //獲取[當前程序]的未決訊號集,存放在pendset集合中
    //1-31訊號                                                                          
    for(int i=1;i<=31;i++){                                                                                                      
      //判斷訊號i是否在pendset中,
      if(sigismember(&pendset,i))                                                                                                
        printf("1");                                                                                                             
      else                                                                                                                       
        printf("0");                                                                                                             
    }                                                                                                                            
    printf("\n");                                                                                                                
    sleep(1);                                                                                                                    
  }                                                                                                                                                                                                                                      
  return 0;                                                                                                                      
}  
[
[email protected]
4-signal]$ ./signal_set 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000

案例2:

int main(){                                                                                                                      
  sigset_t myset;                
  //清空myset                                                                                                
  sigemptyset(&myset);                                                                                                           
  //將下面三個訊號新增到myset集合中
  sigaddset(&myset,SIGINT); /*   ctrl+C   */                                                                                     
  sigaddset(&myset,SIGQUIT);/*   ctrl+\   */                                                                                     
  sigaddset(&myset,SIGKILL);                                                                                                     
  //將myset集合中的訊號設為[阻塞]                                                                     
  sigprocmask(SIG_BLOCK,&myset,NULL);                                                                                            
                                                                                
  while(1){                                                                                                                      
    sigset_t pendset;                                                                                                            
    sigpending(&pendset); //讀取當前程序的未決訊號集
    //1-31                                                                                                                       
    for(int i=1;i<=31;i++){                                                                                                      
      if(sigismember(&pendset,i)) //判斷i訊號是否在penset中
        printf("1");                                                                                                             
      else                                                                                                                       
        printf("0");                                                                                                             
    }                                                                                                                            
    printf("\n");                                                                                                                
    sleep(1);                                                                                                                    
  }                                                                                                                              
                                                                                                                                 
  return 0;                                                                                                                      
}   
[[email protected] 4-signal]$ ./signal_set 
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
^C0100000000000000000000000000000    #點選ctrl+C
^\0110000000000000000000000000000    #點選ctrl+\
0110000000000000000000000000000
0110000000000000000000000000000
0110000000000000000000000000000
已殺死      #kill -9 signal_set的pid
程式解讀:
	1.將ctrl+C,ctrl+\,kill -9引發的訊號,放入myset阻塞訊號集中
	2.呼叫ctrl+C,ctrl+\觸發相應的訊號,呼叫sigpending函式獲取[當前程序的
	未決訊號集],存放在pendset集合中
	3.for迴圈,使用sigismember函式判斷i訊號是否在pendset集合中
	4.呼叫kill -9殺死當前程序