os/uapi/wait.rs
1//! 定义与等待子进程状态相关的标志。
2//!
3//! 这些标志用于 `waitpid` 和 `waitid` 系统调用,以指定等待行为。
4
5use core::ffi::c_int;
6
7use bitflags::bitflags;
8
9/// 子进程的状态编码(对应 waitpid/wait4 返回的 wstatus)。
10/// 包含了解析和构造状态值的方法。
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct WaitStatus {
13 raw_status: c_int,
14}
15
16const __W_CONTINUED: u32 = 0xFFFF; // 0xffff
17const __WCOREFLAG: u32 = 0x80; // 0x80 (用于 WCOREDUMP 标记)
18const __W_STOP_MAGIC: u32 = 0x7F; // 0x7f (用于 WIFSTOPPED 标记)
19
20impl WaitStatus {
21 /// 从原始的 wstatus 整数值创建一个 WaitStatus 实例。
22 pub const fn new(raw_status: c_int) -> Self {
23 Self { raw_status }
24 }
25
26 /// 获取原始状态值。
27 pub const fn raw(&self) -> c_int {
28 self.raw_status
29 }
30
31 /// __W_EXITCODE: 构造一个正常退出或因信号终止的状态值。
32 ///
33 /// 结构: (Exit Code) << 8 | (Termination Signal)
34 /// * ret: 退出码 (0-255)
35 /// * sig: 信号编号 (如果为 0 则表示正常退出)
36 pub fn exit_code(ret: u8, sig: u8) -> Self {
37 let status = ((ret as u32) << 8) | (sig as u32);
38 Self::new(status as c_int)
39 }
40
41 /// __W_STOPCODE: 构造一个子进程被停止的状态值。
42 ///
43 /// 结构: (Signal that stopped the child) << 8 | 0x7f
44 /// * sig: 导致停止的信号编号
45 pub fn stop_code(sig: u8) -> Self {
46 let status = ((sig as u32) << 8) | __W_STOP_MAGIC;
47 Self::new(status as c_int)
48 }
49
50 /// 构造一个子进程从停止状态恢复继续执行的状态值。
51 pub fn continued_code() -> Self {
52 Self::new(__W_CONTINUED as c_int)
53 }
54
55 // WTERMSIG / __WTERMSIG: 获取终止信号编号
56 /// 如果 WIFSIGNALED 为真,返回导致子进程终止的信号编号(低 7 位)。
57 pub fn termination_signal(&self) -> c_int {
58 self.raw_status & 0x7F
59 }
60
61 // WIFEXITED / __WIFEXITED: 是否正常退出
62 /// 检查状态是否表示正常终止(即终止信号为 0)。
63 pub fn is_exited(&self) -> bool {
64 self.termination_signal() == 0
65 }
66
67 // WEXITSTATUS / __WEXITSTATUS: 获取退出码
68 /// 如果 is_exited() 为真,返回子进程的退出状态码(位于第 8-15 位)。
69 pub fn exit_status(&self) -> c_int {
70 (self.raw_status >> 8) & 0xFF
71 }
72
73 // WIFSIGNALED / __WIFSIGNALED: 是否因信号终止
74 /// 检查状态是否表示子进程因未捕获的信号而终止。
75 pub fn is_signaled(&self) -> bool {
76 // C 宏逻辑:((signed char) (((status) & 0x7f) + 1) >> 1) > 0
77 // 等价于检查 (status & 0x7f) 是否在 [1, 127] 范围内
78 let term_sig = (self.raw_status & 0x7F) as u32;
79 term_sig > 0 && term_sig != __W_STOP_MAGIC
80 }
81
82 // WIFSTOPPED / __WIFSTOPPED: 是否被停止
83 /// 检查状态是否表示子进程被停止信号停止。
84 pub fn is_stopped(&self) -> bool {
85 (self.raw_status & 0xFF) as u32 == __W_STOP_MAGIC
86 }
87
88 // WSTOPSIG / __WSTOPSIG: 获取停止信号编号
89 /// 如果 is_stopped() 为真,返回导致子进程停止的信号编号。
90 /// 注意:该宏等价于 __WEXITSTATUS(status),即提取第 8-15 位。
91 pub fn stop_signal(&self) -> c_int {
92 self.exit_status()
93 }
94
95 // WIFCONTINUED / __WIFCONTINUED: 是否已恢复
96 /// 检查状态是否表示子进程已从停止状态恢复执行。
97 pub fn is_continued(&self) -> bool {
98 self.raw_status as u32 == __W_CONTINUED
99 }
100
101 // WCOREDUMP / __WCOREDUMP: 是否生成了核心转储
102 /// 检查子进程终止时是否生成了核心转储文件。
103 pub fn did_core_dump(&self) -> bool {
104 // 检查终止信号的最高位是否设置了 0x80 (__WCOREFLAG)
105 (self.raw_status as u32) & __WCOREFLAG != 0
106 }
107}
108
109bitflags! {
110 /// 等待子进程状态的选项标志。
111 /// 对应于 `waitpid` 和 `waitid` 系统调用中的参数。
112 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113 pub struct WaitFlags: usize {
114 // --- 适用于 waitpid/wait4 的基本标志 ---
115
116 /// WNOHANG: 非阻塞等待。如果没有子进程状态立即可用,则立即返回 0。
117 const NOHANG = 0x1;
118
119 /// WUNTRACED: 报告已停止/终止的子进程状态。
120 /// 报告那些因接收到信号(如 SIGSTOP 或 SIGTTIN/SIGTTOU)而停止的子进程。
121 const UNTRACED = 0x2;
122
123 // --- 适用于 waitid 的 POSIX/XOPEN 标志 ---
124
125 /// WSTOPPED: 报告已停止的子进程状态(与 WUNTRACED 相同)。
126 const STOPPED = 0x2;
127
128 /// WEXITED: 报告已终止(死亡)的子进程状态。
129 const EXITED = 0x4;
130
131 /// WCONTINUED: 报告因收到 SIGCONT 信号而恢复执行的子进程。
132 const CONTINUED = 0x8;
133
134 /// WNOWAIT: 仅查询状态,不将子进程从 wait set 中移除 (不回收/不释放资源)。
135 const NOWAIT = 0x0100_0000;
136
137 // --- Linux/GNU 内部/扩展标志 ---
138
139 /// __WNOTHREAD: 不等待本进程组内其他线程的子进程 (仅限调用线程的子进程)。
140 const NOTHREAD = 0x2000_0000;
141
142 /// __WALL: 等待所有子进程,无论其类型(包括通过 clone() 创建的线程)。
143 const ALL = 0x4000_0000;
144
145 /// __WCLONE: 仅等待由 clone() 创建的“线程”子进程。
146 const CLONE = 0x8000_0000;
147 }
148}