这篇文章上次修改于 456 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

信号可以屏蔽,也可以捕捉

信号屏蔽(阻塞)

    sigset_t set;//初始化信号集
    sigemptyset(&set);//清空信号集
    sigaddset(&set, SIGINT);//信号加入信号集
    sigprocmask(SIG_BLOCK,&set, NULL);//设置屏蔽信号(堵塞,解除后恢复)
    sigprocmask(SIG_UNBLOCK,&set, NULL);//解除屏蔽

详解sigprocmask

   int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

   set自定义位图

   old保存旧位图

   how有
   1. SIG_BLOCK: set 表示需要屏蔽的信号。相当于 mask = mask|set

   2. SIG_UNBLOCK: set 表示需要解除屏蔽的信号。相当于 mask = mask & ~set

   3. SIG_SETMASK: set 表示用于替代原始屏蔽及的新屏蔽集。相当于 mask = set 若,调用 sigprocmask 解除了对当前若干个信号的阻塞,则在 sigprocmask 返回前,至少将其中一 个信号递达。

信号捕捉(自定义)

1.捕捉函数(void)fun(int)

void er(int number)//信号捕捉函数 (void)func(int)
{
    if (number == SIGINT)
        printf("hello\n");
        else if(number==SIGCHLD)
        {
            pid_t wpid;
            int status;
            while((wpid=waitpid(-1,&status,0))!=-1)//防止多个进程同时死亡
            {
                if(WIFEXITED(status))
                printf("%d",WEXISTATUS(ststus));
            }
        }
    return;
}

2.先阻塞

    sigset_t set;//初始化信号集
    sigemptyset(&set);//清空信号集
    sigaddset(&set, SIGCHLD);//SIGCHLD信号加入信号集
    sigprocmask(SIG_BLOCK,&set, NULL);//设置屏蔽信号(堵塞,解除后恢复,只处理一次)

3.再注册

    struct sigaction new, old;
    new.sa_handler = er;            //执行函数名(先写捕捉函数)
    sigemptyset(&new.sa_mask);      //清空捕捉屏蔽字
    new.sa_flags = 0;               //0 默认操作(屏蔽本信号)设置捕捉屏蔽字
    sigaction(SIGCHLD,&new,&old);   //信号SIGCHLD 子进程状态变化

4.再解除阻塞

    sigprocmask(SIG_UNBLOCK,&set, NULL);//解除屏蔽(处理一次)

关于sigaction与struct sigaction

注意3点

    new.sa_handler = er;            //执行函数名
    sigemptyset(&new.sa_mask);      //清空捕捉屏蔽字
    new.sa_flags = 0;               //0 默认操作(屏蔽本信号)设置捕捉屏蔽字

函数原型(详解struct sigaction)

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

struct sigaction
{
    1:
    void        (*sa_handler)(int);
    //指定信号捕捉后的处理函数名(即注册函数)。也可赋值为 SIG_IGN表忽略 或 SIG_DFL 表执行默认动作
            
    2:
    sigset_t    sa_mask;
    //sa_mask: 调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。注意:仅在处理函数被调用期间屏蔽生效,是临时性设置
            
    3:
    int         sa_flags;
    //sa_flags:通常设置为 0,表使用默认属性
    //重启函数 SA_INTERRURT 不重启。 SA_RESTART 重启
            
    other:
    //      void  (*sa_sigaction )(int, siginfo_t *, void *);(进程间通信)
    //      void  (*sa_restorer)(void);
}