xref: /DragonOS/kernel/src/ipc/signal_types.rs (revision ba0d93d8b26034abc54bcaf3f0ff04863bbd076e)
1 #![allow(non_camel_case_types)]
2 // 这是signal暴露给其他模块的公有的接口文件
3 
4 use core::ffi::c_void;
5 use core::fmt::Debug;
6 
7 use alloc::vec::Vec;
8 
9 use crate::include::bindings::bindings::NULL;
10 // todo: 将这里更换为手动编写的ffi绑定
11 use crate::include::bindings::bindings::atomic_t;
12 use crate::include::bindings::bindings::pt_regs;
13 use crate::include::bindings::bindings::spinlock_t;
14 use crate::kerror;
15 use crate::libs::ffi_convert::FFIBind2Rust;
16 use crate::libs::ffi_convert::__convert_mut;
17 use crate::libs::ffi_convert::__convert_ref;
18 use crate::libs::refcount::RefCount;
19 
20 /// 请注意,sigset_t这个bitmap, 第0位表示sig=1的信号。也就是说,SignalNumber-1才是sigset_t中对应的位
21 pub type sigset_t = u64;
22 /// 存储信号处理函数的地址(来自用户态)
23 pub type __signalfn_t = u64;
24 pub type __sighandler_t = __signalfn_t;
25 /// 存储信号处理恢复函数的地址(来自用户态)
26 pub type __sigrestorer_fn_t = u64;
27 pub type __sigrestorer_t = __sigrestorer_fn_t;
28 
29 /// 最大的信号数量(改动这个值的时候请同步到signal.h)
30 pub const MAX_SIG_NUM: i32 = 64;
31 /// sigset所占用的u64的数量(改动这个值的时候请同步到signal.h)
32 pub const _NSIG_U64_CNT: i32 = MAX_SIG_NUM / 64;
33 /// 信号处理的栈的栈指针的最小对齐数量
34 pub const STACK_ALIGN: u64 = 16;
35 
36 /// 由于signal_struct总是和sighand_struct一起使用,并且信号处理的过程中必定会对sighand加锁
37 /// 因此signal_struct不用加锁
38 /// **请将该结构体与`include/DragonOS/signal.h`中的保持同步**
39 #[repr(C)]
40 #[derive(Debug, Copy, Clone)]
41 pub struct signal_struct {
42     pub sig_cnt: atomic_t,
43 }
44 
45 impl Default for signal_struct {
46     fn default() -> Self {
47         Self {
48             sig_cnt: Default::default(),
49         }
50     }
51 }
52 
53 /**
54  * sigaction中的信号处理函数结构体
55  * 分为两种处理函数
56  */
57 #[repr(C)]
58 #[derive(Copy, Clone)]
59 pub union sigaction__union_u {
60     pub _sa_handler: __sighandler_t, // 传统处理函数
61     pub _sa_sigaction: ::core::option::Option<
62         unsafe extern "C" fn(
63             sig: ::core::ffi::c_int,
64             sinfo: *mut siginfo,
65             arg1: *mut ::core::ffi::c_void,
66         ),
67     >,
68 }
69 
70 impl core::fmt::Debug for sigaction__union_u {
71     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
72         f.write_str("sigaction__union_u")
73     }
74 }
75 
76 impl Default for sigaction__union_u {
77     fn default() -> Self {
78         Self {
79             _sa_handler: NULL as u64,
80         }
81     }
82 }
83 
84 // ============ sigaction结构体中的的sa_flags的可选值 begin ===========
85 pub const SA_FLAG_DFL: u64 = 1u64 << 0; // 当前sigaction表示系统默认的动作
86 pub const SA_FLAG_IGN: u64 = 1u64 << 1; // 当前sigaction表示忽略信号的动作
87 pub const SA_FLAG_RESTORER: u64 = 1u64 << 2; // 当前sigaction具有用户指定的restorer
88 pub const SA_FLAG_IMMUTABLE: u64 = 1u64 << 3; // 当前sigaction不可被更改
89 
90 /// 所有的sa_flags的mask。(用于去除那些不存在的sa_flags位)
91 pub const SA_ALL_FLAGS: u64 = SA_FLAG_IGN | SA_FLAG_DFL | SA_FLAG_RESTORER | SA_FLAG_IMMUTABLE;
92 
93 // ============ sigaction结构体中的的sa_flags的可选值 end ===========
94 
95 /// 用户态程序传入的SIG_DFL的值
96 pub const USER_SIG_DFL: u64 = 0;
97 /// 用户态程序传入的SIG_IGN的值
98 pub const USER_SIG_IGN: u64 = 1;
99 
100 /**
101  * @brief 信号处理结构体
102  */
103 #[repr(C)]
104 #[derive(Debug, Copy, Clone)]
105 pub struct sigaction {
106     pub _u: sigaction__union_u,
107     pub sa_flags: u64,
108     pub sa_mask: sigset_t, // 为了可扩展性而设置的sa_mask
109     /// 信号处理函数执行结束后,将会跳转到这个函数内进行执行,然后执行sigreturn系统调用
110     pub sa_restorer: __sigrestorer_t,
111 }
112 
113 impl Default for sigaction {
114     fn default() -> Self {
115         Self {
116             _u: Default::default(),
117             sa_flags: Default::default(),
118             sa_mask: Default::default(),
119             sa_restorer: Default::default(),
120         }
121     }
122 }
123 
124 impl sigaction {
125     /// @brief 判断这个sigaction是否被忽略
126     pub fn ignored(&self, _sig: SignalNumber) -> bool {
127         if (self.sa_flags & SA_FLAG_IGN) != 0 {
128             return true;
129         }
130         // todo: 增加对sa_flags为SA_FLAG_DFL,但是默认处理函数为忽略的情况的判断
131 
132         return false;
133     }
134 }
135 
136 /// @brief 用户态传入的sigaction结构体(符合posix规范)
137 /// 请注意,我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
138 #[repr(C)]
139 #[derive(Debug)]
140 pub struct user_sigaction {
141     pub sa_handler: *mut core::ffi::c_void,
142     pub sa_sigaction: *mut core::ffi::c_void,
143     pub sa_mask: sigset_t,
144     pub sa_flags: u64,
145     pub sa_restorer: *mut core::ffi::c_void,
146 }
147 
148 /**
149  * 信号消息的结构体,作为参数传入sigaction结构体中指向的处理函数
150  */
151 #[repr(C)]
152 #[derive(Copy, Clone)]
153 pub struct siginfo {
154     pub _sinfo: __siginfo_union,
155 }
156 #[repr(C)]
157 #[derive(Copy, Clone)]
158 pub union __siginfo_union {
159     pub data: __siginfo_union_data,
160     pub padding: [u64; 4usize],
161 }
162 
163 #[repr(C)]
164 #[derive(Copy, Clone)]
165 pub struct __siginfo_union_data {
166     pub si_signo: i32,
167     pub si_code: i32,
168     pub si_errno: i32,
169     pub reserved: u32,
170     pub _sifields: __sifields,
171 }
172 
173 /**
174  * siginfo中,根据signal的来源不同,该union中对应了不同的数据./=
175  * 请注意,该union最大占用16字节
176  */
177 #[repr(C)]
178 #[derive(Copy, Clone)]
179 pub union __sifields {
180     pub _kill: __sifields__kill,
181 }
182 
183 /**
184  * 来自kill命令的signal
185  */
186 #[repr(C)]
187 #[derive(Debug, Copy, Clone)]
188 pub struct __sifields__kill {
189     pub _pid: i64, /* 发起kill的进程的pid */
190 }
191 
192 impl siginfo {
193     pub fn new(sig: SignalNumber, _si_errno: i32, _si_code: si_code_val) -> Self {
194         siginfo {
195             _sinfo: __siginfo_union {
196                 data: __siginfo_union_data {
197                     si_signo: sig as i32,
198                     si_code: _si_code as i32,
199                     si_errno: _si_errno,
200                     reserved: 0,
201                     _sifields: super::signal_types::__sifields {
202                         _kill: super::signal_types::__sifields__kill { _pid: 0 },
203                     },
204                 },
205             },
206         }
207     }
208 }
209 
210 impl Debug for siginfo {
211     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
212         unsafe {
213             f.write_fmt(format_args!(
214                 "si_signo:{}, si_code:{}, si_errno:{}, _pid:{}",
215                 self._sinfo.data.si_signo,
216                 self._sinfo.data.si_code,
217                 self._sinfo.data.si_errno,
218                 self._sinfo.data._sifields._kill._pid
219             ))
220         }
221     }
222 }
223 
224 /**
225  * @brief 信号处理结构体,位于pcb之中
226  */
227 #[repr(C)]
228 #[derive(Debug, Copy, Clone)]
229 pub struct sighand_struct {
230     pub siglock: spinlock_t,
231     pub count: RefCount,
232     pub action: [sigaction; MAX_SIG_NUM as usize],
233 }
234 
235 impl Default for sighand_struct {
236     fn default() -> Self {
237         Self {
238             siglock: Default::default(),
239             count: Default::default(),
240             action: [Default::default(); MAX_SIG_NUM as usize],
241         }
242     }
243 }
244 
245 /**
246  * @brief 正在等待的信号的标志位
247  */
248 #[repr(C)]
249 #[derive(Debug, Copy, Clone)]
250 pub struct sigpending {
251     pub signal: sigset_t,
252     /// 信号队列
253     pub queue: *mut SigQueue,
254 }
255 
256 /// siginfo中的si_code的可选值
257 /// 请注意,当这个值小于0时,表示siginfo来自用户态,否则来自内核态
258 #[allow(dead_code)]
259 #[repr(i32)]
260 pub enum si_code_val {
261     /// sent by kill, sigsend, raise
262     SI_USER = 0,
263     /// sent by kernel from somewhere
264     SI_KERNEL = 0x80,
265     /// 通过sigqueue发送
266     SI_QUEUE = -1,
267     /// 定时器过期时发送
268     SI_TIMER = -2,
269     /// 当实时消息队列的状态发生改变时发送
270     SI_MESGQ = -3,
271     /// 当异步IO完成时发送
272     SI_ASYNCIO = -4,
273     /// sent by queued SIGIO
274     SI_SIGIO = -5,
275 }
276 
277 impl si_code_val {
278     /// 为si_code_val这个枚举类型实现从i32转换到枚举类型的转换函数
279     #[allow(dead_code)]
280     pub fn from_i32(x: i32) -> si_code_val {
281         match x {
282             0 => Self::SI_USER,
283             0x80 => Self::SI_KERNEL,
284             -1 => Self::SI_QUEUE,
285             -2 => Self::SI_TIMER,
286             -3 => Self::SI_MESGQ,
287             -4 => Self::SI_ASYNCIO,
288             -5 => Self::SI_SIGIO,
289             _ => panic!("si code not valid"),
290         }
291     }
292 }
293 
294 #[allow(dead_code)]
295 #[derive(Debug, Clone, Copy)]
296 #[repr(i32)]
297 pub enum SignalNumber {
298     INVALID = 0,
299     SIGHUP = 1,
300     SIGINT,
301     SIGQUIT,
302     SIGILL,
303     SIGTRAP,
304     /// SIGABRT和SIGIOT共用这个号码
305     SIGABRT_OR_IOT,
306     SIGBUS,
307     SIGFPE,
308     SIGKILL,
309     SIGUSR1,
310 
311     SIGSEGV = 11,
312     SIGUSR2,
313     SIGPIPE,
314     SIGALRM,
315     SIGTERM,
316     SIGSTKFLT,
317     SIGCHLD,
318     SIGCONT,
319     SIGSTOP,
320     SIGTSTP,
321 
322     SIGTTIN = 21,
323     SIGTTOU,
324     SIGURG,
325     SIGXCPU,
326     SIGXFSZ,
327     SIGVTALRM,
328     SIGPROF,
329     SIGWINCH,
330     /// SIGIO和SIGPOLL共用这个号码
331     SIGIO_OR_POLL,
332     SIGPWR,
333 
334     SIGSYS = 31,
335 }
336 
337 /// 为SignalNumber实现判断相等的trait
338 impl PartialEq for SignalNumber {
339     fn eq(&self, other: &SignalNumber) -> bool {
340         *self as i32 == *other as i32
341     }
342 }
343 
344 impl From<i32> for SignalNumber {
345     fn from(value: i32) -> Self {
346         if Self::valid_signal_number(value) {
347             let ret: SignalNumber = unsafe { core::mem::transmute(value) };
348             return ret;
349         } else {
350             kerror!("Try to convert an invalid number to SignalNumber");
351             return SignalNumber::INVALID;
352         }
353     }
354 }
355 impl SignalNumber {
356     /// 判断一个数字是否为可用的信号
357     fn valid_signal_number(x: i32) -> bool {
358         if x > 0 && x < MAX_SIG_NUM {
359             return true;
360         } else {
361             return false;
362         }
363     }
364 }
365 
366 #[allow(dead_code)]
367 pub const SIGRTMIN: i32 = 32;
368 #[allow(dead_code)]
369 pub const SIGRTMAX: i32 = MAX_SIG_NUM;
370 
371 /// @brief 将给定的signal_struct解析为Rust的signal.rs中定义的signal_struct的引用
372 ///
373 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
374 impl FFIBind2Rust<crate::include::bindings::bindings::signal_struct> for signal_struct {
375     fn convert_mut(
376         src: *mut crate::include::bindings::bindings::signal_struct,
377     ) -> Option<&'static mut Self> {
378         return __convert_mut(src);
379     }
380     fn convert_ref(
381         src: *const crate::include::bindings::bindings::signal_struct,
382     ) -> Option<&'static Self> {
383         return __convert_ref(src);
384     }
385 }
386 
387 /// @brief 将给定的siginfo解析为Rust的signal.rs中定义的siginfo的引用
388 ///
389 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
390 impl FFIBind2Rust<crate::include::bindings::bindings::siginfo> for siginfo {
391     fn convert_mut(
392         src: *mut crate::include::bindings::bindings::siginfo,
393     ) -> Option<&'static mut Self> {
394         return __convert_mut(src);
395     }
396     fn convert_ref(
397         src: *const crate::include::bindings::bindings::siginfo,
398     ) -> Option<&'static Self> {
399         return __convert_ref(src);
400     }
401 }
402 
403 /// @brief 将给定的sigset_t解析为Rust的signal.rs中定义的sigset_t的引用
404 ///
405 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
406 impl FFIBind2Rust<crate::include::bindings::bindings::sigset_t> for sigset_t {
407     fn convert_mut(
408         src: *mut crate::include::bindings::bindings::sigset_t,
409     ) -> Option<&'static mut Self> {
410         return __convert_mut(src);
411     }
412     fn convert_ref(
413         src: *const crate::include::bindings::bindings::sigset_t,
414     ) -> Option<&'static Self> {
415         return __convert_ref(src);
416     }
417 }
418 
419 /// @brief 将给定的sigpending解析为Rust的signal.rs中定义的sigpending的引用
420 ///
421 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
422 impl FFIBind2Rust<crate::include::bindings::bindings::sigpending> for sigpending {
423     fn convert_mut(
424         src: *mut crate::include::bindings::bindings::sigpending,
425     ) -> Option<&'static mut Self> {
426         return __convert_mut(src);
427     }
428     fn convert_ref(
429         src: *const crate::include::bindings::bindings::sigpending,
430     ) -> Option<&'static Self> {
431         return __convert_ref(src);
432     }
433 }
434 
435 /// @brief 将给定的来自bindgen的sighand_struct解析为Rust的signal.rs中定义的sighand_struct的引用
436 ///
437 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的,会导致无法自定义功能的问题。
438 impl FFIBind2Rust<crate::include::bindings::bindings::sighand_struct> for sighand_struct {
439     fn convert_mut(
440         src: *mut crate::include::bindings::bindings::sighand_struct,
441     ) -> Option<&'static mut Self> {
442         return __convert_mut(src);
443     }
444     fn convert_ref(
445         src: *const crate::include::bindings::bindings::sighand_struct,
446     ) -> Option<&'static Self> {
447         return __convert_ref(src);
448     }
449 }
450 
451 /// @brief 将给定的来自bindgen的sigaction解析为Rust的signal.rs中定义的sigaction的引用
452 impl FFIBind2Rust<crate::include::bindings::bindings::sigaction> for sigaction {
453     fn convert_mut(
454         src: *mut crate::include::bindings::bindings::sigaction,
455     ) -> Option<&'static mut Self> {
456         return __convert_mut(src);
457     }
458     fn convert_ref(
459         src: *const crate::include::bindings::bindings::sigaction,
460     ) -> Option<&'static Self> {
461         return __convert_ref(src);
462     }
463 }
464 
465 /// @brief 进程接收到的信号的队列
466 pub struct SigQueue {
467     pub q: Vec<siginfo>,
468 }
469 
470 #[allow(dead_code)]
471 impl SigQueue {
472     /// @brief 初始化一个新的信号队列
473     pub fn new(capacity: usize) -> Self {
474         SigQueue {
475             q: Vec::with_capacity(capacity),
476         }
477     }
478 
479     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
480     ///
481     /// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
482     pub fn find(&self, sig: SignalNumber) -> (Option<&siginfo>, bool) {
483         // 是否存在多个满足条件的siginfo
484         let mut still_pending = false;
485         let mut info: Option<&siginfo> = None;
486 
487         for x in self.q.iter() {
488             if unsafe { x._sinfo.data.si_signo } == sig as i32 {
489                 if info.is_some() {
490                     still_pending = true;
491                     break;
492                 } else {
493                     info = Some(x);
494                 }
495             }
496         }
497         return (info, still_pending);
498     }
499 
500     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除,然后返回这个siginfo
501     ///
502     /// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
503     pub fn find_and_delete(&mut self, sig: SignalNumber) -> (Option<siginfo>, bool) {
504         // 是否存在多个满足条件的siginfo
505         let mut still_pending = false;
506         let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
507 
508         let filter = |x: &mut siginfo| {
509             if unsafe { x._sinfo.data.si_signo } == sig as i32 {
510                 if !first {
511                     // 如果之前已经筛选出了一个元素,则不把当前元素删除
512                     still_pending = true;
513                     return false;
514                 } else {
515                     // 当前是第一个被筛选出来的元素
516                     first = false;
517                     return true;
518                 }
519             } else {
520                 return false;
521             }
522         };
523         // 从sigqueue中过滤出结果
524         let mut filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
525         // 筛选出的结果不能大于1个
526         assert!(filter_result.len() <= 1);
527 
528         return (filter_result.pop(), still_pending);
529     }
530 
531     /// @brief 从sigqueue中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
532     pub fn flush_by_mask(&mut self, mask: &sigset_t) {
533         // 定义过滤器,从sigqueue中删除mask中被置位的信号
534         let filter = |x: &mut siginfo| {
535             if sig_is_member(mask, SignalNumber::from(unsafe { x._sinfo.data.si_signo })) {
536                 true
537             } else {
538                 false
539             }
540         };
541         let filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
542         // 回收这些siginfo
543         for x in filter_result {
544             drop(x)
545         }
546     }
547 
548     /// @brief 从C的void*指针转换为static生命周期的可变引用
549     pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue{
550         let sq = p as *mut SigQueue;
551         let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
552         return sq;
553     }
554 }
555 
556 impl Default for SigQueue {
557     fn default() -> Self {
558         Self {
559             q: Default::default(),
560         }
561     }
562 }
563 
564 /// @brief 清除sigset中,某个信号对应的标志位
565 #[inline]
566 pub fn sigset_del(set: &mut sigset_t, sig: SignalNumber) {
567     let sig = sig as i32 - 1;
568     if _NSIG_U64_CNT == 1 {
569         *set &= !(1 << sig);
570     } else {
571         // 暂时不支持超过64个信号
572         panic!("Unsupported signal number: {:?}", sig);
573     }
574 }
575 
576 /// @brief 将指定的信号在sigset中的对应bit进行置位
577 #[inline]
578 pub fn sigset_add(set: &mut sigset_t, sig: SignalNumber) {
579     *set |= 1 << ((sig as u32) - 1);
580 }
581 
582 /// @brief 将sigset清零
583 #[inline]
584 pub fn sigset_clear(set: &mut sigset_t) {
585     *set = 0;
586 }
587 
588 /// @brief 将mask中置为1的位,在sigset中清零
589 #[inline]
590 pub fn sigset_delmask(set: &mut sigset_t, mask: u64) {
591     *set &= !mask;
592 }
593 
594 /// @brief 判断两个sigset是否相等
595 #[inline]
596 pub fn sigset_equal(a: &sigset_t, b: &sigset_t) -> bool {
597     if _NSIG_U64_CNT == 1 {
598         return *a == *b;
599     }
600     return false;
601 }
602 
603 /// @brief 使用指定的值,初始化sigset(为支持将来超过64个signal留下接口)
604 #[inline]
605 pub fn sigset_init(new_set: &mut sigset_t, mask: u64) {
606     *new_set = mask;
607     match _NSIG_U64_CNT {
608         1 => {}
609         _ => {
610             // 暂时不支持大于64个信号
611             todo!();
612         }
613     };
614 }
615 
616 /// @brief 判断指定的信号在sigset中的对应位是否被置位
617 /// @return true: 给定的信号在sigset中被置位
618 /// @return false: 给定的信号在sigset中没有被置位
619 #[inline]
620 pub fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool {
621     return if 1 & (set >> ((_sig as u32) - 1)) != 0 {
622         true
623     } else {
624         false
625     };
626 }
627 
628 #[repr(C)]
629 #[derive(Debug, Clone, Copy)]
630 pub struct sigframe {
631     /// 指向restorer的地址的指针。(该变量必须放在sigframe的第一位,因为这样才能在handler返回的时候,跳转到对应的代码,执行sigreturn)
632     pub ret_code_ptr: *mut core::ffi::c_void,
633     /// signum
634     pub arg0: u64,
635     /// siginfo pointer
636     pub arg1: usize,
637     /// sigcontext pointer
638     pub arg2: usize,
639 
640     pub handler: *mut c_void,
641     pub info: siginfo,
642     pub context: sigcontext,
643 }
644 
645 #[derive(Debug, Clone, Copy)]
646 pub struct sigcontext {
647     /// sigcontext的标志位
648     pub sc_flags: u64,
649     pub sc_stack: signal_stack, // 信号处理程序备用栈信息
650 
651     pub regs: pt_regs, // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
652     pub trap_num: u64, // 用来保存线程结构体中的trap_num字段
653     pub oldmask: u64,  // 暂存的执行信号处理函数之前的,被设置block的信号
654     pub cr2: u64,      // 用来保存线程结构体中的cr2字段
655     pub err_code: u64, // 用来保存线程结构体中的err_code字段
656     // todo: 支持x87浮点处理器后,在这里增加浮点处理器的状态结构体指针
657     pub reserved_for_x87_state: u64,
658     pub reserved: [u64; 8],
659 }
660 
661 /// @brief 信号处理备用栈的信息
662 #[derive(Debug, Clone, Copy)]
663 pub struct signal_stack {
664     pub sp: *mut c_void,
665     pub flags: u32,
666     pub size: u32,
667 }
668