由于 SIGINT 在您调用 select 时被阻塞,因此它不会被传递并且select()
不会被中断。如果您的处理程序只是调用exit()
并且即使在您的代码调用 select 时您也想要这个,最好的解决方案是不理会信号掩码。如果您出于某种原因不希望在调用时调用您的普通处理程序,则select()
可以使用该pselect()
函数。
编辑:
什么时候发出信号
如果信号已启用(即未阻塞)并且进程正在运行,则立即。
如果启用了信号并且进程在可中断的睡眠中睡眠(这意味着 top/ps 输出中的 state==S),则系统调用被中断(例如,通过将 EINTR 返回给调用者)并执行信号处理程序。
如果信号被阻塞,它会等待一旦被解除阻塞就被传递。系统调用不会被阻塞信号打断。
在您的示例中,这意味着select()
正在等待输入;当输入可用时,它返回,信号处理程序被启用(在对 sigprocmask 的第二次调用中)并调用处理程序。
这是它在 strace 中的样子:
Process 22393 attached - interrupt to quit
19:31:05.844940 select(1, [0], NULL, NULL, NULL) = 1 (in [0])
19:31:12.131431 rt_sigprocmask(SIG_UNBLOCK, [INT TERM], [INT TERM], 8) = 0
19:31:12.131560 --- SIGINT (Interrupt) @ 0 (0) ---
19:31:12.131730 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
19:31:12.131871 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ffb000
19:31:12.132027 write(1, "signal..."..., 9) = 9
19:31:12.132148 exit_group(1) = ?
Process 22393 detached
如何启用信号
要始终启用信号处理程序,只需sigprocmask()
从代码中删除对的调用。