基本概念:
原理就是捕获SIGCHLD信号,通过waitpid函数处理子进程退出,直接上代码:
----- gcc fork_one.c -----
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
void sig_chld(int signo)
{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) //while循环是表示处理所有待处理的信号,-1表示任意子进程,WNOHANG表示非阻塞
printf("child %d terminated\n", pid);
return;
}
int main()
{
signal(SIGCHLD, sig_chld);
pid_t cli = fork();
if (cli > 0) {
printf("I am father\n");
} else {
printf("I am child\n");
_exit(0);
}
while (1) {
sleep(1);
}
}
ps:还有一种办法就是双重fork,让子进程fork孙子进程,然后让子进程退出,孙子进程归init进程托管。
----- gcc fork_two.c -----
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void Perror(const char *s)
{
perror(s);
exit(EXIT_FAILURE);
}
int main()
{
pid_t pid;
if ((pid = fork()) < 0) {
Perror("fork error");
} else if (pid == 0) { /* first child */
if ((pid = fork()) < 0) {
Perror("fork error");
} else if (pid > 0) {
exit(0); /* parent from second fork == first child */
}
sleep(2);
printf("second child pid = %ld, parent pid = %ld\n",
(long)getpid(), (long)getppid());
exit(0);
}
if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
Perror("waitpid error");
printf("parent for first child exit\n");
exit(0);
}
参考:《unix网络编程》·卷1、《unix环境高级编程》·第三版