APUE——sigprocmask,sigaction

sigprocmask

在調用sigprocmask後如果有任何未決的、不再阻塞的信號,則在sigprocmask返回前,至少會將其中一個信號遞送給該進程。
不能阻塞SIGKILL和SIGSTOP信號。

#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功則返回0,若出錯則返回-1

在這裏插入圖片描述
sigprocmask是僅爲單線程的進程定義的。
進程屏蔽信號集

#include "apue.h"

static void sig_quit();

int main()
{
    sigset_t newmask,oldmask,pendingmask;

    if(signal(SIGQUIT,sig_quit)<0)
        printf("can't catch SIGQUIT");

    sigemptyset(&newmask);
    sigaddset(&newmask,SIGQUIT);
    if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
        printf("SIG_BLOCK error");
    sleep(8);

    if(sigpending(&pendingmask)<0)
        printf("pendingmask error");
    if(sigismember(&pendingmask,SIGQUIT))
        printf("\n SIGQUIT pengding");

    if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
        printf("SIG_SETMASK error");

    if(sigpending(&pendingmask)<0)
        printf("pendingmask error");
    if(sigismember(&pendingmask,SIGQUIT))
    {
        printf("\n SIGQUIT pengding");
    }
    else
    {
        printf("\n SIGQUIT is not pengded");
    }
        
    
}

static void sig_quit(int signo)
{
    printf("caught SIGQUIT\n");
    if(signal(SIGQUIT,SIG_DFL)==SIG_ERR)
        printf("cat't reset SIGQUIT");
}

sigaction

參考鏈接添加鏈接描述

這裏要注意,SA_NODEFER 表示信號處理函數可以重複進入,原調用該信號處理函數後,操作系統會將該信號加入mask裏,阻塞表裏,進入信號後,會被阻塞。當該函數執行完畢後,會再次處理該函數!但是如果SA_RESETHAND,那麼該信號處理函數將會設置缺省值SIG_DFL!!!如果設置sa_flags = 0 ,那麼原調用該信號處理函數後,會阻塞,不能重複進入,必須等函數執行完畢!!!

  1. sa_handler此參數和signal()的參數handler相同,代表新的信號處理函數
  2. sa_mask 用來設置在處理該信號時暫時將sa_mask 指定的信號集擱置
  3. sa_flags 用來設置信號處理的其他相關操作,下列的數值可用。
  4. SA_RESETHAND:當調用信號處理函數時,將信號的處理函數重置爲缺省值SIG_DFL
  5. SA_RESTART:如果信號中斷了進程的某個系統調用,則系統自動啓動該系統調用
  6. SA_NODEFER :一般情況下, 當信號處理函數運行時,內核將阻塞該給定信號。但是如果設置了 SA_NODEFER標記, 那麼在該信號處理函數運行時,內核將不會阻塞該信號

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void show_handler(int sig)
{
    printf("I got signal %d\n", sig);
    int i;
    for(i = 0; i < 5; i++) 
   {
        printf("i = %d\n", i);
        sleep(1);
    }
}
 
int main(void)
{
    int i = 0;
    struct sigaction act, oldact;
    act.sa_handler = show_handler;
    sigaddset(&act.sa_mask, SIGQUIT);         //見注(1)
    act.sa_flags = SA_RESETHAND | SA_NODEFER; //見注(2)
    //act.sa_flags = 0;                      //見注(3)
    sigaction(SIGINT, &act, &oldact);  //sigaction是執行信號處理函數的時候屏蔽!!!!
    pr_mask("hello world!!!!!!"); //與int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
    // 不一樣!!!!!!sigprocmask是屏蔽但線程的進程
    while(1) 
   {
        sleep(1);
        printf("sleeping %d\n", i);
        i++;
    }
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void handler();


int main()
{                              //sigaction都是設置與捕捉信號有關的處理
   
   struct sigaction act,old;
   sigemptyset(&act.sa_mask);
   sigaddset(&act.sa_mask,SIGQUIT);
   act.sa_flags =  0;
   act.sa_handler = handler;
   //sigaction(SIGINT,&act,&old);  //這裏是在捕捉信號時,阻塞SIGQUIT
   sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);   //主進程阻塞SIGQUIT信號!!
   //signal(SIGINT,handler);
   while(1)
   {
      int d = 0;
      d++;
      printf("value d is : %d\n ",d);
      sleep(1);
   }
   
}

void handler(int signum)
{
   int i=0;

   for(;i<5;i++){
   printf("value i is : %d\n ",i);
   sleep(1);
   }
}

重寫signal

#include "apue.h"

Sigfunc* signal(int signo, Sigfunc* func)
{
    struct sigaction act, old;
    sigemptyset(&act.sa_mask);
    act.sa_handler = func;
    act.flags = 0;

    if(signo == SIGALARM)
    {
    #ifdef SA_INTERUPT
        act.sa_flags |= SA_INTERUPT;   //被阻止的系統調用不會重啓
    #endif
    }
    else{
    #ifdef SA_RESTART
        act.sa_flags |= SA_RESTART;  //被阻止的系統調用會重啓
    #endif
    }
    if (sigaction(,&act,&old)<0)
        return(SIG_ERR);
    return(old.sa_handler);

}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章