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);

}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44537992/article/details/105779189