子进程执行完毕后,会向父进程发出 SIGCHLD信号 , 这段代码实现的就是i,父进程接受到子进程 发出的SIGCHLD信号,实现对子进程进行回收,从而避免僵尸进程
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>void catch(int sigNum) {pid_t wpid;// 这里之所以写成while循环的方式, // 是为了应对当多个子进程——同时——发出SIGCHLD信号的时候,主进程能够// 将所有发出SIGCHLD信号的子进程回收掉while( (wpid = waitpid(-1, NULL, WNOHANG)) > 0) {printf("father wait son pid is %d\n", wpid);}
}int main() {// 因为主进程 在注册 SIGCHLD信号处理的时候,子进程可能已经执行//完毕,子进程发出SIGCHLD信号的时候,早于主进程对SIGCHLD处理的注册// 这时候首先 在主进程 ,设置 SIGCHLD为屏蔽信号(屏蔽信号集),这样就影响了// 主进程的未决信号集,使主进程的未决信号集,SIGCHLD对应的位置为1,sigset_t myset, oldset;sigemptyset(&myset);sigaddset(&myset, SIGCHLD);sigprocmask(SIG_BLOCK, &myset, &oldset);pid_t pid;int i;for(i=0; i<10; ++i) {pid = fork();if(pid == 0) {break;}}if(i == 10) {// father// 模拟先让子进程执行完毕,主进程再注册 SIGCHLD信号处理函数sleep(2);struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = catch;sigaction(SIGCHLD, &act, NULL);// 当主进程注册了 SIGCHLD的时候,将屏蔽信号集恢复,// 进而 ,主进程的未决信号集,SIGCHLD的那个,也会处理, 由1变为0,从而触发 处理函数,回收子进程sigprocmask(SIG_SETMASK, &oldset, NULL);while (1) {sleep(1);}} else if(i < 10) {// sonprintf("I am son process pid is %d\n", getpid());}return 0;
}