Kaynağa Gözat

feat(ipc): 实现 rt_sigtimedwait 系统调用并优化信号处理机制 (#1323)

* feat(ipc): 实现 rt_sigtimedwait 系统调用并优化信号处理机制

- 添加标准 POSIX siginfo_t 结构体及相关类型,用于用户态接口
- 实现 rt_sigtimedwait 系统调用,支持等待特定信号并处理超时
- 优化信号处理逻辑,确保信号正确标记为 pending
- 修复生命周期标注问题,提高代码健壮性
- 添加完整的系统调用测试用例

Signed-off-by: longjin <longjin@DragonOS.org>

* feat(signal): 扩展实时信号支持并优化信号处理逻辑

- 新增实时信号定义(SIGRTMIN+1至SIGRTMIN+31)
- 改进信号唤醒机制,修复阻塞状态下的信号处理
- 增强内存错误日志,添加进程ID和RIP信息
- 重构抢占管理,引入PreemptGuard机制
- 优化rt_sigtimedwait系统调用实现

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin 2 hafta önce
ebeveyn
işleme
0fdf7e1123

+ 10 - 5
kernel/src/arch/x86_64/ipc/signal.rs

@@ -1,3 +1,4 @@
+use core::sync::atomic::{compiler_fence, Ordering};
 use core::{ffi::c_void, intrinsics::unlikely, mem::size_of};
 
 use defer::defer;
@@ -20,7 +21,9 @@ use crate::{
     exception::InterruptArch,
     ipc::{
         signal::{restore_saved_sigmask, set_current_blocked},
-        signal_types::{SaHandlerType, SigInfo, Sigaction, SigactionType, SignalArch, SignalFlags},
+        signal_types::{
+            PosixSigInfo, SaHandlerType, SigInfo, Sigaction, SigactionType, SignalArch, SignalFlags,
+        },
     },
     mm::MemoryManagementArch,
     process::ProcessManager,
@@ -55,7 +58,7 @@ pub struct SigFrame {
     /// 指向restorer的地址的指针。(该变量必须放在sigframe的第一位,因为这样才能在handler返回的时候,跳转到对应的代码,执行sigreturn)
     pub ret_code_ptr: *mut core::ffi::c_void,
     pub handler: *mut c_void,
-    pub info: SigInfo,
+    pub info: PosixSigInfo,
     pub context: SigContext,
 }
 
@@ -237,6 +240,7 @@ unsafe fn do_signal(frame: &mut TrapFrame, got_signal: &mut bool) {
     // 因此这里需要检查清楚:上面所有的锁、arc指针都被释放了。否则会产生资源泄露的问题!
     let res: Result<i32, SystemError> =
         handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame);
+    compiler_fence(Ordering::SeqCst);
     if res.is_err() {
         error!(
             "Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
@@ -337,6 +341,7 @@ impl SignalArch for X86_64SignalArch {
 /// @return Result<0,SystemError> 若Error, 则返回错误码,否则返回Ok(0)
 ///
 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/signal.c#787
+#[inline(never)]
 fn handle_signal(
     sig: Signal,
     sigaction: &mut Sigaction,
@@ -472,14 +477,14 @@ fn setup_frame(
     }
 
     // 将siginfo拷贝到用户栈
-    info.copy_siginfo_to_user(unsafe { &mut ((*frame).info) as *mut SigInfo })
+    info.copy_posix_siginfo_to_user(unsafe { &mut ((*frame).info) as *mut PosixSigInfo })
         .map_err(|e| -> SystemError {
             let r = crate::ipc::kill::kill_process(
                 ProcessManager::current_pcb().raw_pid(),
                 Signal::SIGSEGV,
             );
             if r.is_err() {
-                error!("In copy_siginfo_to_user: generate SIGSEGV signal failed");
+                error!("In copy_posix_siginfo_to_user: generate SIGSEGV signal failed");
             }
             return e;
         })?;
@@ -510,7 +515,7 @@ fn setup_frame(
     unsafe { (*frame).handler = temp_handler };
     // 传入信号处理函数的第一个参数
     trap_frame.rdi = sig as u64;
-    trap_frame.rsi = unsafe { &(*frame).info as *const SigInfo as u64 };
+    trap_frame.rsi = unsafe { &(*frame).info as *const PosixSigInfo as u64 };
     trap_frame.rsp = frame as u64;
     trap_frame.rip = unsafe { (*frame).handler as u64 };
     // 设置cs和ds寄存器

+ 3 - 1
kernel/src/arch/x86_64/mm/fault.rs

@@ -264,9 +264,11 @@ impl X86_64MMArch {
                 Some(vma) => vma,
                 None => {
                     log::error!(
-                        "can not find nearest vma, error_code: {:?}, address: {:#x}",
+                        "pid:{}, can not find nearest vma, \n\terror_code: {:?}, address: {:#x}, rip: {:#x}",
+                        ProcessManager::current_pid().data(),
                         error_code,
                         address.data(),
+                        regs.rip,
                     );
                     send_segv();
                     return;

+ 120 - 3
kernel/src/ipc/generic_signal.rs

@@ -62,6 +62,38 @@ pub enum GenericSignal {
     SIGSYS = 31,
 
     SIGRTMIN = 32,
+    // 实时信号:SIGRTMIN+1 到 SIGRTMAX-1
+    SIGRTMIN_1 = 33,
+    SIGRTMIN_2 = 34,
+    SIGRTMIN_3 = 35,
+    SIGRTMIN_4 = 36,
+    SIGRTMIN_5 = 37,
+    SIGRTMIN_6 = 38,
+    SIGRTMIN_7 = 39,
+    SIGRTMIN_8 = 40,
+    SIGRTMIN_9 = 41,
+    SIGRTMIN_10 = 42,
+    SIGRTMIN_11 = 43,
+    SIGRTMIN_12 = 44,
+    SIGRTMIN_13 = 45,
+    SIGRTMIN_14 = 46,
+    SIGRTMIN_15 = 47,
+    SIGRTMIN_16 = 48,
+    SIGRTMIN_17 = 49,
+    SIGRTMIN_18 = 50,
+    SIGRTMIN_19 = 51,
+    SIGRTMIN_20 = 52,
+    SIGRTMIN_21 = 53,
+    SIGRTMIN_22 = 54,
+    SIGRTMIN_23 = 55,
+    SIGRTMIN_24 = 56,
+    SIGRTMIN_25 = 57,
+    SIGRTMIN_26 = 58,
+    SIGRTMIN_27 = 59,
+    SIGRTMIN_28 = 60,
+    SIGRTMIN_29 = 61,
+    SIGRTMIN_30 = 62,
+    SIGRTMIN_31 = 63,
     SIGRTMAX = 64,
 }
 
@@ -88,6 +120,18 @@ impl GenericSignal {
         return (*self) as usize >= Self::SIGRTMIN.into();
     }
 
+    /// 判断一个信号号是否为实时信号
+    #[inline]
+    pub fn is_rt_signal_number(sig_num: i32) -> bool {
+        sig_num >= Self::SIGRTMIN as i32 && sig_num <= Self::SIGRTMAX as i32
+    }
+
+    /// 获取实时信号的范围
+    #[inline]
+    pub fn rt_signal_range() -> (i32, i32) {
+        (Self::SIGRTMIN as i32, Self::SIGRTMAX as i32)
+    }
+
     /// 调用信号的默认处理函数
     pub fn handle_default(&self) {
         match self {
@@ -125,7 +169,39 @@ impl GenericSignal {
             Self::SIGIO_OR_POLL => sig_terminate(*self),
             Self::SIGPWR => sig_terminate(*self),
             Self::SIGSYS => sig_terminate(*self),
+            // 实时信号默认处理:终止进程
             Self::SIGRTMIN => sig_terminate(*self),
+            Self::SIGRTMIN_1 => sig_terminate(*self),
+            Self::SIGRTMIN_2 => sig_terminate(*self),
+            Self::SIGRTMIN_3 => sig_terminate(*self),
+            Self::SIGRTMIN_4 => sig_terminate(*self),
+            Self::SIGRTMIN_5 => sig_terminate(*self),
+            Self::SIGRTMIN_6 => sig_terminate(*self),
+            Self::SIGRTMIN_7 => sig_terminate(*self),
+            Self::SIGRTMIN_8 => sig_terminate(*self),
+            Self::SIGRTMIN_9 => sig_terminate(*self),
+            Self::SIGRTMIN_10 => sig_terminate(*self),
+            Self::SIGRTMIN_11 => sig_terminate(*self),
+            Self::SIGRTMIN_12 => sig_terminate(*self),
+            Self::SIGRTMIN_13 => sig_terminate(*self),
+            Self::SIGRTMIN_14 => sig_terminate(*self),
+            Self::SIGRTMIN_15 => sig_terminate(*self),
+            Self::SIGRTMIN_16 => sig_terminate(*self),
+            Self::SIGRTMIN_17 => sig_terminate(*self),
+            Self::SIGRTMIN_18 => sig_terminate(*self),
+            Self::SIGRTMIN_19 => sig_terminate(*self),
+            Self::SIGRTMIN_20 => sig_terminate(*self),
+            Self::SIGRTMIN_21 => sig_terminate(*self),
+            Self::SIGRTMIN_22 => sig_terminate(*self),
+            Self::SIGRTMIN_23 => sig_terminate(*self),
+            Self::SIGRTMIN_24 => sig_terminate(*self),
+            Self::SIGRTMIN_25 => sig_terminate(*self),
+            Self::SIGRTMIN_26 => sig_terminate(*self),
+            Self::SIGRTMIN_27 => sig_terminate(*self),
+            Self::SIGRTMIN_28 => sig_terminate(*self),
+            Self::SIGRTMIN_29 => sig_terminate(*self),
+            Self::SIGRTMIN_30 => sig_terminate(*self),
+            Self::SIGRTMIN_31 => sig_terminate(*self),
             Self::SIGRTMAX => sig_terminate(*self),
         }
     }
@@ -150,7 +226,17 @@ impl From<usize> for GenericSignal {
 impl From<i32> for GenericSignal {
     fn from(value: i32) -> Self {
         if value < 0 {
-            log::error!("Try to convert an invalid number to GenericSignal");
+            log::error!(
+                "Try to convert a negative number {} to GenericSignal",
+                value
+            );
+            return GenericSignal::INVALID;
+        } else if value as usize > GENERIC_MAX_SIG_NUM {
+            log::error!(
+                "Try to convert an out-of-range number {} to GenericSignal (max: {})",
+                value,
+                GENERIC_MAX_SIG_NUM
+            );
             return GenericSignal::INVALID;
         } else {
             return Self::from(value as usize);
@@ -240,8 +326,39 @@ bitflags! {
         const SIGPWR   =  1<<29;
         const SIGSYS   =  1<<30;
         const SIGRTMIN =  1<<31;
-        // TODO 写上实时信号
-        const SIGRTMAX =  1 << (GENERIC_MAX_SIG_NUM-1);
+        // 实时信号位图:SIGRTMIN+1 到 SIGRTMAX-1
+        const SIGRTMIN_1 =  1<<32;
+        const SIGRTMIN_2 =  1<<33;
+        const SIGRTMIN_3 =  1<<34;
+        const SIGRTMIN_4 =  1<<35;
+        const SIGRTMIN_5 =  1<<36;
+        const SIGRTMIN_6 =  1<<37;
+        const SIGRTMIN_7 =  1<<38;
+        const SIGRTMIN_8 =  1<<39;
+        const SIGRTMIN_9 =  1<<40;
+        const SIGRTMIN_10 = 1<<41;
+        const SIGRTMIN_11 = 1<<42;
+        const SIGRTMIN_12 = 1<<43;
+        const SIGRTMIN_13 = 1<<44;
+        const SIGRTMIN_14 = 1<<45;
+        const SIGRTMIN_15 = 1<<46;
+        const SIGRTMIN_16 = 1<<47;
+        const SIGRTMIN_17 = 1<<48;
+        const SIGRTMIN_18 = 1<<49;
+        const SIGRTMIN_19 = 1<<50;
+        const SIGRTMIN_20 = 1<<51;
+        const SIGRTMIN_21 = 1<<52;
+        const SIGRTMIN_22 = 1<<53;
+        const SIGRTMIN_23 = 1<<54;
+        const SIGRTMIN_24 = 1<<55;
+        const SIGRTMIN_25 = 1<<56;
+        const SIGRTMIN_26 = 1<<57;
+        const SIGRTMIN_27 = 1<<58;
+        const SIGRTMIN_28 = 1<<59;
+        const SIGRTMIN_29 = 1<<60;
+        const SIGRTMIN_30 = 1<<61;
+        const SIGRTMIN_31 = 1<<62;
+        const SIGRTMAX =  1<<63;
     }
 
     #[repr(C,align(8))]

+ 42 - 29
kernel/src/ipc/signal.rs

@@ -1,4 +1,7 @@
-use core::{fmt::Debug, sync::atomic::compiler_fence};
+use core::{
+    fmt::Debug,
+    sync::atomic::{compiler_fence, Ordering},
+};
 
 use alloc::sync::Arc;
 use log::warn;
@@ -129,7 +132,8 @@ impl Signal {
             //详见 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c?r=&mo=32170&fi=1220#1226
         }
 
-        if !self.prepare_sianal(pcb.clone(), force_send) {
+        let prepare_result = self.prepare_sianal(pcb.clone(), force_send);
+        if !prepare_result {
             return Ok(0);
         }
         // debug!("force send={}", force_send);
@@ -187,8 +191,6 @@ impl Signal {
     /// @param pt siginfo结构体中,pid字段代表的含义
     #[allow(clippy::if_same_then_else)]
     fn complete_signal(&self, pcb: Arc<ProcessControlBlock>, pt: PidType) {
-        // debug!("complete_signal");
-
         compiler_fence(core::sync::atomic::Ordering::SeqCst);
         // ===== 寻找需要wakeup的目标进程 =====
         // 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
@@ -198,19 +200,20 @@ impl Signal {
 
         let target_pcb: Option<Arc<ProcessControlBlock>>;
 
-        // 判断目标进程是否想接收这个信号
-        if self.wants_signal(pcb.clone()) {
-            // todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify)
-            // 将这个信号加到目标进程的sig_pending中
-            pcb.sig_info_mut()
-                .sig_pending_mut()
-                .signal_mut()
-                .insert((*self).into());
+        // 无论目标进程当前是否屏蔽该信号,均应当将其标记为 pending
+        pcb.sig_info_mut()
+            .sig_pending_mut()
+            .signal_mut()
+            .insert((*self).into());
+        // 根据实际 pending/blocked 关系更新 HAS_PENDING_SIGNAL,避免长时间误置位
+        pcb.recalc_sigpending(None);
+        // 判断目标进程是否应该被唤醒以立即处理该信号
+        let wants_signal = self.wants_signal(pcb.clone());
+        if wants_signal {
             target_pcb = Some(pcb.clone());
         } else if pt == PidType::PID {
             /*
-             * There is just one thread and it does not need to be woken.
-             * It will dequeue unblocked signals before it runs again.
+             * 单线程场景且不需要唤醒:信号已入队,等待合适时机被取走
              */
             return;
         } else {
@@ -235,32 +238,42 @@ impl Signal {
     /// 这么做是为了防止我们把信号发送给了一个正在或已经退出的进程,或者是不响应该信号的进程。
     #[inline]
     fn wants_signal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
-        // 如果改进程屏蔽了这个signal,则不能接收
-        if pcb
-            .sig_info_irqsave()
-            .sig_blocked()
-            .contains((*self).into())
-        {
-            return false;
-        }
-
-        // 如果进程正在退出,则不能接收信号
+        // 若进程正在退出,则不能接收
         if pcb.flags().contains(ProcessFlags::EXITING) {
             return false;
         }
 
+        // SIGKILL 总是唤醒
         if *self == Signal::SIGKILL {
             return true;
         }
+
+        // 若线程正处于可中断阻塞,且当前在 set_user_sigmask 语义下(如 rt_sigtimedwait/pselect 等)
+        // 则无论该信号是否在常规 blocked 集内,都应唤醒,由具体系统调用在返回路径上判定。
         let state = pcb.sched_info().inner_lock_read_irqsave().state();
-        if state.is_blocked() && (!state.is_blocked_interruptable()) {
+        let is_blocked_interruptable = state.is_blocked_interruptable();
+        let has_restore_sig_mask = pcb.flags().contains(ProcessFlags::RESTORE_SIG_MASK);
+
+        if is_blocked_interruptable && has_restore_sig_mask {
+            return true;
+        }
+
+        // 常规规则:被屏蔽则不唤醒;否则在可中断阻塞下唤醒
+        let blocked = *pcb.sig_info_irqsave().sig_blocked();
+        let is_blocked = blocked.contains((*self).into());
+
+        if is_blocked {
             return false;
         }
 
-        // todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项
+        let is_blocked_non_interruptable =
+            state.is_blocked() && (!state.is_blocked_interruptable());
+
+        if is_blocked_non_interruptable {
+            return false;
+        }
 
-        // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
-        return pcb.sig_info_irqsave().sig_pending().signal().bits() == 0;
+        return true;
     }
 
     /// @brief 判断signal的处理是否可能使得整个进程组退出
@@ -334,7 +347,6 @@ fn signal_wake_up(pcb: Arc<ProcessControlBlock>, fatal: bool) {
     // debug!("signal_wake_up");
     // 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核
     let state = pcb.sched_info().inner_lock_read_irqsave().state();
-    pcb.flags().insert(ProcessFlags::HAS_PENDING_SIGNAL);
     let mut wakeup_ok = true;
     if state.is_blocked_interruptable() {
         ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
@@ -421,6 +433,7 @@ pub fn restore_saved_sigmask() {
             .saved_sigmask();
         __set_current_blocked(&saved);
     }
+    compiler_fence(Ordering::SeqCst);
 }
 
 pub fn restore_saved_sigmask_unless(interrupted: bool) {

+ 150 - 12
kernel/src/ipc/signal_types.rs

@@ -10,7 +10,7 @@ use crate::{
         ipc::signal::{SigFlags, SigSet, Signal, MAX_SIG_NUM},
     },
     mm::VirtAddr,
-    process::RawPid,
+    process::{ProcessManager, RawPid},
     syscall::user_access::UserBufferWriter,
 };
 
@@ -279,10 +279,9 @@ pub struct UserSigaction {
 }
 
 /**
- * siginfo中,根据signal的来源不同,该info中对应了不同的数据./=
- * 请注意,该info最大占用16字节
+ * 内核内部使用的SigInfo结构体,不直接暴露给用户态
+ * 用于内核内部的信号信息存储和处理
  */
-#[repr(C)]
 #[derive(Copy, Clone, Debug)]
 pub struct SigInfo {
     sig_no: i32,
@@ -291,6 +290,111 @@ pub struct SigInfo {
     sig_type: SigType,
 }
 
+/**
+ * 标准POSIX siginfo_t结构体,用于用户态接口
+ * 完全兼容Linux标准,大小为128字节
+ */
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSigInfo {
+    pub si_signo: i32,
+    pub si_code: i32,
+    pub si_errno: i32,
+    pub _sifields: PosixSiginfoFields,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union PosixSiginfoFields {
+    pub _kill: PosixSiginfoKill,
+    pub _timer: PosixSiginfoTimer,
+    pub _rt: PosixSiginfoRt,
+    pub _sigchld: PosixSiginfoSigchld,
+    pub _sigfault: PosixSiginfoSigfault,
+    pub _sigpoll: PosixSiginfoSigpoll,
+    pub _sigsys: PosixSiginfoSigsys,
+    // 填充到128字节
+    _pad: [u8; 128 - 16],
+}
+
+impl core::fmt::Debug for PosixSiginfoFields {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        // 由于是联合体,我们只显示_kill字段作为默认表示
+        f.debug_struct("PosixSiginfoFields")
+            .field("_kill", unsafe { &self._kill })
+            .finish()
+    }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoKill {
+    pub si_pid: i32,
+    pub si_uid: u32,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoTimer {
+    pub si_tid: i32,
+    pub si_overrun: i32,
+    pub si_sigval: PosixSigval,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoRt {
+    pub si_pid: i32,
+    pub si_uid: u32,
+    pub si_sigval: PosixSigval,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoSigchld {
+    pub si_pid: i32,
+    pub si_uid: u32,
+    pub si_status: i32,
+    pub si_utime: i64,
+    pub si_stime: i64,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoSigfault {
+    pub si_addr: u64,
+    pub si_addr_lsb: u16,
+    pub si_band: i32,
+    pub si_fd: i32,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoSigpoll {
+    pub si_band: i64,
+    pub si_fd: i32,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSiginfoSigsys {
+    pub _call_addr: u64,
+    pub _syscall: i32,
+    pub _arch: u32,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct PosixSigval {
+    pub sival_int: i32,
+    pub sival_ptr: u64,
+}
+
+/// 获取当前进程的UID
+fn get_current_uid() -> u32 {
+    ProcessManager::current_pcb().cred().uid.data() as u32
+}
+
 impl SigInfo {
     pub fn sig_code(&self) -> SigCode {
         self.sig_code
@@ -299,24 +403,59 @@ impl SigInfo {
     pub fn set_sig_type(&mut self, sig_type: SigType) {
         self.sig_type = sig_type;
     }
-    /// @brief 将siginfo结构体拷贝到用户栈
+
+    /// 将内核SigInfo转换为标准PosixSigInfo
+    #[inline(never)]
+    pub fn convert_to_posix_siginfo(&self) -> PosixSigInfo {
+        match self.sig_type {
+            SigType::Kill(pid) => PosixSigInfo {
+                si_signo: self.sig_no,
+                si_code: self.sig_code as i32,
+                si_errno: self.errno,
+                _sifields: PosixSiginfoFields {
+                    _kill: PosixSiginfoKill {
+                        si_pid: pid.data() as i32,
+                        si_uid: get_current_uid(),
+                    },
+                },
+            },
+            SigType::Alarm(pid) => PosixSigInfo {
+                si_signo: self.sig_no,
+                si_code: self.sig_code as i32,
+                si_errno: self.errno,
+                _sifields: PosixSiginfoFields {
+                    _timer: PosixSiginfoTimer {
+                        si_tid: pid.data() as i32,
+                        si_overrun: 0,
+                        si_sigval: PosixSigval {
+                            sival_int: 0,
+                            sival_ptr: 0,
+                        },
+                    },
+                },
+            },
+        }
+    }
+
+    /// @brief 将PosixSigInfo结构体拷贝到用户栈
     /// ## 参数
     ///
     /// `to` 用户空间指针
     ///
     /// ## 注意
     ///
+    /// 该函数将内核SigInfo转换为标准PosixSigInfo后拷贝到用户态
+    ///
     /// 该函数对应Linux中的https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c#3323
-    /// Linux还提供了 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c#3383 用来实现
-    /// kernel_siginfo 保存到 用户的 compact_siginfo 的功能,但是我们系统内还暂时没有对这两种
-    /// siginfo做区分,因此暂时不需要第二个函数
-    pub fn copy_siginfo_to_user(&self, to: *mut SigInfo) -> Result<i32, SystemError> {
+    #[inline(never)]
+    pub fn copy_posix_siginfo_to_user(&self, to: *mut PosixSigInfo) -> Result<i32, SystemError> {
         // 验证目标地址是否为用户空间
-        let mut user_buffer = UserBufferWriter::new(to, size_of::<SigInfo>(), true)?;
+        let posix_siginfo = self.convert_to_posix_siginfo();
+        let mut user_buffer = UserBufferWriter::new(to, size_of::<PosixSigInfo>(), true)?;
 
         let retval: Result<i32, SystemError> = Ok(0);
 
-        user_buffer.copy_one_to_user(self, 0)?;
+        user_buffer.copy_one_to_user(&posix_siginfo, 0)?;
         return retval;
     }
 }
@@ -421,7 +560,6 @@ impl SigPending {
     /// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号)
     /// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock
     pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
-        // debug!("dequeue signal");
         // 获取下一个要处理的信号的编号
         let sig = self.next_signal(sig_mask);
 

+ 1 - 0
kernel/src/ipc/syscall/mod.rs

@@ -2,6 +2,7 @@ pub mod sys_kill;
 pub mod sys_pipe2;
 mod sys_restart;
 mod sys_rt_sigprocmask;
+pub mod sys_rt_sigtimedwait;
 mod sys_shmat;
 mod sys_shmctl;
 mod sys_shmdt;

+ 5 - 1
kernel/src/ipc/syscall/sys_kill.rs

@@ -70,9 +70,13 @@ impl Syscall for SysKillHandle {
         let sig_c_int = Self::sig(args);
 
         let converter = PidConverter::from_id(id).ok_or(SystemError::ESRCH)?;
+
         let sig = Signal::from(sig_c_int);
         if sig == Signal::INVALID {
-            warn!("Not a valid signal number");
+            warn!(
+                "Failed to convert signal number {} to Signal enum",
+                sig_c_int
+            );
             return Err(SystemError::EINVAL);
         }
 

+ 294 - 0
kernel/src/ipc/syscall/sys_rt_sigtimedwait.rs

@@ -0,0 +1,294 @@
+//! System call handler for rt_sigtimedwait.
+//!
+//! This module implements the rt_sigtimedwait system call, which allows a process
+//! to wait for specific signals with an optional timeout.
+
+use crate::arch::interrupt::TrapFrame;
+use crate::arch::ipc::signal::{SigSet, Signal};
+use crate::arch::syscall::nr::SYS_RT_SIGTIMEDWAIT;
+use crate::ipc::signal::{restore_saved_sigmask, set_user_sigmask};
+use crate::ipc::signal_types::{PosixSigInfo, SigInfo};
+use crate::process::preempt::PreemptGuard;
+use crate::process::ProcessManager;
+use crate::syscall::{
+    table::{FormattedSyscallParam, Syscall},
+    user_access::{UserBufferReader, UserBufferWriter},
+};
+use crate::time::{jiffies::NSEC_PER_JIFFY, timer::schedule_timeout, PosixTimeSpec};
+use alloc::vec::Vec;
+use core::mem::size_of;
+use syscall_table_macros::declare_syscall;
+use system_error::SystemError;
+
+pub struct SysRtSigtimedwaitHandle;
+
+/// 实现 rt_sigtimedwait 系统调用的核心逻辑
+///
+/// ## 参数
+///
+/// - `uthese`: 要等待的信号集合指针
+/// - `uinfo`: 用于返回信号信息的 siginfo 结构体指针(可为 NULL)
+/// - `uts`: 超时时间指针(可为 NULL 表示无限等待)
+/// - `sigsetsize`: 信号集大小
+/// - `from_user`: 是否来自用户态
+///
+/// ## 返回值
+///
+/// - `Ok(sig_num)`: 捕获到的信号号
+/// - `Err(SystemError::EAGAIN)`: 超时
+/// - `Err(SystemError::EINTR)`: 被非目标信号打断
+/// - `Err(SystemError::EINVAL)`: 参数错误
+/// - `Err(SystemError::EFAULT)`: 用户空间访问错误
+pub fn do_kernel_rt_sigtimedwait(
+    uthese: *const SigSet,
+    uinfo: *mut PosixSigInfo,
+    uts: *const PosixTimeSpec,
+    sigsetsize: usize,
+    from_user: bool,
+) -> Result<usize, SystemError> {
+    // 验证 sigsetsize 参数
+    if sigsetsize != size_of::<SigSet>() {
+        return Err(SystemError::EINVAL);
+    }
+
+    // 从用户空间读取信号集合
+    let these = if uthese.is_null() {
+        return Err(SystemError::EINVAL);
+    } else {
+        let reader = UserBufferReader::new(uthese, size_of::<SigSet>(), from_user)?;
+        let sigset = reader.read_one_from_user::<SigSet>(0)?;
+        // 移除不可屏蔽的信号(SIGKILL 和 SIGSTOP)
+        let sigset_val: SigSet = SigSet::from_bits(sigset.bits()).ok_or(SystemError::EINVAL)?;
+        let kill_stop_mask: SigSet =
+            SigSet::from_bits_truncate((Signal::SIGKILL as u64) | (Signal::SIGSTOP as u64));
+        let result = sigset_val & !kill_stop_mask;
+
+        result
+    };
+
+    // 如果信号集合为空,直接返回 EINVAL(根据 POSIX 标准)
+    if these.is_empty() {
+        return Err(SystemError::EINVAL);
+    }
+
+    // 构造等待/屏蔽语义:与Linux一致
+    // - 等待集合 these
+    // - 临时屏蔽集合 = 旧blocked ∪ these(将这些信号作为masked的常规语义,但仍由本系统调用专门消费)
+    let awaited = these;
+
+    // 快速路径:先尝试从队列中获取信号
+    if let Some((sig, info)) = try_dequeue_signal(&awaited) {
+        // 如果用户提供了 uinfo 指针,拷贝信号信息
+        if !uinfo.is_null() {
+            copy_posix_siginfo_to_user(uinfo, &info, from_user)?;
+        }
+        return Ok(sig as usize);
+    }
+
+    // 设置新的信号掩码并等待
+    let pcb = ProcessManager::current_pcb();
+    let mut new_blocked = *pcb.sig_info_irqsave().sig_blocked();
+    // 按Linux:等待期间屏蔽 these
+    new_blocked.insert(awaited);
+    set_user_sigmask(&mut new_blocked);
+
+    // 计算超时时间
+    let deadline = if uts.is_null() {
+        None // 无限等待
+    } else {
+        let reader = UserBufferReader::new(uts, size_of::<PosixTimeSpec>(), from_user)?;
+        let timeout = reader.read_one_from_user::<PosixTimeSpec>(0)?;
+        let deadline = compute_deadline(*timeout)?;
+        Some(deadline)
+    };
+
+    // 等待循环(prepare-to-wait 语义)
+    let mut _loop_count = 0;
+    loop {
+        _loop_count += 1;
+
+        // 第一步:准备进入可中断阻塞,先将当前线程标记为可中断阻塞,关闭中断,避免错过唤醒窗口
+        let preempt_guard = PreemptGuard::new();
+        // 第二步:在“已是可中断阻塞状态”下,重检是否已有目标信号,若有则不睡眠,恢复为 runnable 并返回
+        if has_pending_awaited_signal(&awaited) {
+            drop(preempt_guard);
+
+            if let Some((sig, info)) = try_dequeue_signal(&awaited) {
+                restore_saved_sigmask();
+                if !uinfo.is_null() {
+                    copy_posix_siginfo_to_user(uinfo, &info, from_user)?;
+                }
+                return Ok(sig as usize);
+            }
+            // 有 pending 但未从 awaited 集取到(被其他信号打断)
+            restore_saved_sigmask();
+            return Err(SystemError::EINTR);
+        }
+
+        // 第三步:检查是否已超时;若已超时则不睡眠,恢复为 runnable 并返回超时
+        if let Some(deadline) = deadline {
+            if is_timeout_expired(deadline) {
+                drop(preempt_guard);
+                restore_saved_sigmask();
+                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+            }
+        }
+
+        // 第四步:释放中断,然后真正进入调度睡眠(窗口期内,线程保持可中断阻塞,发送侧会唤醒)
+
+        // 计算剩余等待时间
+        let remaining_time = if let Some(deadline) = deadline {
+            let now = PosixTimeSpec::now();
+            let remaining = deadline.total_nanos() - now.total_nanos();
+            if remaining <= 0 {
+                restore_saved_sigmask();
+                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+            }
+            remaining / (NSEC_PER_JIFFY as i64)
+        } else {
+            i64::MAX
+        };
+
+        drop(preempt_guard);
+        if let Err(e) = schedule_timeout(remaining_time) {
+            restore_saved_sigmask();
+            return Err(e);
+        }
+        // 被唤醒后回到循环起点,继续重检条件
+    }
+}
+
+/// 尝试从信号队列中取出信号
+fn try_dequeue_signal(awaited: &SigSet) -> Option<(Signal, SigInfo)> {
+    let pcb = ProcessManager::current_pcb();
+    let _current_pid = pcb.raw_pid();
+
+    let mut siginfo_guard = pcb.sig_info_mut();
+    let pending = siginfo_guard.sig_pending_mut();
+
+    // 检查 per-thread pending
+    // 仅允许从 awaited 集合中取信号:将"忽略掩码"设为 !awaited
+    let ignore_mask = !*awaited;
+    if let (sig, Some(info)) = pending.dequeue_signal(&ignore_mask) {
+        if sig != Signal::INVALID {
+            return Some((sig, info));
+        }
+    }
+
+    drop(siginfo_guard);
+
+    // 检查 shared pending
+    let (sig, info) = pcb.sighand().shared_pending_dequeue(&ignore_mask);
+
+    if sig != Signal::INVALID {
+        if let Some(info) = info {
+            return Some((sig, info));
+        }
+    }
+
+    None
+}
+
+/// 检查是否有未屏蔽的待处理信号
+fn has_pending_awaited_signal(awaited: &SigSet) -> bool {
+    let pcb = ProcessManager::current_pcb();
+    let _current_pid = pcb.raw_pid();
+    let siginfo_guard = pcb.sig_info_irqsave();
+    let pending_set = siginfo_guard.sig_pending().signal();
+    drop(siginfo_guard);
+
+    let shared_pending_set = pcb.sighand().shared_pending_signal();
+    let result = pending_set.union(shared_pending_set);
+    // 只看 awaited 与 pending 的交集
+    let intersection = result.intersection(*awaited);
+    let has = !intersection.is_empty();
+
+    has
+}
+
+/// 计算超时截止时间
+fn compute_deadline(timeout: PosixTimeSpec) -> Result<PosixTimeSpec, SystemError> {
+    if timeout.tv_sec < 0 || timeout.tv_nsec < 0 || timeout.tv_nsec >= 1_000_000_000 {
+        return Err(SystemError::EINVAL);
+    }
+
+    let now = PosixTimeSpec::now();
+    Ok(PosixTimeSpec {
+        tv_sec: now.tv_sec + timeout.tv_sec,
+        tv_nsec: now.tv_nsec + timeout.tv_nsec,
+    })
+}
+
+/// 检查是否超时
+fn is_timeout_expired(deadline: PosixTimeSpec) -> bool {
+    let now = PosixTimeSpec::now();
+    now.total_nanos() >= deadline.total_nanos()
+}
+
+/// 将 PosixSigInfo 拷贝到用户空间
+fn copy_posix_siginfo_to_user(
+    uinfo: *mut PosixSigInfo,
+    info: &SigInfo,
+    from_user: bool,
+) -> Result<(), SystemError> {
+    if uinfo.is_null() {
+        return Ok(());
+    }
+
+    let posix_siginfo = info.convert_to_posix_siginfo();
+    let mut writer = UserBufferWriter::new(uinfo, size_of::<PosixSigInfo>(), from_user)?;
+    writer.copy_one_to_user(&posix_siginfo, 0)?;
+    Ok(())
+}
+
+impl SysRtSigtimedwaitHandle {
+    #[inline(always)]
+    fn uthese(args: &[usize]) -> *const SigSet {
+        args[0] as *const SigSet
+    }
+
+    #[inline(always)]
+    fn uinfo(args: &[usize]) -> *mut PosixSigInfo {
+        args[1] as *mut PosixSigInfo
+    }
+
+    #[inline(always)]
+    fn uts(args: &[usize]) -> *const PosixTimeSpec {
+        args[2] as *const PosixTimeSpec
+    }
+
+    #[inline(always)]
+    fn sigsetsize(args: &[usize]) -> usize {
+        args[3]
+    }
+}
+
+impl Syscall for SysRtSigtimedwaitHandle {
+    fn num_args(&self) -> usize {
+        4
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        let uthese = Self::uthese(args);
+        let uinfo = Self::uinfo(args);
+        let uts = Self::uts(args);
+        let sigsetsize = Self::sigsetsize(args);
+
+        vec![
+            FormattedSyscallParam::new("uthese", format!("{:#x}", uthese as usize)),
+            FormattedSyscallParam::new("uinfo", format!("{:#x}", uinfo as usize)),
+            FormattedSyscallParam::new("uts", format!("{:#x}", uts as usize)),
+            FormattedSyscallParam::new("sigsetsize", format!("{}", sigsetsize)),
+        ]
+    }
+
+    fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
+        let uthese = Self::uthese(args);
+        let uinfo = Self::uinfo(args);
+        let uts = Self::uts(args);
+        let sigsetsize = Self::sigsetsize(args);
+        do_kernel_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize, true)
+    }
+}
+
+declare_syscall!(SYS_RT_SIGTIMEDWAIT, SysRtSigtimedwaitHandle);

+ 2 - 18
kernel/src/process/mod.rs

@@ -2,7 +2,7 @@ use core::{
     fmt,
     hash::Hash,
     hint::spin_loop,
-    intrinsics::{likely, unlikely},
+    intrinsics::unlikely,
     mem::ManuallyDrop,
     sync::atomic::{compiler_fence, fence, AtomicBool, AtomicUsize, Ordering},
 };
@@ -85,6 +85,7 @@ pub mod idle;
 pub mod kthread;
 pub mod namespace;
 pub mod pid;
+pub mod preempt;
 pub mod process_group;
 pub mod resource;
 pub mod session;
@@ -190,22 +191,6 @@ impl ProcessManager {
         return ProcessManager::current_pcb().raw_pid();
     }
 
-    /// 增加当前进程的锁持有计数
-    #[inline(always)]
-    pub fn preempt_disable() {
-        if likely(unsafe { __PROCESS_MANAGEMENT_INIT_DONE }) {
-            ProcessManager::current_pcb().preempt_disable();
-        }
-    }
-
-    /// 减少当前进程的锁持有计数
-    #[inline(always)]
-    pub fn preempt_enable() {
-        if likely(unsafe { __PROCESS_MANAGEMENT_INIT_DONE }) {
-            ProcessManager::current_pcb().preempt_enable();
-        }
-    }
-
     /// 根据pid获取进程的pcb
     ///
     /// ## 参数
@@ -432,7 +417,6 @@ impl ProcessManager {
 
         // 关中断
         let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
-
         let pid: Arc<Pid>;
         let raw_pid = ProcessManager::current_pid();
         {

+ 36 - 0
kernel/src/process/preempt.rs

@@ -0,0 +1,36 @@
+use core::intrinsics::likely;
+
+use crate::process::{ProcessManager, __PROCESS_MANAGEMENT_INIT_DONE};
+
+pub struct PreemptGuard;
+
+impl PreemptGuard {
+    pub fn new() -> Self {
+        ProcessManager::preempt_disable();
+        Self
+    }
+}
+
+impl Drop for PreemptGuard {
+    fn drop(&mut self) {
+        ProcessManager::preempt_enable();
+    }
+}
+
+impl ProcessManager {
+    /// 增加当前进程的锁持有计数
+    #[inline(always)]
+    pub fn preempt_disable() {
+        if likely(unsafe { __PROCESS_MANAGEMENT_INIT_DONE }) {
+            ProcessManager::current_pcb().preempt_disable();
+        }
+    }
+
+    /// 减少当前进程的锁持有计数
+    #[inline(always)]
+    pub fn preempt_enable() {
+        if likely(unsafe { __PROCESS_MANAGEMENT_INIT_DONE }) {
+            ProcessManager::current_pcb().preempt_enable();
+        }
+    }
+}

+ 0 - 4
kernel/src/syscall/mod.rs

@@ -399,10 +399,6 @@ impl Syscall {
                 Self::sys_perf_event_open(attr, pid, cpu, group_fd, flags)
             }
 
-            SYS_RT_SIGTIMEDWAIT => {
-                log::warn!("SYS_RT_SIGTIMEDWAIT has not yet been implemented");
-                Ok(0)
-            }
             _ => {
                 log::error!(
                     "Unsupported syscall ID: {} -> {}, args: {:?}",

+ 304 - 0
user/apps/c_unitest/test_rt_sigtimedwait.c

@@ -0,0 +1,304 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/types.h>
+
+// 兼容性处理:获取 SYS_rt_sigtimedwait 宏
+#ifndef SYS_rt_sigtimedwait
+#  ifdef __NR_rt_sigtimedwait
+#    define SYS_rt_sigtimedwait __NR_rt_sigtimedwait
+#  else
+#    error "SYS_rt_sigtimedwait 未定义,无法直接进行系统调用测试"
+#  endif
+#endif
+
+// libc 包装:优先使用 sigtimedwait,保证在不同libc/内核下参数兼容
+static int rt_sigtimedwait_libc(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) {
+    return sigtimedwait(set, info, timeout);
+}
+
+// 原始syscall:用于特定场景(如测试非法sigsetsize)
+static int sys_rt_sigtimedwait_raw(const sigset_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) {
+    return (int)syscall(SYS_rt_sigtimedwait, set, info, timeout, sigsetsize);
+}
+
+// 测试统计
+static int total_tests = 0;
+static int passed_tests = 0;
+static int failed_tests = 0;
+static char failed_test_names[200][256];
+static int failed_test_count = 0;
+
+#define TEST_ASSERT(condition, test_name) do { \
+    total_tests++; \
+    if (condition) { \
+        passed_tests++; \
+        printf("PASS - %s\n", test_name); \
+    } else { \
+        failed_tests++; \
+        if (failed_test_count < 200) { \
+            snprintf(failed_test_names[failed_test_count], sizeof(failed_test_names[failed_test_count]), "%s", test_name); \
+            failed_test_count++; \
+        } \
+        printf("FAIL - %s (errno=%d: %s)\n", test_name, errno, strerror(errno)); \
+    } \
+} while(0)
+
+// 工具函数:阻塞/解除阻塞 指定信号
+static int block_signal(int sig, sigset_t *oldset) {
+    sigset_t set;
+    sigemptyset(&set);
+    sigaddset(&set, sig);
+    return pthread_sigmask(SIG_BLOCK, &set, oldset);
+}
+
+static int unblock_signal(int sig, const sigset_t *oldset) {
+    (void)sig; // 未使用,仅保持接口对称
+    return pthread_sigmask(SIG_SETMASK, oldset, NULL);
+}
+
+// 工具函数:使用rt_sigtimedwait带0超时轮询一次并(如存在)清理信号
+static int poll_and_consume_signal_once(int sig) {
+    sigset_t set;
+    siginfo_t info;
+    struct timespec ts = {0, 0};
+    sigemptyset(&set);
+    sigaddset(&set, sig);
+    int r = rt_sigtimedwait_libc(&set, &info, &ts);
+    return r; // =sig 表示读到并消费;-1 且 errno=EAGAIN 表示无;其它为异常
+}
+
+// 用于线程延迟发送信号
+typedef struct {
+    pid_t pid;
+    int sig;
+    int delay_ms;
+} sender_args_t;
+
+static void *delayed_kill_sender(void *arg) {
+    sender_args_t *a = (sender_args_t *)arg;
+    // 确保该线程不接收要发送的信号:阻塞之,让信号成为进程待处理,供主线程 sigtimedwait 消费
+    sigset_t set, oldset;
+    sigemptyset(&set);
+    sigaddset(&set, a->sig);
+    pthread_sigmask(SIG_BLOCK, &set, &oldset);
+
+    struct timespec ts;
+    ts.tv_sec = a->delay_ms / 1000;
+    ts.tv_nsec = (long)(a->delay_ms % 1000) * 1000000L;
+    nanosleep(&ts, NULL);
+
+    printf("[TEST_DEBUG]:delayed_kill_sender to kill %d sig %d\n", a->pid, a->sig);
+    // 进程定向发送
+    kill(a->pid, a->sig);
+    printf("[TEST_DEBUG]:delayed_kill_sender killed %d sig %d\n", a->pid, a->sig);
+    // 还原该线程掩码
+    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+    printf("[TEST_DEBUG]:delayed_kill_sender unblocked %d sig %d\n", a->pid, a->sig);
+    return NULL;
+}
+
+// 基础功能:阻塞SIGUSR1 -> 自发 -> rt_sigtimedwait应立即返回该信号
+static void test_rt_sigtimedwait_basic_self_kill_SIGUSR1() {
+    printf("=== 测试: 基础 - 阻塞SIGUSR1后自发并等待 ===\n");
+
+    sigset_t oldset;
+    int rc = block_signal(SIGUSR1, &oldset);
+    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");
+
+    // 确保没有遗留的待处理SIGUSR1
+    while (poll_and_consume_signal_once(SIGUSR1) == SIGUSR1) {}
+
+    // 发送到自身
+    pid_t me = getpid();
+    rc = kill(me, SIGUSR1);
+    TEST_ASSERT(rc == 0, "向自身发送SIGUSR1");
+
+    sigset_t waitset;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIGUSR1);
+
+    siginfo_t info;
+    struct timespec timeout = {2, 0}; // 2秒超时,正常应很快返回
+    int ret = rt_sigtimedwait_libc(&waitset, &info, &timeout);
+    TEST_ASSERT(ret == SIGUSR1, "rt_sigtimedwait 返回SIGUSR1");
+    if (ret == SIGUSR1) {
+        TEST_ASSERT(info.si_signo == SIGUSR1, "info.si_signo == SIGUSR1");
+        // kill() 产生的应为 SI_USER
+        TEST_ASSERT(info.si_code == SI_USER, "info.si_code == SI_USER");
+        TEST_ASSERT(info.si_pid == me, "info.si_pid 为当前进程");
+        TEST_ASSERT(info.si_uid == getuid(), "info.si_uid 为当前用户");
+    }
+
+    rc = unblock_signal(SIGUSR1, &oldset);
+    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
+}
+
+// 超时:等待一个未发送的被阻塞信号,短超时应返回EAGAIN
+static void test_rt_sigtimedwait_timeout() {
+    printf("\n=== 测试: 超时 - 无信号到达时返回EAGAIN ===\n");
+
+    const int sig = SIGUSR2;
+    sigset_t oldset;
+    int rc = block_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "阻塞SIGUSR2");
+
+    // 清理可能的遗留
+    while (poll_and_consume_signal_once(sig) == sig) {}
+
+    sigset_t waitset;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, sig);
+
+    siginfo_t info;
+    struct timespec timeout = {0, 100 * 1000 * 1000}; // 100ms
+    int ret = rt_sigtimedwait_libc(&waitset, &info, &timeout);
+    TEST_ASSERT(ret == -1 && errno == EAGAIN, "无信号到达时超时返回EAGAIN");
+
+    rc = unblock_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
+}
+
+// 非法timespec:tv_nsec越界应返回EINVAL
+static void test_rt_sigtimedwait_invalid_timespec() {
+    printf("\n=== 测试: 参数校验 - 非法timespec返回EINVAL ===\n");
+
+    const int sig = SIGUSR1;
+    sigset_t oldset;
+    int rc = block_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");
+
+    sigset_t waitset;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, sig);
+
+    siginfo_t info;
+    struct timespec bad = { .tv_sec = 0, .tv_nsec = 2000000000L }; // > 1e9-1
+    int ret = rt_sigtimedwait_libc(&waitset, &info, &bad);
+    TEST_ASSERT(ret == -1 && errno == EINVAL, "tv_nsec越界 -> EINVAL");
+
+    rc = unblock_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
+}
+
+// 延迟发送:NULL超时指针(无限等待) + 后台线程延迟发送实时信号,调用应被唤醒并返回
+static void test_rt_sigtimedwait_null_timeout_with_delayed_rt_signal() {
+    printf("\n=== 测试: NULL超时 + 延迟发送SIGRTMIN+1 ===\n");
+
+    int rtsig = SIGRTMIN + 1;
+    sigset_t oldset;
+    int rc = block_signal(rtsig, &oldset);
+    TEST_ASSERT(rc == 0, "阻塞SIGRTMIN+1");
+
+    // 线程延迟发送
+    pthread_t th;
+    sender_args_t args = { .pid = getpid(), .sig = rtsig, .delay_ms = 100 };
+    rc = pthread_create(&th, NULL, delayed_kill_sender, &args);
+    TEST_ASSERT(rc == 0, "创建延迟发送线程");
+
+    sigset_t waitset;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, rtsig);
+    siginfo_t info;
+    printf("[TEST_DEBUG]: to call rt_sigtimedwait_libc\n");
+    // NULL超时:按规范为无限等待,但我们确保100ms内会到信号
+    int ret = rt_sigtimedwait_libc(&waitset, &info, NULL);
+    printf("[TEST_DEBUG]: rt_sigtimedwait_libc returned %d\n", ret);
+    TEST_ASSERT(ret == rtsig, "rt_sigtimedwait(NULL) 收到实时信号");
+    if (ret == rtsig) {
+        TEST_ASSERT(info.si_signo == rtsig, "info.si_signo == 发送的实时信号");
+        TEST_ASSERT((info.si_code == SI_USER) || (info.si_code == SI_TKILL) || (info.si_code == SI_QUEUE), "info.si_code 合理");
+        TEST_ASSERT(info.si_pid == getpid(), "info.si_pid 为当前进程");
+    }
+    printf("[TEST_DEBUG]: to join thread\n");
+    if (rc == 0) {
+        pthread_join(th, NULL);
+    }
+    printf("[TEST_DEBUG]: to unblock signal\n");
+    rc = unblock_signal(rtsig, &oldset);
+    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
+}
+
+// 零超时轮询:ts={0,0} 未有信号立刻返回EAGAIN
+static void test_rt_sigtimedwait_zero_timeout_poll() {
+    printf("\n=== 测试: 轮询模式 - 零超时无信号返回EAGAIN ===\n");
+
+    const int sig = SIGUSR1;
+    sigset_t oldset;
+    int rc = block_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");
+
+    // 清空待处理
+    while (poll_and_consume_signal_once(sig) == sig) {}
+
+    sigset_t waitset;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, sig);
+
+    siginfo_t info;
+    struct timespec ts = {0, 0};
+    int ret = rt_sigtimedwait_libc(&waitset, &info, &ts);
+    TEST_ASSERT(ret == -1 && errno == EAGAIN, "零超时无信号 -> EAGAIN");
+
+    rc = unblock_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
+}
+
+// 非法sigsetsize:传0期望返回EINVAL(具体行为依赖内核,这里按Linux常见实现)
+static void test_rt_sigtimedwait_invalid_sigsetsize() {
+    printf("\n=== 测试: 参数校验 - 非法sigsetsize返回EINVAL ===\n");
+
+    const int sig = SIGUSR1;
+    sigset_t oldset;
+    int rc = block_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");
+
+    sigset_t waitset;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, sig);
+
+    siginfo_t info;
+    struct timespec ts = {0, 0};
+    int ret = sys_rt_sigtimedwait_raw(&waitset, &info, &ts, 0 /* 非法大小 */);
+    TEST_ASSERT(ret == -1 && errno == EINVAL, "sigsetsize=0 -> EINVAL");
+
+    rc = unblock_signal(sig, &oldset);
+    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
+}
+
+int main() {
+    printf("开始 rt_sigtimedwait 系统调用测试\n");
+    printf("当前进程 PID=%d\n", getpid());
+
+    test_rt_sigtimedwait_basic_self_kill_SIGUSR1();
+    test_rt_sigtimedwait_timeout();
+    test_rt_sigtimedwait_invalid_timespec();
+    test_rt_sigtimedwait_null_timeout_with_delayed_rt_signal();
+    test_rt_sigtimedwait_zero_timeout_poll();
+    test_rt_sigtimedwait_invalid_sigsetsize();
+
+    printf("\n=== rt_sigtimedwait 测试完成 ===\n");
+    printf("\n=== 测试结果总结 ===\n");
+    printf("总测试数: %d\n", total_tests);
+    printf("通过: %d\n", passed_tests);
+    printf("失败: %d\n", failed_tests);
+    printf("成功率: %.1f%%\n", total_tests > 0 ? (float)passed_tests / total_tests * 100 : 0);
+
+    if (failed_tests > 0) {
+        printf("\n失败的测试用例:\n");
+        for (int i = 0; i < failed_test_count; i++) {
+            printf("  - %s\n", failed_test_names[i]);
+        }
+    } else {
+        printf("\n所有测试用例都通过了!\n");
+    }
+
+    return failed_tests > 0 ? 1 : 0;
+}