程序简介:这个例子显示了保护临界区,不被特定信号中断的正确方法
//《APUE》程序10-10:为进程打印屏蔽字 //《APUE》程序10-15:保护临界区不被信号中断 #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <errno.h> //输出错误信息并退出 void error_quit(const char *str) { fprintf(stderr, "%s\n", str); exit(1); } //打印调用进程的依赖屏蔽字中信号的名称(只测试了我们用到的几种) void pr_mark(const char *str) { sigset_t sigset; int error_save; error_save = errno; int temp = sigprocmask(0, NULL, &sigset); if( temp < 0 ) error_quit("sigpromask error"); printf("%s", str); if( sigismember(&sigset, SIGINT) ) printf("SIGINT "); if( sigismember(&sigset, SIGQUIT) ) printf("SIGQUIT "); if( sigismember(&sigset, SIGUSR1) ) printf("SIGUSR1 "); if( sigismember(&sigset, SIGALRM) ) printf("SIGALRM "); printf("\n"); errno = error_save; } void sig_int(int signo) { pr_mark("\nin sig_int: "); } int main(void) { sigset_t newmask, oldmask, waitmask; pr_mark("program start: "); //设置对SIGINT信号的处理函数 if( SIG_ERR == signal(SIGINT, sig_int) ) error_quit("signal(SIGINT) error"); //将waitmask信号集初始化为空 sigemptyset(&waitmask); //在waitmask信号集中增加SIGUSR1信号 sigaddset(&waitmask, SIGUSR1); //将newmask信号集初始化为空 sigemptyset(&newmask); //在newmask信号集中增加SIGINT信号 sigaddset(&newmask, SIGINT); //将oldmask设置为当前的屏蔽信号集(方便以后恢复) //在当前的屏蔽信号添加增加newmask信号集 int temp = sigprocmask(SIG_BLOCK, &newmask, &oldmask); if( temp < 0 ) error_quit("SIG_BLOCK error"); pr_mark("in critical region: "); //这段操作比较难理解,请见注解2 //进入临界区,等待SIGINT信号 temp = sigsuspend(&waitmask); if( temp != -1 ) error_quit("sigsuspend error"); //收到SIGINT信号后,离开临界区 pr_mark("after return from sigsuspend: "); //恢复屏蔽信号集 temp = sigprocmask(SIG_SETMASK, &oldmask, NULL); if( temp < 0 ) error_quit("SIG_SETMASK error"); pr_mark("program exit: "); return 0; }