目录
[1. 引言](#1. 引言)
[2. 进程等待的必要性](#2. 进程等待的必要性)
[3. wait 函数](#3. wait 函数)
[4. waitpid 函数](#4. waitpid 函数)
[5. 获取子进程退出状态](#5. 获取子进程退出状态)
[6. 阻塞与非阻塞等待](#6. 阻塞与非阻塞等待)
[7. 补充:孤儿进程与守护进程](#7. 补充:孤儿进程与守护进程)
[8. 总结](#8. 总结)
1. 引言
如果父进程不等待子进程退出,子进程会变成僵尸进程(Zombie),占用内核资源,甚至导致内存泄漏。本文详细讲解进程等待的必要性、wait 和 waitpid 的使用方法,以及如何获取子进程的退出状态。
2. 进程等待的必要性
-
回收子进程资源:避免僵尸进程;
-
获取子进程退出状态:判断任务执行结果;
-
防止内存泄漏 :僵尸进程无法被
kill -9杀死。
3. wait 函数
c
#include <sys/wait.h>
pid_t wait(int *status);
-
返回值:成功返回子进程PID,失败返回-1;
-
参数
status:输出型参数,用于获取子进程退出信息,不关心则传NULL。
4. waitpid 函数
c
pid_t waitpid(pid_t pid, int *status, int options);
参数 pid:
-
pid == -1:等待任意子进程,同wait; -
pid > 0:等待指定PID的子进程。
参数 options:
-
0:阻塞等待; -
WNOHANG:非阻塞等待,若子进程未退出则立即返回0。
返回值:
-
正常返回子进程PID;
-
WNOHANG且无子进程退出时返回0; -
出错返回-1。
5. 获取子进程退出状态
status 是一个32位整数,其低16位包含以下信息:
-
高8位(位8~15):退出码(正常退出时);
-
低7位(位0~6):终止信号编号;
-
第7位(bit 7):coredump标志。
常用宏:
-
WIFEXITED(status):是否正常退出; -
WEXITSTATUS(status):提取退出码; -
WIFSIGNALED(status):是否被信号终止; -
WTERMSIG(status):提取终止信号。
6. 阻塞与非阻塞等待
阻塞等待示例
c
waitpid(-1, &status, 0); // 等待任意子进程,阻塞
非阻塞等待示例
c
while ((ret = waitpid(-1, &status, WNOHANG)) == 0) {
// 子进程仍在运行,执行其他任务
}
7. 补充:孤儿进程与守护进程
-
孤儿进程 :父进程先于子进程退出,子进程被
init(PID=1)收养,可自动回收; -
守护进程 :一种特殊的孤儿进程,脱离终端,后台运行(如
sshd、crond)。
8. 总结
-
始终使用
wait或waitpid回收子进程; -
非阻塞等待适用于需要同时处理其他任务的场景;
-
理解
status的位结构是调试信号问题的基础。