如果父进程在子进程之前终止,子进程先成为孤儿进程,此后子进程的父进程将变为init进程。我们称这些进程由init进程领养。其操作过程大致是:在一个进程终止时,内核逐个检查所有活动进程,以判断它是否是正要终止的进程的子进程,如果是,则该进程的父进程ID就更改为1(init进程的ID)。这种处理方法保证了每个进程有一个父进程。
如果子进程在父进程之前终止,那么父进程又如何能在做相应检查时得到子进程的终止状态呢?内核为每个终止子进程保存了一定量的信息,当终止进程的父进程调用wait或waitpid 时,可以得到有关信息。这种信息至少包括进程I D、该进程的终止状态、以反该进程使用的CPU时间总量。内核可以释放终止进程所使用的所有存储器,关闭其所有打开文件。在UNIX中,一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息、释放它仍占用的资源)的进程被称为僵死进程。如果编写一个长期运行的程序,它fork了很多子进程,那么除非父进程等待取得子进程的终止状态,否则这些子进程就会变成僵死进程。
实例代码(孤儿进程):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid = fork();
if(pid == 0)
{
printf("before father end\n");
printf("my process id is %d, my father is %d\n", getpid(), getppid());
sleep(10);
printf("after father end\n");
printf("my process id is %d, my father is %d\n", getpid(), getppid());
}
else if(pid > 0)
{
sleep(5);
}
else
{
printf("error");
}
return 0;
}
代码分析:
程序中,子进程挂起10秒,父进程挂起5秒,以保证父进程先于子进程结束。
运行结果:
结果分析:
这里可能会感到奇怪,不是说应该是由进程ID为1的init进程来接管孤儿进程吗?这是因为实验环境的关系,在我的实验环境Ubuntu中,系统使用进程upstart代替init来接管了孤儿进程。我们可以通过ps axu|grep 1364来查看指定进程ID的具体信息,如下:
实例代码(僵死进程):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid = fork();
if(pid == 0)
{
sleep(5);
}
else if(pid > 0)
{
sleep(10);
}
else
{
printf("error");
}
return 0;
}
代码分析:
程序中,子进程挂起5秒,父进程挂起10秒,以保证子进程先于父进程结束。
运行结果(状态为Z+的即表示僵死进程):