Linux 信号(二)信号集 青旅半醒 2022-06-14 08:13 208阅读 0赞 # 信号集 # 信号集可以用来表示一组信号,用`sigprocmask`系列函数可以让应用程序对一些信号进行屏蔽。 类似于`select`调用中的`fd_set`一个信号对应一个比特位。 在信号中,这样的数据结构用`sigsetg_t`表示。 #include <signal.h> int sigemptyset(sigset_t *set); //初始化set指向的信号集,使其为空 int sigfillset(sigset_t *set); //初始化set指向的信号集,使其包含所有信号 int sigaddset(sigset_t *set, int signum); // 添加一个信号 int sigdelset(sigset_t *set, int signum); //删除一个信号 int sigismember(const sigset_t *set, int signum);//测试指定位 回忆`pause()`函数: pause() causes the calling process (or thread) to sleep until a signal is delivered that either terminates the process or causes the invoca‐ tion of a signal-catching function. 进程阻塞在`pause`调用,直到收到信号。这个时候进程可能进入信号处理函数,也可能直接终止。 而`sigpending`和`sigprocmask`就可以对某些信号进行屏蔽。 为了查看当前哪些信号被屏蔽,引入了apue中的一个库函数: 核心思想就是利用`sigismember`查看信号是否在屏蔽信号集中 void pr_mask(const char *str) { sigset_t sigset; int errno_save; errno_save = errno; /* we can be called by signal handlers */ if (sigprocmask(0, NULL, &sigset) < 0) { //获取当前oldset err_ret("sigprocmask error"); } else { 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"); /* remaining signals can go here */ printf("\n"); } errno = errno_save; /* restore errno */ } 上文提到的`sigprocmask`函数 #include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); 第一个参数表示取值有三个: > SIG\_BLOCK:屏蔽信号,添加的信号屏蔽字不覆盖之前的,这是一个并集的关系 > SIG\_UNBLOCK:希望解除BLOCK的信号集合。 > SIG\_SETMASK:该进程的信号屏蔽是set指向的值。 注意到这里后两个参数,`set`用以设置新的信号屏蔽字,`oldset`返回当前信号屏蔽字。 如果不进行设置,仅仅只是想得到当前的信号屏蔽字,那么前两个参数也就没有意义了。 sigprocmask(0,NULL,&sigset); `sigprocmask`仅仅是对屏蔽字进行设置,程序将继续执行,`sigpending`将设置屏蔽字,同时阻塞。 就像执行了两步操作: //第一步 sigprocmask(); //第二步 pause(); 设置之后,除了屏蔽字中的信号,其他信号都能收到,此时要么进入信号处理函数,要么程序直接终止。 下面一段代码将测试`sigprocmask`和`sigpending`函数,完整代码:[github][] 可以用`kill -[信号] [pid]`进行测试 #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <sys/time.h> #include <malloc.h> #include <signal.h> static void sig_int(int signo) { pr_mask("\nin sig_int: "); } static void sig_quit(int signo) { pr_mask("\nin sig_quit: "); } int main(int argc,char **argv) { sigset_t newmask, oldmask, waitmask; pr_mask("program start: "); if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); if(signal(SIGQUIT,sig_quit)==SIG_ERR) err_sys("signal(SIGQUIT) error"); //init to zero sigemptyset(&waitmask); //add SIGUSR1 sigaddset(&waitmask, SIGUSR1); //init to zero sigemptyset(&newmask); //add SIGINT sigaddset(&newmask, SIGINT); //BLOCK SIGINT and save current sigsets if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); // sleep(10);//will not receive SIGINT #if 1 /* * Critical region of code. */ pr_mask("in critical region: "); /* * Pause, allowing all signals except SIGUSR1. */ if (sigsuspend(&waitmask) != -1) err_sys("sigsuspend error"); pr_mask("after return from sigsuspend: "); /* * Reset signal mask which unblocks SIGINT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); /* * And continue processing ... */ pr_mask("program exit: "); #endif return 0; } PS: 在终端输入`kill -l`可以查看各个信号对应的编号: 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX [github]: https://github.com/NearXdu/APUE
还没有评论,来说两句吧...