一、函数概述
1. 函数原型与头文件
cs
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
2. 返回值
-
成功:返回已终止子进程的PID。
-
失败:返回-1,当前进程无子进程时,错误码置为
ECHILD。
3. 核心功能
-
阻塞父进程,等待当前进程创建的任意子进程终止。
-
回收终止子进程的PCB残留资源,清除僵尸进程,避免系统PID资源耗尽。
-
获取并保存子进程的完整退出状态,包含退出码、终止信号等信息。
4. 使用前置条件
wait()函数仅用于回收当前进程通过fork()创建的子进程。
未创建子进程时直接调用该函数,会直接调用失败。
二、wstatus参数底层存储机制
子进程退出后,内核将其退出状态信息按二进制位打包存储于wstatus指向的整型内存空间,不同比特位对应不同状态信息,无法直接通过变量原值读取有效数据。
比特位分布规则
-
0~7 bit:存储子进程终止信号编号,子进程正常退出时该数据为0。
-
8~15 bit:存储子进程退出码,仅占用8位存储空间。
退出码取值规则
受8位存储空间限制,子进程退出码有效取值范围为0~255。若传入数值超出范围,系统自动对256取模。
-
exit(256)等效exit(0) -
exit(257)等效exit(1) -
exit(300)等效exit(44)
三、wstatus两种传参方式及完整实现
方式一:传参 &wstatus(保存子进程退出状态)
使用说明
自定义整型变量int wstatus,将变量地址传入函数。该方式可保存子进程完整退出状态,支持两种合法解析方式:手动位运算解析、系统标准宏解析。两种方式功能等价,适用场景不同。
1. 手动位运算解析(底层原理实现)
依据比特位分布规则,通过移位、按位与运算直接解析状态数据,无需依赖系统宏,仅适配Linux平台,用于理解底层存储原理。
核心解析公式:
-
提取退出码:
(wstatus >> 8) & 0xff -
提取终止信号:
wstatus & 0x7f
cs
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid = fork();
if(pid == 0)
{
exit(10);
}
int wstatus;
wait(&wstatus);
// 位运算解析退出状态
int exit_code = (wstatus >> 8) & 0xff;
//int sig_num = wstatus & 0x7f;
printf("子进程退出码:%d\n", exit_code);
//printf("子进程终止信号:%d\n", sig_num);
return 0;
}
2. 系统宏解析(工程标准实现)
调用系统封装的状态解析宏,跨平台兼容性强,是工程开发的标准写法。
cs
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid = fork();
if(pid == 0)
{
exit(10);
}
int wstatus;
wait(&wstatus);
if(WIFEXITED(wstatus))
{
printf("子进程正常退出,退出码:%d\n", WEXITSTATUS(wstatus));
}
//else if(WIFSIGNALED(wstatus))
//{
// printf("子进程被信号终止,信号编号:%d\n", WTERMSIG(wstatus));
//}
return 0;
}
方式二:传参 NULL(仅回收僵尸进程)
使用场景
仅需清除子进程僵尸状态、释放系统资源,无需获取子进程退出码、终止信号等状态信息。
使用说明
无需定义状态变量,无需状态解析操作,代码简洁,仅完成进程回收功能。
cs
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid = fork();
if(pid == 0)
{
printf("子进程执行完毕\n");
exit(5);
}
wait(NULL);
printf("父进程完成子进程资源回收\n");
return 0;
}
四、两种解析方式对比
| 解析方式 | 合法性 | 兼容性 | 适用场景 |
|---|---|---|---|
| 手动位运算解析 | 合法有效 | 仅Linux平台适配 | 底层原理学习、知识点验证 |
| 系统宏解析 | 标准合法 | 全UNIX/Linux平台通用 | 工程项目开发、正式业务代码 |
五、系统状态解析宏说明
系统宏为内核封装的跨平台状态解析接口,仅适用于wait(&wstatus)传参场景。
| 宏定义 | 功能描述 | 使用条件 |
|---|---|---|
| WIFEXITED(wstatus) | 判断子进程是否为正常退出 | 任意场景 |
| WEXITSTATUS(wstatus) | 提取子进程正常退出码 | 子进程正常退出 |
| WIFSIGNALED(wstatus) | 判断子进程是否被信号终止 | 任意场景 |
| WTERMSIG(wstatus) | 获取终止子进程的信号编号 | 子进程被信号终止 |
六、核心总结
-
wait()函数依赖fork()创建的子进程,无有效子进程时调用失败,函数具备阻塞特性。
-
wait(&wstatus)用于保存子进程退出状态,支持手动位运算和系统宏两种解析方式,功能等价、场景不同。 -
wait(NULL)仅用于回收僵尸进程,舍弃所有退出状态信息,适用于无需判断子进程执行结果的场景。 -
子进程退出码仅占用8位存储空间,有效范围0~255,超出数值自动对256取模。
-
手动位运算用于底层原理学习,工程开发统一使用系统宏,保障代码跨平台兼容性。