🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # SIGCHLD信号 ## SIGCHLD信号产生的条件 1) 子进程终止时 2) 子进程接收到SIGSTOP信号停止时 3) 子进程处在停止态,接受到SIGCONT后唤醒时 ## 如何避免僵尸进程 1) 最简单的方法,父进程通过 wait() 和 waitpid() 等函数等待子进程结束,但是,这会导致父进程挂起。 2) 如果父进程要处理的事情很多,不能够挂起,通过 signal() 函数人为处理信号 SIGCHLD , 只要有子进程退出自动调用指定好的回调函数,因为子进程结束后, 父进程会收到该信号 SIGCHLD ,可以在其回调函数里调用 wait() 或 waitpid() 回收。 ~~~ void sig_child(int signo) { pid_t pid; ​ //处理僵尸进程, -1 代表等待任意一个子进程, WNOHANG代表不阻塞 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { printf("child %d terminated.\n", pid); } } ​ int main() { pid_t pid; ​ // 创建捕捉子进程退出信号 // 只要子进程退出,触发SIGCHLD,自动调用sig_child() signal(SIGCHLD, sig_child); ​ pid = fork(); // 创建进程 if (pid < 0) { // 出错 perror("fork error:"); exit(1); } else if (pid == 0) { // 子进程 printf("I am child process,pid id %d.I am exiting.\n", getpid()); exit(0); } else if (pid > 0) { // 父进程 sleep(2); // 保证子进程先运行 printf("I am father, i am exited\n\n"); system("ps -ef | grep defunct"); // 查看有没有僵尸进程 } ​ return 0; } ~~~ 3)如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD, SIG\_IGN)通知内核,自己对子进程的结束不感兴趣,父进程忽略此信号,那么子进程结束后,内核会回收, 并不再给父进程发送信号。 ~~~ int main() { pid_t pid; ​ // 忽略子进程退出信号的信号 // 那么子进程结束后,内核会回收, 并不再给父进程发送信号 signal(SIGCHLD, SIG_IGN); ​ pid = fork(); // 创建进程 ​ if (pid < 0) { // 出错 perror("fork error:"); exit(1); } else if (pid == 0) { // 子进程 printf("I am child process,pid id %d.I am exiting.\n", getpid()); exit(0); ​ } else if (pid > 0) { // 父进程 sleep(2); // 保证子进程先运行 printf("I am father, i am exited\n\n"); system("ps -ef | grep defunct"); // 查看有没有僵尸进程 } ​ return 0; } ~~~