在《 CSAPP 》中有一个简单的 signal 示例程序。我在 Ubuntu 里编译运行相同的代码,得到的结果和书上给出的结果不一样,并且就是在最关键的一个地方不一样:信号不排队。
而我在自己的机器上编译运行结果:
按照书里面的说法,Handler reaped child 这一项应该只出现两次。
#include "csapp.h" /* $begin signal1 */ /* WARNING: This code is buggy! */ void handler1(int sig) { int olderrno = errno; if ((waitpid(-1, NULL, 0)) < 0) sio_error("waitpid error"); Sio_puts("Handler reaped child\n"); Sleep(1); errno = olderrno; } int main() { int i, n; char buf[MAXBUF]; if (signal(SIGCHLD, handler1) == SIG_ERR) unix_error("signal error"); /* Parent creates children */ for (i = 0; i < 3; i++) { if (Fork() == 0) { printf("Hello from child %d\n", (int)getpid()); exit(0); } } /* Parent waits for terminal input and then processes it */ if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0) unix_error("read"); printf("Parent processing input\n"); while (1) ; exit(0); } /* $end signal1 */
![]() | 1 redsonic 2018-08-06 00:15:27 +08:00 ![]() 内核中的信号处理和进程调度有关联性,一般都是计时上的问题,我试了两台空闲的都和书上的一样,打印两次。然后生成子进程的时候延迟错开一下就打印三次了,exit 的时候不容易撞到。不必纠结,也许你系统繁忙 /空闲的时候结果会不一样,明白道理就行了。 /* Parent creates children */ for (i = 0; i < 3; i++) { usleep(100) if (Fork() == 0) { |
2 manifold 2018-08-06 02:19:35 +08:00 via Android 这个本身就取决于进程调度(因为 signal 是在陷入内核是 handle 的)。。所以理论上可以出现各种情况。因此要用 waitpid 来回收 zombie processes |
![]() | 3 ryd994 2018-08-06 02:21:44 +08:00 via Android 你是不是在虚拟机里,而且是单核虚拟机? |
![]() | 5 ryd994 2018-08-06 06:50:09 +08:00 via Android |