#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
sigsuspend为原子操作,先解除原先的block信号,然后进程的信号屏蔽字设置为sigmask,然后挂起,当从sissuspend函数返回时在恢复为原先的mask。
之所以存在sigsuspend函数是为了防止在解除mask和pause之间产生信号,而pause之后却再也得不到信号,导致进程一直挂起。
一、源代码:
cat -n 10_22.c 10_14.c
1 #include "apue.h"
2
3 static void sig_int(int);
4
5 int main(void)
6 {
7 sigset_t newmask,oldmask,waitmask;
8 pr_mask("Begin of main:");
9 if (signal(SIGINT,sig_int) == SIG_ERR)
10 err_sys("Establish SIGINT handler failed");
11
12 sigemptyset(&waitmask);
13 sigaddset(&waitmask,SIGUSR1);
14 sigemptyset(&newmask);
15 sigaddset(&newmask,SIGINT);
16
17 if (sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)
18 err_sys("SIG_BLOCK error");
19 pr_mask("in critical region: ");
20
21 if (sigsuspend(&waitmask) != -1)
22 err_sys("sigsuspend error");
23
24 pr_mask("after return from sigsuspend: ");
25
26 if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)
27 err_sys("SIG_SETMASK error");
28
29
30 pr_mask("program exit: ");
31 exit(0);
32 }
33
34
35 static void sig_int(int signo)
36 {
37 pr_mask("\nin sig_int: ");
38 }
1 #include "apue.h"
2 #include <errno.h>
3
4 void pr_mask(const char *str)
5 {
6 int saved_errno;
7 sigset_t sigset;
8
9 saved_errno = errno;
10 if (sigprocmask(0,NULL,&sigset) < 0){
11 err_ret("sigpromask error");
12 }
13 else{
14 printf("%s",str);
15 if (sigismember(&sigset,SIGUSR2))
16 printf(" SIGUSR2");
17 if(sigismember(&sigset,SIGINT))
18 printf(" SIGINT");
19 if(sigismember(&sigset,SIGQUIT))
20 printf(" SIGQUIT");
21 if(sigismember(&sigset,SIGUSR1))
22 printf(" SIGUSR1");
23 if (sigismember(&sigset,SIGALRM))
24 printf(" SIGALRM");
25
26
27 printf("\n");
28 }
29 errno = saved_errno;
30 }
二、编译执行。
因为操作系统的原因,我的机器上正在处理的信号不阻塞,所以in sig_int: SIGUSR1 只有SIGUSR1 没有SIGINT.
gcc -Wall -ggdb3 error.c 10_22.c 10_14.c -o suspend
:./suspend
Begin of main:
in critical region: SIGINT
^C
in sig_int: SIGUSR1
after return from sigsuspend: SIGINT
program exit: