1.僵尸进程
在父进程执行wait()之前,其子进程就已终止, 即使子进程终止,系统也允许父进程在以后的某个时刻去执行wait(),以确定子进程是如何终止。内核通过将子进程转为僵尸进程,以释放其占用的系统资源,供其他进程使用,该进程唯一保留的是系统PCB中的一条记录,其中包含了子进程的ID,终止状态,和资源使用的数据。当父进程再次调用wait(),内核进程表中将删除该记录,如果父进程终止,init进程会自动调用wait(),以删除该记录.
2.孤儿进程
父进程在子进程之前退出或者终止,init进程会接管其子进程,此时子进程调用getppid()得到的是1,子进程终止,init会自动调用wait()。
3.僵尸进程示例
#include <signal.h>
#include <libgen.h> /* For basename() declaration */
#include "tlpi_hdr.h"
#define CMD_SIZE 200
int main(int argc, char *argv[])
{
char cmd[CMD_SIZE];
pid_t childPid;
setbuf(stdout, NULL); /* Disable buffering of stdout */
printf("Parent PID=%ld\n", (long) getpid());
switch (childPid = fork()) {
case -1:
errExit("fork");
case 0: /* Child: immediately exits to become zombie */
printf("Child (PID=%ld) exiting\n", (long) getpid());
_exit(EXIT_SUCCESS);
default: /* Parent */
sleep(3); /* Give child a chance to start and exit */
snprintf(cmd, CMD_SIZE, "ps | grep %s", basename(argv[0]));
system(cmd); /* View zombie child */
/* Now send the "sure kill" signal to the zombie */
if (kill(childPid, SIGKILL) == -1)
errMsg("kill");
sleep(3); /* Give child a chance to react to signal */
printf("After sending SIGKILL to zombie (PID=%ld):\n", (long) childPid);
system(cmd); /* View zombie child again */
exit(EXIT_SUCCESS);
}
}
$ ./make_zombie
Parent PID=61272
Child (PID=61273) exiting
61272 pts/1 00:00:00 make_zombie
61273 pts/1 00:00:00 make_zombie <defunct>
After sending SIGKILL to zombie (PID=61273):
61272 pts/1 00:00:00 make_zombie
61273 pts/1 00:00:00 make_zombie <defunct>