首页 > 代码库 > APUE读书笔记:关于sigsuspend
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\n"); 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("\n");}
运行:先ctrl+C(发送SIGINT信号),后发送信号SIGUSR1(kill -SIGUSR1 pid)
输出:
Before suspend:^Cproc_usr1In sigusr1::SIGUSR1 SIGINT
输出解释:第一行输出表示该进程未设置信号屏蔽字
第二行看到Ctrl+c的信号,之后的是信号响应函数proc_usr1的输出
第三行也是proc_usr1的输出当前进程的屏蔽字有SIGINT(由sigsuspend设置),还有SIGUSR1(不懂为啥SIGUSR1也会出现在当前屏蔽字中)
对于上面的问题:为啥SIGUSR1也会出现在当前屏蔽字中?
假设当前进程接受到了SIGUSR1信号,进入proc_usr1的信号处理函数,在函数执行期间,又收到了一个SIGUSR1信号,进程会怎么处理呢?
os应该先接受该信号,在SIGUSR1的响应函数结束后,os把该信号扔到当前进程,当前进程继续响应该SIGUSR1。
这样就能够解释了为啥SIGUSR1信号被屏蔽了,再某个信号的响应函数内,该信号一定会被设置为阻塞的,即响应函数处理时间内当前进程不要响应该信号。