我很好奇,如果一个进程的父进程不关心它,那么这个僵尸进程会发生什么。
假设我们有一个父进程和一个子进程。子进程在父进程之前终止。
根据APUE:
内核为每个终止的进程保留少量信息...最小限度包括进程ID、进程的终止状态...
父进程需要使用waitpid()
获取此信息。
但是,如果父进程在没有等待子进程的情况下退出,会发生什么:
内核是否删除此信息(显然没有用)?
还是一直收集这些垃圾?
这是特定于实现的吗?
还是有一种标准方法来处理这种情况?
我很好奇,如果一个进程的父进程不关心它,那么这个僵尸进程会发生什么。
假设我们有一个父进程和一个子进程。子进程在父进程之前终止。
根据APUE:
内核为每个终止的进程保留少量信息...最小限度包括进程ID、进程的终止状态...
父进程需要使用waitpid()
获取此信息。
但是,如果父进程在没有等待子进程的情况下退出,会发生什么:
内核是否删除此信息(显然没有用)?
还是一直收集这些垃圾?
这是特定于实现的吗?
还是有一种标准方法来处理这种情况?
孤儿进程会自动被init
接管,它有一个标准的SIGCHLD
处理程序,只会丢弃已死进程的任何退出状态。
在你的情况下,如果僵尸进程的父进程死亡,则将由init接管并清理该僵尸进程。
以下代码测试了这一点:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t child_pid;
if (child_pid = fork()) { // fork a child, child will exit straight away
char name[128];
sprintf(name, "/proc/%d/stat", child_pid);
char line[2048];
// read childs /proc/pid/stat, field 3 will give its status
FILE * fp = fopen(name, "r");
while (fgets(line, sizeof(line), fp))
puts(line);
fclose(fp);
usleep(5000000);
// by now the child will have exited for sure, repeat
fp = fopen(name, "r");
while (fgets(line, sizeof(line), fp))
puts(line);
fclose(fp);
// make another child to repeat the process and exit the parent
if (!fork()) {
usleep(5000000);
// both parent and child will have exited by now
fp = fopen(name, "r");
// this should fail because init has already cleaned up the child
if (!fp) {
perror("fopen");
return -1;
}
while (fgets(line, sizeof(line), fp))
puts(line);
fclose(fp);
}
}
return 0;
}
SIGCHLD
信号是否仍会生成?我认为当子进程终止时会生成该信号(如果我错了请纠正我)。 - mohitinit
会清理子进程并丢弃其退出状态。整个被init
收养是为了确保孤儿僵尸不会停留在系统中。 - Sergey L.SIGCHLD
- init
定期等待所有子进程清理它们(如果需要)。来自:http://en.wikipedia.org/wiki/Zombie_process - Sergey L.
init进程
成为子进程的父进程,init
从进程表中清除条目。 - Grijesh Chauhan