Skip to main content

tg_signal_impl/
lib.rs

1//! 信号模块的具体实现。
2//!
3//! 本模块实现了 [`tg_signal::Signal`] trait,提供完整的信号处理功能。
4//!
5//! 教程阅读建议:
6//!
7//! - 先看 `SignalImpl` 的四个核心字段:`received/mask/handling/actions`;
8//! - 再看 `handle_signals` 的状态机分支(Frozen、用户处理函数、默认动作)。
9
10#![no_std]
11#![deny(warnings, missing_docs)]
12
13extern crate alloc;
14use alloc::boxed::Box;
15use tg_kernel_context::LocalContext;
16use tg_signal::{Signal, SignalAction, SignalNo, SignalResult, MAX_SIG};
17
18mod default_action;
19use default_action::DefaultAction;
20mod signal_set;
21use signal_set::SignalSet;
22
23/// 正在处理的信号状态。
24pub enum HandlingSignal {
25    /// 进程被冻结(收到 SIGSTOP 等信号),需要暂停当前进程
26    Frozen,
27    /// 正在处理用户信号,保存了之前的用户上下文
28    UserSignal(LocalContext),
29}
30
31/// 管理一个进程中的信号
32pub struct SignalImpl {
33    /// 已收到的信号
34    received: SignalSet,
35    /// 屏蔽的信号掩码
36    mask: SignalSet,
37    /// 在信号处理函数中,保存之前的用户栈
38    handling: Option<HandlingSignal>,
39    /// 当前任务的信号处理函数集
40    actions: [Option<SignalAction>; MAX_SIG + 1],
41}
42
43impl SignalImpl {
44    /// 创建一个新的信号管理器。
45    pub fn new() -> Self {
46        Self {
47            received: SignalSet::empty(),
48            mask: SignalSet::empty(),
49            handling: None,
50            actions: [None; MAX_SIG + 1],
51        }
52    }
53}
54
55impl Default for SignalImpl {
56    fn default() -> Self {
57        Self::new()
58    }
59}
60
61impl SignalImpl {
62    /// 获取一个没有被 mask 屏蔽的信号,并从已收到的信号集合中删除它。如果没有这样的信号,则返回空
63    fn fetch_signal(&mut self) -> Option<SignalNo> {
64        // 在已收到的信号中,寻找一个没有被 mask 屏蔽的信号
65        self.received.find_first_one(self.mask).map(|num| {
66            self.received.remove_bit(num);
67            num.into()
68        })
69    }
70
71    /// 检查是否收到一个信号,如果是,则接收并删除它
72    fn fetch_and_remove(&mut self, signal_no: SignalNo) -> bool {
73        if self.received.contain_bit(signal_no as usize)
74            && !self.mask.contain_bit(signal_no as usize)
75        {
76            self.received.remove_bit(signal_no as usize);
77            true
78        } else {
79            false
80        }
81    }
82}
83
84impl Signal for SignalImpl {
85    fn from_fork(&mut self) -> Box<dyn Signal> {
86        Box::new(Self {
87            received: SignalSet::empty(),
88            mask: self.mask,
89            handling: None,
90            actions: {
91                let mut actions = [None; MAX_SIG + 1];
92                actions.copy_from_slice(&self.actions);
93                actions
94            },
95        })
96    }
97
98    fn clear(&mut self) {
99        for action in &mut self.actions {
100            action.take();
101        }
102    }
103
104    /// 添加一个信号
105    fn add_signal(&mut self, signal: SignalNo) {
106        self.received.add_bit(signal as usize)
107    }
108
109    /// 是否当前正在处理信号
110    fn is_handling_signal(&self) -> bool {
111        self.handling.is_some()
112    }
113
114    /// 设置一个信号处理函数。`sys_sigaction` 会使用
115    fn set_action(&mut self, signum: SignalNo, action: &SignalAction) -> bool {
116        if signum == SignalNo::SIGKILL || signum == SignalNo::SIGSTOP {
117            false
118        } else {
119            self.actions[signum as usize] = Some(*action);
120            true
121        }
122    }
123
124    /// 获取一个信号处理函数的值。`sys_sigaction` 会使用
125    fn get_action_ref(&self, signum: SignalNo) -> Option<SignalAction> {
126        if signum == SignalNo::SIGKILL || signum == SignalNo::SIGSTOP {
127            None
128        } else {
129            Some(self.actions[signum as usize].unwrap_or(SignalAction::default()))
130        }
131    }
132
133    /// 设置信号掩码,并获取旧的信号掩码,`sys_procmask` 会使用
134    fn update_mask(&mut self, mask: usize) -> usize {
135        self.mask.set_new(mask.into())
136    }
137
138    fn handle_signals(&mut self, current_context: &mut LocalContext) -> SignalResult {
139        // 状态机入口:
140        // A. 若已在处理信号,则只处理可恢复情形(例如 Frozen + SIGCONT);
141        // B. 否则从 pending 集合提取一个可投递信号并执行默认或用户动作。
142        if self.is_handling_signal() {
143            match self.handling.as_ref().unwrap() {
144                // 如果当前正在暂停状态
145                HandlingSignal::Frozen => {
146                    // 则检查是否收到 SIGCONT,如果收到则当前任务需要从暂停状态中恢复
147                    if self.fetch_and_remove(SignalNo::SIGCONT) {
148                        self.handling.take();
149                        SignalResult::Handled
150                    } else {
151                        // 否则,继续暂停
152                        SignalResult::ProcessSuspended
153                    }
154                } // 其他情况下,需要等待当前信号处理结束
155                _ => SignalResult::IsHandlingSignal,
156            }
157        } else if let Some(signal) = self.fetch_signal() {
158            match signal {
159                // SIGKILL 信号不能被捕获或忽略
160                SignalNo::SIGKILL => SignalResult::ProcessKilled(-(signal as i32)),
161                SignalNo::SIGSTOP => {
162                    self.handling = Some(HandlingSignal::Frozen);
163                    SignalResult::ProcessSuspended
164                }
165                _ => {
166                    if let Some(action) = self.actions[signal as usize] {
167                        // 如果用户给定了处理方式,则按照 SignalAction 中的描述处理
168                        // 保存原来用户程序的上下文信息
169                        self.handling = Some(HandlingSignal::UserSignal(current_context.clone()));
170                        // 修改返回后的 pc 值为 handler,修改 a0 为信号编号
171                        //println!("handle pre {:x}, after {:x}", current_context.pc(), action.handler);
172                        *current_context.pc_mut() = action.handler;
173                        *current_context.a_mut(0) = signal as usize;
174                        SignalResult::Handled
175                    } else {
176                        // 否则,使用自定义的 DefaultAction 类来处理
177                        // 然后再转换成 SignalResult
178                        DefaultAction::from(signal).into()
179                    }
180                }
181            }
182        } else {
183            SignalResult::NoSignal
184        }
185    }
186
187    fn sig_return(&mut self, current_context: &mut LocalContext) -> bool {
188        let handling_signal = self.handling.take();
189        match handling_signal {
190            Some(HandlingSignal::UserSignal(old_ctx)) => {
191                // 用户 handler 执行完毕,恢复被中断前上下文。
192                //println!("return to {:x} a0 {}", old_ctx.pc(), old_ctx.a(0));
193                *current_context = old_ctx;
194                true
195            }
196            // 如果当前在处理内核信号,或者没有在处理信号,也就谈不上“返回”了
197            _ => {
198                self.handling = handling_signal;
199                false
200            }
201        }
202    }
203}