sigsuspend解决时序竞态问题
- 使用pause()函数, 会导致在恢复信号集之前程序挂起
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
void handler(int sig) //信号处理函数的实现
{
printf("SIGINT sig\n");
}
int main(void)
{
sigset_t new,old;
struct sigaction act;
act.sa_handler = handler; //信号处理函数handler
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, 0); //准备捕捉SIGINT信号(注册)
sigemptyset(&new);
sigaddset(&new, SIGINT);
sigprocmask(SIG_BLOCK, &new, &old); //将SIGINT信号阻塞,同时保存当前信号集
printf("Blocked\n"); //模拟阻塞了SIGINT
pause(); // 因为之前阻塞了SIGINT, 所以SIGINT在挂起期间永远不会递达, 程序将永久挂起
sigprocmask(SIG_SETMASK, &old, NULL); //恢复原阻塞信号集
printf("sigprocmask recovered\n");
return 0;
}
- 使用sigsuspend()函数在程序挂起期间临时撤销对wait信号集中的SIGUSR1以外的信号阻塞(只临时阻塞SIGUSR1), 在挂起期间, 程序可以对除SIGUSR1以外的信号(如SIGINT)进行处理, 执行sigaction
- sigsuspend实际是将临时阻塞SIGUSR1和pause结合起来原子操作
- 临时替换信号集wait和挂起是一个原子操作
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
void handler(int sig) //信号处理函数的实现
{
printf("SIGINT sig\n");
}
int main(void)
{
sigset_t new,old, wait;
struct sigaction act;
act.sa_handler = handler; //信号处理函数handler
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, 0); //准备捕捉SIGINT信号
sigemptyset(&new);
sigaddset(&new, SIGINT);
//sigprocmask作用: 改变当前进程的阻塞信号集
sigprocmask(SIG_BLOCK, &new, &old); //将SIGINT信号阻塞(模拟Ctrl+c失效),同时保存当前信号集
printf("Blocked\n"); // 模拟阻塞SIGINT(Ctrl+c), 模拟失去cpu
sigemptyset(&wait);
sigaddset(&wait, SIGUSR1);
//pause(); 是挂起期间对所有信号都响应
// 在程序挂起期间对wait(SIGUSR1)临时不响应, 而响应其他所有信号,如SIGINT, 挂起结束后恢复.
// 程序挂起期间可以不想被SIGUSR1打断
// 挂起期间可以用SIGINT(Ctrl+c)唤醒进程
sigsuspend(&wait);
sigprocmask(SIG_SETMASK, &old, NULL); //恢复原阻塞信号集
printf("sigprocmask recovered\n");
return 0;
}
446

被折叠的 条评论
为什么被折叠?



