#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
void printffun(signum)
{
printf("catch the signal %d", signum);
return;
}
int main()
{
pid_t pid = 0; //进程ID
printf("Start to begin fork.\n");
/* 注册信号回调函数 */
signal(SIGHOLD,printffun);
for (;;)
{
pid = fork();
if (pid < 0)
{
printf("Failed to fork child process.\n");
}
else if (pid = 0)
{
printf("Succeed to fork child[%d] process.\n", getpid());
exit(0);
}
sleep(1);
}
return 0;
}
解决僵尸进程的方法有两种:
方法一:可以参考apue中fork两次的方法,主进程fork一个子进程,然后等待子进程退出,子进程fork一个孙子进程去执行任务,然后自己退出,这个时候主进程收到子进程退出的状态,继续往下执行,子进程退出后,孙子进程就会成为孤儿进程,我们系统是不允许孤儿进程的,除了进程ID 为1的init进程,因此当出现孤儿进程,init进程都会去接收孤儿进程,成为孤儿进程的父进程,意思就是说子进程退出,孙子进程的父进程就不再是子进程,而是init进程,因此孙子进程做完作业,进程退出的时候,他的退出状态就有init进程来接收,这样就不会出现孙子进程成为僵尸进程的状况,这也是面试的时候面试官会问服务器端要fork两次的原因。
方法二:注册消息回调函数,就像有上面的代码块写的一样,只要有子进程退出,printffun函数就会被触发,这个函数里面调用waitpid函数就可以接收子进程的退出状态了,现在的printffun函数里面没有调用waitpid,只是打了一次语句,表示接收到了这个信号,这样也不会出现僵尸进程,但这个函数也有一个问题,那就是原本主进程fork子进程之后,会sleep一秒钟,但是现在有了signal函数,如果接收到了信号,会打断sleep状态,转而执行printffun函数,执行完成以后就继续往下走,不会再次进程sleep状态,完成没有睡眠的时间,因此执行这个函数,会出现一秒钟内fork了很多次,并没有sleep一秒钟就是这个原因。