APUE读书笔记:关于sigsuspend

sigsuspend是一个原子操作,为了防止信号丢失而存在的,具体含义看下函数原型。

int sigsuspend(const sigset_t *mask);

先忽略参数,sigsuspend完成的操作是阻塞进程的运行,直到有信号的产生。这样来看与另一个函数的作用相同。pause()

加上参数来理解,sigsuspend完成的操作是阻塞进程的运行,如果信号是mask参数设置的信号集,那么该信号是pending状态,而不会影响进程的阻塞状态,意思是进程仍然在阻塞中,直到不在信号集中的信号出现,进程能够继续执行。注意:如果之前确实有在mask信号集中的信号出现,该信号会在sigsuspend函数返回后被进程所捕获,完成自定义的或者默认的信号响应函数。

实验:sigsuspend对SIGINT信号设置屏蔽,在阻塞期间先发送SIGINT信号,再发送SIGUSR1信号

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

static int proc_sig=0;
sigset_t zeromask;

void pr_mask(const char* str);

void proc_usr1(int)
{
    printf("proc_usr1
");
    pr_mask("In sigusr1:");
};


int main()
{
    sigset_t sigset, oldmask, waitmask;
    
    signal(SIGUSR1, proc_usr1);

    sigprocmask(0, NULL, &oldmask);

    //sigaddset(&sigset, SIGUSR1); 
    //sigprocmask(SIG_BLOCK, &sigset, NULL);
    //pr_mask("Block SIGUSR1");

    pr_mask("Before suspend");

    sigaddset(&waitmask, SIGINT);
    sigsuspend(&waitmask);

    pr_mask("After suspend:");

    //sleep(12);
    //sigprocmask(SIG_UNBLOCK, &sigset, NULL);
    //pr_mask("Unblock SIGUSR1");

    sleep(12);

    return 0;
}

void pr_mask(const char * str)
{
    sigset_t sigset;
    sigprocmask(0, NULL, &sigset);

    printf("%s:", str);

    if (sigismember(&sigset, SIGCHLD)) printf("SIGCHLD ");
    if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
    if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
    if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
    if (sigismember(&sigset, SIGSTOP)) printf("SIGSTOP ");
    if (sigismember(&sigset, SIGKILL)) printf("SIGKILL ");
if (sigismember(&sigset, SIGINT)) printf("SIGINT "); printf(
" "); }

运行:先ctrl+C(发送SIGINT信号),后发送信号SIGUSR1(kill -SIGUSR1 pid)

输出:

Before suspend:
^Cproc_usr1
In sigusr1::SIGUSR1 SIGINT

输出解释:第一行输出表示该进程未设置信号屏蔽字

第二行看到Ctrl+c的信号,之后的是信号响应函数proc_usr1的输出

第三行也是proc_usr1的输出当前进程的屏蔽字有SIGINT(由sigsuspend设置),还有SIGUSR1(不懂为啥SIGUSR1也会出现在当前屏蔽字中)

对于上面的问题:为啥SIGUSR1也会出现在当前屏蔽字中?

假设当前进程接受到了SIGUSR1信号,进入proc_usr1的信号处理函数,在函数执行期间,又收到了一个SIGUSR1信号,进程会怎么处理呢?

os应该先接受该信号,在SIGUSR1的响应函数结束后,os把该信号扔到当前进程,当前进程继续响应该SIGUSR1。

这样就能够解释了为啥SIGUSR1信号被屏蔽了,再某个信号的响应函数内,该信号一定会被设置为阻塞的,即响应函数处理时间内当前进程不要响应该信号。

原文地址:https://www.cnblogs.com/helww/p/3815202.html