关于sigsuspend() 这个函数想了很久,终于想明白了,这里写下自己的心得与体会。
有的是参考别人的帖子,加上自己的程序的调试!
事实求是:首先来代码,离开代码都是浮云!
code1:
#include "../../include/apue.h"
#include "../../include/error.c"
#include "../../include/prmask.c"
static void sig_int(int);
int main(void)
{
sigset_t newmask, oldmask, waitmask;
if (signal(SIGINT, sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
sigemptyset(&oldmask);
sigaddset(&oldmask,SIGUSR1);
sigemptyset(&waitmask);
sigaddset(&waitmask,SIGUSR2);
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) //set thecurrent maskin the process,oldmask=SIGSUR1
sys_sys("SIG_SETMASK error");
/* block SIGINT and save current signal mask */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) //newmask=SIGINT,oldmask=SIGINT,SIGUSR1;
err_sys("SIG_BLOCK error");
/* critical region of code */
pr_mask("in critical region: "); //output: in critical region:SIGINT,SIGUSR1;
/* allow all signals and pause */
if (sigsuspend(&waitmask) != -1) //waitmask=SIGUSR2,This is wait for the other mask set in the current mask in the process.
err_sys("sigsuspend error");
pr_mask("after return from sigsuspend: "); //output:after return from sigsuspend:SIGINT,SIGUSR1;
/* reset signal mask which unblocks SIGINT */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) //oldmask=SIGUSR1;
err_sys("SIG_SETMASK error");
/* and continue processing ... */
pr_mask("oldmask in process :"); //output:oldmask in process :SIGUSR1;
exit(0);
}
static void sig_int(int signo)
{
pr_mask("\nin sig_int: "); //output: in sig_int:SIGUSR2;
}
#gcc -g -o other_test_10.15 other_test_10.15.c
./other_test_10.15
output:
in critical region: SIGINT SIGUSR1
Ctrl+C
in sig_int: SIGUSR2
after return from sigsuspend: SIGINT SIGUSR1
oldmask in process :SIGUSR1
code2:
#include "../../include/apue.h"
#include "../../include/error.c"
#include "../../include/prmask.c"
static void sig_int(int);
int main(void)
{
sigset_t newmask, oldmask, waitmask;
if (signal(SIGINT, sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
sigemptyset(&oldmask);
sigaddset(&oldmask,SIGUSR1);
sigemptyset(&waitmask);
sigaddset(&waitmask,SIGUSR2);
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) //set the current mask in the process,oldmask=SIGSUR1
err_sys("SIG_SETMASK error");
/* block SIGINT and save current signal mask */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) //newmask=SIGINT,oldmask=SIGINT,SIGUSR1;
err_sys("SIG_BLOCK error");
/* critical region of code */
pr_mask("in critical region: "); //output: in critical region:SIGINT,SIGUSR1;
/* allow all signals and pause */
if (sigsuspend(&newmask) != -1) //newmask=SIGINT
err_sys("sigsuspend error");
pr_mask("after return from sigsuspend: "); //output:after return from sigsuspend:SIGINT,SIGUSR1;
/* reset signal mask which unblocks SIGINT */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) //oldmask=SIGUSR1;
err_sys("SIG_SETMASK error");
/* and continue processing ... */
pr_mask("oldmask in process :"); //output:oldmask in process :SIGUSR1;
exit(0);
}
static void sig_int(int signo)
{
pr_mask("\nin sig_int: "); //output: in sig_int:SIGINT;
}
#gcc -g -o other_test_10.15_1 other_test_10.15_1.c
#./other_test_10.15_1
output:
in critical region: SIGINT SIGUSR1
Ctrl+C(没有反应)
上面发出信号SIGINT没有反应的原因是,存在这一句 if (sigsuspend(&newmask)!= -1) //newmask=SIGINT; 它将信号SIGINT挂断了,所以按下Crtl+C键则没有反应,要理解好sigsuspend的意思!!
小结:
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,调用该进程设置的信号处理函数;
(3) 待信号处理函数返回后,恢复原先mask;
(4) sigsuspend返回。