用于在接受到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。 1 /*The sigsuspend() function replaces the current signal mask of the calling thread with the set of signals pointed 2 to by sigmask and then suspends the thread until delivery of a signal whose action is either to execute a signal-catching 3 function or to terminate the process. This will not cause any other signals that may have been pending on the process to 4 become pending on the thread. 5 If the action is to terminate the process then sigsuspend() will never return. If the action is to execute a signal-catching 6 function, thensigsuspend() will return after the signal-catching function returns, with the signal mask restored to the set 7 that existed prior to thesigsuspend() call. 8 It is not possible to block signals that cannot be ignored. This is enforced by the system without causing an error to be indicated.*/
Stevens在《Unix环境高级编程》一书中是如是回答的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由于sigsuspend是原子操作,所以这句给人的感觉就是先调用signal handler先返回,然后sigsuspend再返回。 9 int main(void) { 10 sigset_t newmask, oldmask, zeromask; 11 12 if (signal(SIGINT, sig_int) == SIG_ERR) 13 err_sys("signal(SIGINT) error"); 14 15 sigemptyset(&zeromask); 16 17 sigemptyset(&newmask); 18 sigaddset(&newmask, SIGINT); 19 /* block SIGINT and save current signal mask */ 20 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 21 err_sys("SIG_BLOCK error"); 22 23 /* critical region of code */ 24 pr_mask("in critical region: "); 25 26 /* allow all signals and pause */ 27 if (sigsuspend(&zeromask) != -1) 28 err_sys("sigsuspend error"); 29 pr_mask("after return from sigsuspend: "); 30 31 /* reset signal mask which unblocks SIGINT */ 32 if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 33 err_sys("SIG_SETMASK error"); 34 35 /* and continue processing ... */ 36 exit(0); 37 } 38 39 static void sig_int(int signo) { 40 pr_mask("\nin sig_int: "); 41 return; 42 }
43 $a.out 44 in critical region: SIGINT 45 ^C 46 in sig_int: SIGINT 47 after return from sigsuspend: SIGINT 如果按照sig_handler先返回,那么SIGINT是不该被打印出来的,因为那时屏蔽字还没有恢复,所有信号都是不阻塞的。那么是Stevens说错了么?当然没有,只是Stevens没有说请在sigsuspend的原子操作中到底做了什么? 48 /*The sigsuspend( ) system call puts the process in the TASK_INTERRUPTIBLE state, after having blocked the standard signals specified 49 by a bit mask array to which the mask parameter points. The process will wake up only when a nonignored, nonblocked signal is sent 50 |