函数 sigsuspend(sigset_t *mask)
1、之前说过,更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞,这可以用来保护不希望由信号中断的代码临界区
2、如果希望对一个信号解除阻塞,然后pause以等待以前被阻塞的信号发生,如何实现呢?
若是直接 sigprocmask(); pause(); 这样可能会导致pause永久阻塞,所以可以使用此函数 sigsuspend。
进程的信号屏蔽字设置为由 sigmask 指向的值。 在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回。并且该进程的信号屏蔽字设置为调用sigsuspend之前的值。
此函数经常和pause相比较。
这段愣是没看懂,上网查了一下:
sigsuspend的原子操作是:
(1)设置新的mask阻塞当前进程(用参数替换当前屏蔽字,这里的参数屏蔽字包含SIGUSR1)
(2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask(即包含SIGINT信号的)。
(3)调用该进程设置的信号处理函数(程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)
(4)待信号处理函数返回,sigsuspend返回了。(sigsuspend将捕捉信号和信号处理函数集成到一起了)
(一) 、 Show how to protect the code area from being interrupted by unexpected signal.
1、之前说过,更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞,这可以用来保护不希望由信号中断的代码临界区
2、如果希望对一个信号解除阻塞,然后pause以等待以前被阻塞的信号发生,如何实现呢?
若是直接 sigprocmask(); pause(); 这样可能会导致pause永久阻塞,所以可以使用此函数 sigsuspend。
进程的信号屏蔽字设置为由 sigmask 指向的值。 在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回。并且该进程的信号屏蔽字设置为调用sigsuspend之前的值。
此函数经常和pause相比较。
这段愣是没看懂,上网查了一下:
sigsuspend的原子操作是:
(1)设置新的mask阻塞当前进程(用参数替换当前屏蔽字,这里的参数屏蔽字包含SIGUSR1)
(2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask(即包含SIGINT信号的)。
(3)调用该进程设置的信号处理函数(程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)
(4)待信号处理函数返回,sigsuspend返回了。(sigsuspend将捕捉信号和信号处理函数集成到一起了)
(一) 、 Show how to protect the code area from being interrupted by unexpected signal.
//
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void pr_mask(char *s)
{
printf("%s ",s);
sigset_t set;
if(sigprocmask(0,NULL,&set) < 0)
{
perror("sigprocmask");
exit(1);
}
if(sigismember(&set,SIGUSR1))
printf("SIGUSR1");
if(sigismember(&set,SIGALRM))
printf("SIGALRM");
if(sigismember(&set,SIGINT))
printf("SIGINT");
putchar('\n');
}
void sig_int(int s)
{
pr_mask("\nin sig_int");
}
void sig_usr(int s)
{
}
int main()
{
sigset_t new,old,wait;
pr_mask("program mask : ");
if(signal(SIGINT,sig_int) == SIG_ERR)
{
perror("signal");
exit(1);
}
if(signal(SIGUSR1,sig_usr) == SIG_ERR)
{
perror("signal");
exit(1);
}
sigemptyset(&wait);
sigaddset(&wait, SIGUSR1);
sigemptyset(&new);
sigaddset(&new, SIGINT);
//Block SIGINT and save curret mask
if(sigprocmask(SIG_BLOCK,&new,&old) < 0) //在原有屏蔽字中添加SIGINT
{
perror("sigprocmask");
exit(1);
}
//Critical region of code
pr_mask("in critical region"); //通过结果发现现在SIGINT是应该被阻塞在外的
//Pause, allowing all signals except SIGUSR1
if(sigsuspend(&wait) != -1) //通过sigsuspend改变当前的屏蔽字为wait的值,现在我们发送SIGINT进程可以接收了
{
perror("sigsuspend");
exit(1);
}
pr_mask("After return from suspend : "); //结果显示,这里仍然是SIGINT被包含在内
//reset signal mask which unblocks SIGINT
if(sigprocmask(SIG_SETMASK,&old,NULL) < 0)
{
perror("sigprocmask");