在 Linux/Unix 系統中,進程關係鏈的動態變化造就了「孤兒進程」與「殭屍進程」兩種特殊狀態。本文先講孤兒進程:父進程先於子進程終止,子進程被 init 進程(PID 1)收養。
exit() 終止。ppid 設為 1(init)。#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
} else if (pid == 0) { // 子進程
printf("pid=%d, ppid=%d\n", getpid(), getppid()); // 出生時的父進程
sleep(2); // 確保父進程先退出
printf("pid=%d, ppid=%d\n", getpid(), getppid()); // 被收養後的父進程
} else {
exit(0); // 父進程立即退出
}
return 0;
}
$ ./a.out
pid=1091, ppid=1090 // 初始父進程 PID 1090
pid=1091, ppid=1 // 2 秒後,父進程變為 init (PID 1)
getpid():取得當前進程 ID。getppid():取得父進程 ID。內核在每次進程退出時,會遍歷任務鏈表,將該進程的所有子進程 ppid 重置為 1。init 進程會週期性調用 wait() 清理已終止的孤兒進程,因此孤兒進程不會造成資源洩漏。
下一篇將詳細剖析「殭屍進程」:子進程先退出、父進程未回收的危險狀態,以及如何避免 PID 耗盡。