Przeglądaj źródła

Signal refactor (#402)

* 初步完成对 signal_types 和 部分signal代码的初始化

* 重构了一部分架构相关代码进入 arch 中

* 基本修改完成,编译通过,后续补上系统调用

* signal基本完成,能实现 Sigaction 系统调用

* 增加了一组枚举抽象

* 进一步重构了一部分C风格的代码

* 继续重构了一部分C风格代码

* 继续完善了一部分逻辑

* 修改了部分代码逻辑

* 补充了 fork 中复制信号信息的逻辑

* 修复了 kallsysms 未转义引号的问题

* 修复了无法跳转到 sigreturn 的bug

* 调通了 signal

* 实现了 signal 架构抽象层的 trait

* 为信号提供了默认处理函数

* 基本完成了 signal 的大体逻辑

* 修复了 Sigreturn 的一个小错误,格式化

* 修复了一个编译器漏报错误

* 删除了多余的代码

* 修改测试程序为链接 relibc

* 修复了信号处理过程中浮点寄存器错误保存的问题

* 修复了一个结构体错误引起的无法在relibc下正确运行的错误

* 修复了链接 relibc 时无法正常从信号处理返回的 bug

* 修复了 signal 处理流程中 rsp 指针错误导致的浮点运算触发GP

* 修复了一个死锁问题,解决了默认处理函数无法进入调度导致的bug

* 修复了一些错误

* 修改了 relibc 依赖版本号

* 删除了多余的 imports

* 删除一些debug日志

* 删除内核 signal.h 文件

* 删除一个依赖项

* 删除了 binding 相关依赖项
Chiichen 1 rok temu
rodzic
commit
3c82aa56d1

+ 0 - 1
.vscode/settings.json

@@ -160,7 +160,6 @@
         "wait.h": "c",
         "__libc__.h": "c",
         "ctype.h": "c",
-        "signal.h": "c",
         "mmio.h": "c",
         "stdint-gcc.h": "c",
         "acpi.h": "c",

+ 2 - 1
kernel/src/arch/x86_64/fpu.rs

@@ -60,9 +60,10 @@ impl FpState {
         }
     }
 
-    /// 清空fp_state
+    /// 清空浮点寄存器
     #[allow(dead_code)]
     pub fn clear(&mut self) {
         *self = Self::default();
+        self.restore();
     }
 }

+ 1 - 10
kernel/src/arch/x86_64/ipc/mod.rs

@@ -1,10 +1 @@
-use super::interrupt::TrapFrame;
-
-use crate::{arch::CurrentIrqArch, exception::InterruptArch};
-
-#[no_mangle]
-pub unsafe extern "C" fn do_signal(_frame: &mut TrapFrame) {
-    CurrentIrqArch::interrupt_enable();
-    // todo: 处理信号
-    return;
-}
+pub mod signal;

+ 679 - 0
kernel/src/arch/x86_64/ipc/signal.rs

@@ -0,0 +1,679 @@
+use core::{ffi::c_void, mem::size_of};
+
+use crate::{
+    arch::{
+        fpu::FpState,
+        interrupt::TrapFrame,
+        process::table::{USER_CS, USER_DS},
+        sched::sched,
+        CurrentIrqArch, MMArch,
+    },
+    exception::InterruptArch,
+    ipc::{
+        signal::set_current_sig_blocked,
+        signal_types::{SaHandlerType, SigInfo, Sigaction, SigactionType, SignalArch},
+    },
+    kerror,
+    mm::MemoryManagementArch,
+    process::ProcessManager,
+    syscall::{user_access::UserBufferWriter, Syscall, SystemError},
+};
+
+/// 信号处理的栈的栈指针的最小对齐数量
+pub const STACK_ALIGN: u64 = 16;
+/// 信号最大值
+pub const MAX_SIG_NUM: usize = 64;
+#[allow(dead_code)]
+#[derive(Debug, Clone, Copy, Eq)]
+#[repr(usize)]
+#[allow(non_camel_case_types)]
+pub enum Signal {
+    INVALID = 0,
+    SIGHUP = 1,
+    SIGINT,
+    SIGQUIT,
+    SIGILL,
+    SIGTRAP,
+    /// SIGABRT和SIGIOT共用这个号码
+    SIGABRT_OR_IOT,
+    SIGBUS,
+    SIGFPE,
+    SIGKILL,
+    SIGUSR1,
+
+    SIGSEGV = 11,
+    SIGUSR2,
+    SIGPIPE,
+    SIGALRM,
+    SIGTERM,
+    SIGSTKFLT,
+    SIGCHLD,
+    SIGCONT,
+    SIGSTOP,
+    SIGTSTP,
+
+    SIGTTIN = 21,
+    SIGTTOU,
+    SIGURG,
+    SIGXCPU,
+    SIGXFSZ,
+    SIGVTALRM,
+    SIGPROF,
+    SIGWINCH,
+    /// SIGIO和SIGPOLL共用这个号码
+    SIGIO_OR_POLL,
+    SIGPWR,
+
+    SIGSYS = 31,
+
+    SIGRTMIN = 32,
+    SIGRTMAX = 64,
+}
+
+/// 为Signal实现判断相等的trait
+impl PartialEq for Signal {
+    fn eq(&self, other: &Signal) -> bool {
+        *self as usize == *other as usize
+    }
+}
+
+impl From<usize> for Signal {
+    fn from(value: usize) -> Self {
+        if value <= MAX_SIG_NUM {
+            let ret: Signal = unsafe { core::mem::transmute(value) };
+            return ret;
+        } else {
+            kerror!("Try to convert an invalid number to Signal");
+            return Signal::INVALID;
+        }
+    }
+}
+
+impl Into<usize> for Signal {
+    fn into(self) -> usize {
+        self as usize
+    }
+}
+
+impl From<i32> for Signal {
+    fn from(value: i32) -> Self {
+        if value < 0 {
+            kerror!("Try to convert an invalid number to Signal");
+            return Signal::INVALID;
+        } else {
+            return Self::from(value as usize);
+        }
+    }
+}
+
+impl Into<SigSet> for Signal {
+    fn into(self) -> SigSet {
+        SigSet {
+            bits: (1 << (self as usize - 1) as u64),
+        }
+    }
+}
+impl Signal {
+    /// 判断一个数字是否为可用的信号
+    #[inline]
+    pub fn is_valid(&self) -> bool {
+        return (*self) as usize <= MAX_SIG_NUM;
+    }
+
+    /// const convertor between `Signal` and `SigSet`
+    pub const fn into_sigset(self) -> SigSet {
+        SigSet {
+            bits: (1 << (self as usize - 1) as u64),
+        }
+    }
+
+    /// 判断一个信号是不是实时信号
+    ///
+    /// ## 返回值
+    ///
+    /// - `true` 这个信号是实时信号
+    /// - `false` 这个信号不是实时信号
+    #[inline]
+    pub fn is_rt_signal(&self) -> bool {
+        return (*self) as usize >= Signal::SIGRTMIN.into();
+    }
+
+    /// 调用信号的默认处理函数
+    pub fn handle_default(&self) {
+        match self {
+            Signal::INVALID => {
+                kerror!("attempting to handler an Invalid");
+            }
+            Signal::SIGHUP => sig_terminate(self.clone()),
+            Signal::SIGINT => sig_terminate(self.clone()),
+            Signal::SIGQUIT => sig_terminate_dump(self.clone()),
+            Signal::SIGILL => sig_terminate_dump(self.clone()),
+            Signal::SIGTRAP => sig_terminate_dump(self.clone()),
+            Signal::SIGABRT_OR_IOT => sig_terminate_dump(self.clone()),
+            Signal::SIGBUS => sig_terminate_dump(self.clone()),
+            Signal::SIGFPE => sig_terminate_dump(self.clone()),
+            Signal::SIGKILL => sig_terminate(self.clone()),
+            Signal::SIGUSR1 => sig_terminate(self.clone()),
+            Signal::SIGSEGV => sig_terminate_dump(self.clone()),
+            Signal::SIGUSR2 => sig_terminate(self.clone()),
+            Signal::SIGPIPE => sig_terminate(self.clone()),
+            Signal::SIGALRM => sig_terminate(self.clone()),
+            Signal::SIGTERM => sig_terminate(self.clone()),
+            Signal::SIGSTKFLT => sig_terminate(self.clone()),
+            Signal::SIGCHLD => sig_ignore(self.clone()),
+            Signal::SIGCONT => sig_continue(self.clone()),
+            Signal::SIGSTOP => sig_stop(self.clone()),
+            Signal::SIGTSTP => sig_stop(self.clone()),
+            Signal::SIGTTIN => sig_stop(self.clone()),
+            Signal::SIGTTOU => sig_stop(self.clone()),
+            Signal::SIGURG => sig_ignore(self.clone()),
+            Signal::SIGXCPU => sig_terminate_dump(self.clone()),
+            Signal::SIGXFSZ => sig_terminate_dump(self.clone()),
+            Signal::SIGVTALRM => sig_terminate(self.clone()),
+            Signal::SIGPROF => sig_terminate(self.clone()),
+            Signal::SIGWINCH => sig_ignore(self.clone()),
+            Signal::SIGIO_OR_POLL => sig_terminate(self.clone()),
+            Signal::SIGPWR => sig_terminate(self.clone()),
+            Signal::SIGSYS => sig_terminate(self.clone()),
+            Signal::SIGRTMIN => sig_terminate(self.clone()),
+            Signal::SIGRTMAX => sig_terminate(self.clone()),
+        }
+    }
+}
+
+/// siginfo中的si_code的可选值
+/// 请注意,当这个值小于0时,表示siginfo来自用户态,否则来自内核态
+#[derive(Copy, Debug, Clone)]
+#[repr(i32)]
+pub enum SigCode {
+    /// sent by kill, sigsend, raise
+    User = 0,
+    /// sent by kernel from somewhere
+    Kernel = 0x80,
+    /// 通过sigqueue发送
+    Queue = -1,
+    /// 定时器过期时发送
+    Timer = -2,
+    /// 当实时消息队列的状态发生改变时发送
+    Mesgq = -3,
+    /// 当异步IO完成时发送
+    AsyncIO = -4,
+    /// sent by queued SIGIO
+    SigIO = -5,
+}
+
+impl SigCode {
+    /// 为SigCode这个枚举类型实现从i32转换到枚举类型的转换函数
+    #[allow(dead_code)]
+    pub fn from_i32(x: i32) -> SigCode {
+        match x {
+            0 => Self::User,
+            0x80 => Self::Kernel,
+            -1 => Self::Queue,
+            -2 => Self::Timer,
+            -3 => Self::Mesgq,
+            -4 => Self::AsyncIO,
+            -5 => Self::SigIO,
+            _ => panic!("signal code not valid"),
+        }
+    }
+}
+
+bitflags! {
+    #[repr(C,align(8))]
+    #[derive(Default)]
+    pub struct SigFlags:u32{
+        const SA_NOCLDSTOP =  1;
+        const SA_NOCLDWAIT = 2;
+        const SA_SIGINFO   = 4;
+        const SA_ONSTACK   = 0x08000000;
+        const SA_RESTART   = 0x10000000;
+        const SA_NODEFER  = 0x40000000;
+        const SA_RESETHAND = 0x80000000;
+        const SA_RESTORER   =0x04000000;
+        const SA_ALL = Self::SA_NOCLDSTOP.bits()|Self::SA_NOCLDWAIT.bits()|Self::SA_NODEFER.bits()|Self::SA_ONSTACK.bits()|Self::SA_RESETHAND.bits()|Self::SA_RESTART.bits()|Self::SA_SIGINFO.bits()|Self::SA_RESTORER.bits();
+    }
+
+    /// 请注意,sigset 这个bitmap, 第0位表示sig=1的信号。也就是说,Signal-1才是sigset_t中对应的位
+    #[derive(Default)]
+    pub struct SigSet:u64{
+        const SIGHUP   =  1<<0;
+        const SIGINT   =  1<<1;
+        const SIGQUIT  =  1<<2;
+        const SIGILL   =  1<<3;
+        const SIGTRAP  =  1<<4;
+        /// SIGABRT和SIGIOT共用这个号码
+        const SIGABRT_OR_IOT    =    1<<5;
+        const SIGBUS   =  1<<6;
+        const SIGFPE   =  1<<7;
+        const SIGKILL  =  1<<8;
+        const SIGUSR   =  1<<9;
+        const SIGSEGV  =  1<<10;
+        const SIGUSR2  =  1<<11;
+        const SIGPIPE  =  1<<12;
+        const SIGALRM  =  1<<13;
+        const SIGTERM  =  1<<14;
+        const SIGSTKFLT=  1<<15;
+        const SIGCHLD  =  1<<16;
+        const SIGCONT  =  1<<17;
+        const SIGSTOP  =  1<<18;
+        const SIGTSTP  =  1<<19;
+        const SIGTTIN  =  1<<20;
+        const SIGTTOU  =  1<<21;
+        const SIGURG   =  1<<22;
+        const SIGXCPU  =  1<<23;
+        const SIGXFSZ  =  1<<24;
+        const SIGVTALRM=  1<<25;
+        const SIGPROF  =  1<<26;
+        const SIGWINCH =  1<<27;
+        /// SIGIO和SIGPOLL共用这个号码
+        const SIGIO_OR_POLL    =   1<<28;
+        const SIGPWR   =  1<<29;
+        const SIGSYS   =  1<<30;
+        const SIGRTMIN =  1<<31;
+        // TODO 写上实时信号
+        const SIGRTMAX =  1<<MAX_SIG_NUM-1;
+    }
+}
+
+#[repr(C, align(16))]
+#[derive(Debug, Clone, Copy)]
+pub struct SigFrame {
+    // pub pedding: u64,
+    /// 指向restorer的地址的指针。(该变量必须放在sigframe的第一位,因为这样才能在handler返回的时候,跳转到对应的代码,执行sigreturn)
+    pub ret_code_ptr: *mut core::ffi::c_void,
+    pub handler: *mut c_void,
+    pub info: SigInfo,
+    pub context: SigContext,
+}
+
+#[repr(C, align(16))]
+#[derive(Debug, Clone, Copy)]
+pub struct SigContext {
+    /// sigcontext的标志位
+    pub sc_flags: u64,
+    pub sc_stack: SigStack, // 信号处理程序备用栈信息
+    pub frame: TrapFrame,   // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
+    // pub trap_num: u64,    // 用来保存线程结构体中的trap_num字段
+    pub oldmask: SigSet, // 暂存的执行信号处理函数之前的,被设置block的信号
+    pub cr2: u64,        // 用来保存线程结构体中的cr2字段
+    // pub err_code: u64,    // 用来保存线程结构体中的err_code字段
+    pub reserved_for_x87_state: Option<FpState>,
+    pub reserved: [u64; 8],
+}
+
+impl SigContext {
+    /// 设置sigcontext
+    ///
+    /// ## 参数
+    ///
+    /// - `mask` 要被暂存的信号mask标志位
+    /// - `regs` 进入信号处理流程前,Restore all要弹出的内核栈栈帧
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok(0)`
+    /// - `Err(Systemerror)` (暂时不会返回错误)
+    pub fn setup_sigcontext(
+        &mut self,
+        mask: &SigSet,
+        frame: &TrapFrame,
+    ) -> Result<i32, SystemError> {
+        //TODO 引入线程后补上
+        // let current_thread = ProcessManager::current_pcb().thread;
+        let pcb = ProcessManager::current_pcb();
+        let mut archinfo_guard = pcb.arch_info();
+        self.oldmask = *mask;
+        self.frame = frame.clone();
+        // context.trap_num = unsafe { (*current_thread).trap_num };
+        // context.err_code = unsafe { (*current_thread).err_code };
+        // context.cr2 = unsafe { (*current_thread).cr2 };
+        self.reserved_for_x87_state = archinfo_guard.fp_state().clone();
+
+        // 保存完毕后,清空fp_state,以免下次save的时候,出现SIMD exception
+        archinfo_guard.clear_fp_state();
+        return Ok(0);
+    }
+
+    /// 指定的sigcontext恢复到当前进程的内核栈帧中,并将当前线程结构体的几个参数进行恢复
+    ///
+    /// ## 参数
+    /// - `frame` 目标栈帧(也就是把context恢复到这个栈帧中)
+    ///
+    /// ##返回值
+    /// - `true` -> 成功恢复
+    /// - `false` -> 执行失败
+    pub fn restore_sigcontext(&mut self, frame: &mut TrapFrame) -> bool {
+        let guard = ProcessManager::current_pcb();
+        let mut arch_info = guard.arch_info();
+        (*frame) = self.frame.clone();
+        // (*current_thread).trap_num = (*context).trap_num;
+        *arch_info.cr2_mut() = self.cr2 as usize;
+        // (*current_thread).err_code = (*context).err_code;
+        // 如果当前进程有fpstate,则将其恢复到pcb的fp_state中
+        *arch_info.fp_state_mut() = self.reserved_for_x87_state.clone();
+        arch_info.restore_fp_state();
+        return true;
+    }
+}
+/// @brief 信号处理备用栈的信息
+#[derive(Debug, Clone, Copy)]
+pub struct SigStack {
+    pub sp: *mut c_void,
+    pub flags: u32,
+    pub size: u32,
+    pub fpstate: FpState,
+}
+
+#[no_mangle]
+unsafe extern "C" fn do_signal(frame: &mut TrapFrame) {
+    X86_64SignalArch::do_signal(frame);
+}
+
+pub struct X86_64SignalArch;
+
+impl SignalArch for X86_64SignalArch {
+    unsafe fn do_signal(frame: &mut TrapFrame) {
+        // 检查sigpending是否为0
+        if ProcessManager::current_pcb()
+            .sig_info()
+            .sig_pending()
+            .signal()
+            .bits()
+            == 0
+            || !frame.from_user()
+        {
+            // 若没有正在等待处理的信号,或者将要返回到的是内核态,则启用中断,然后返回
+            CurrentIrqArch::interrupt_enable();
+            return;
+        }
+
+        // 做完上面的检查后,开中断
+        CurrentIrqArch::interrupt_enable();
+        let pcb = ProcessManager::current_pcb();
+        let sig_guard = pcb.sig_struct();
+        let mut sig_number: Signal;
+        let mut info: Option<SigInfo>;
+        let mut sigaction: Sigaction;
+        let reader = pcb.sig_info();
+        let sig_block: SigSet = reader.sig_block().clone();
+        drop(reader);
+        loop {
+            (sig_number, info) = pcb.sig_info_mut().dequeue_signal(&sig_block);
+            // 如果信号非法,则直接返回
+            if sig_number == Signal::INVALID {
+                return;
+            }
+
+            sigaction = sig_guard.handlers[sig_number as usize - 1];
+            match sigaction.action() {
+                SigactionType::SaHandler(action_type) => match action_type {
+                    SaHandlerType::SigError => {
+                        kerror!("Trying to handle a Sigerror on Process:{:?}", pcb.pid());
+                        return;
+                    }
+                    SaHandlerType::SigDefault => {
+                        sigaction = Sigaction::default();
+                        break;
+                    }
+                    SaHandlerType::SigIgnore => continue,
+                    SaHandlerType::SigCustomized(_) => {
+                        break;
+                    }
+                },
+                SigactionType::SaSigaction(_) => todo!(),
+            }
+            // 如果当前动作是忽略这个信号,就继续循环。
+        }
+        // 所有的信号都处理完了
+        let reader = pcb.sig_info();
+        let oldset = reader.sig_block().clone();
+        //避免死锁
+        drop(reader);
+        drop(sig_guard);
+        let res: Result<i32, SystemError> =
+            handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame);
+        if res.is_err() {
+            kerror!(
+                "Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
+                sig_number as i32,
+                ProcessManager::current_pcb().pid(),
+                res.unwrap_err()
+            );
+        }
+    }
+
+    fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64 {
+        let frame = (trap_frame.rsp as usize) as *mut SigFrame;
+
+        // 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击)
+        if UserBufferWriter::new(frame, size_of::<SigFrame>(), true).is_err() {
+            kerror!("rsp doesn't from user level");
+            let _r = Syscall::kill(ProcessManager::current_pcb().pid(), Signal::SIGSEGV as i32)
+                .map_err(|e| e.to_posix_errno());
+            return trap_frame.rax;
+        }
+        let mut sigmask: SigSet = unsafe { (*frame).context.oldmask };
+        set_current_sig_blocked(&mut sigmask);
+        // 从用户栈恢复sigcontext
+        if !unsafe { &mut (*frame).context }.restore_sigcontext(trap_frame) {
+            kerror!("unable to restore sigcontext");
+            let _r = Syscall::kill(ProcessManager::current_pcb().pid(), Signal::SIGSEGV as i32)
+                .map_err(|e| e.to_posix_errno());
+            // 如果这里返回 err 值的话会丢失上一个系统调用的返回值
+        }
+        // 由于系统调用的返回值会被系统调用模块被存放在rax寄存器,因此,为了还原原来的那个系统调用的返回值,我们需要在这里返回恢复后的rax的值
+        return trap_frame.rax;
+    }
+}
+
+/// @brief 真正发送signal,执行自定义的处理函数
+///
+/// @param sig 信号number
+/// @param sigaction 信号响应动作
+/// @param info 信号信息
+/// @param oldset
+/// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝
+///
+/// @return Result<0,SystemError> 若Error, 则返回错误码,否则返回Ok(0)
+fn handle_signal(
+    sig: Signal,
+    sigaction: &mut Sigaction,
+    info: &SigInfo,
+    oldset: &SigSet,
+    frame: &mut TrapFrame,
+) -> Result<i32, SystemError> {
+    // TODO 这里要补充一段逻辑,好像是为了保证引入线程之后的地址空间不会出问题。详见https://opengrok.ringotek.cn/xref/linux-6.1.9/arch/mips/kernel/signal.c#830
+
+    // 设置栈帧
+    return setup_frame(sig, sigaction, info, oldset, frame);
+}
+
+/// @brief 在用户栈上开辟一块空间,并且把内核栈的栈帧以及需要在用户态执行的代码给保存进去。
+///
+/// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
+fn setup_frame(
+    sig: Signal,
+    sigaction: &mut Sigaction,
+    info: &SigInfo,
+    oldset: &SigSet,
+    trap_frame: &mut TrapFrame,
+) -> Result<i32, SystemError> {
+    let ret_code_ptr: *mut c_void;
+    let temp_handler: *mut c_void;
+    match sigaction.action() {
+        SigactionType::SaHandler(handler_type) => match handler_type {
+            SaHandlerType::SigDefault => {
+                sig.handle_default();
+                return Ok(0);
+            }
+            SaHandlerType::SigCustomized(handler) => {
+                // 如果handler位于内核空间
+                if handler >= MMArch::USER_END_VADDR {
+                    // 如果当前是SIGSEGV,则采用默认函数处理
+                    if sig == Signal::SIGSEGV {
+                        sig.handle_default();
+                        return Ok(0);
+                    } else {
+                        kerror!("attempting  to execute a signal handler from kernel");
+                        sig.handle_default();
+                        return Err(SystemError::EINVAL);
+                    }
+                } else {
+                    // 为了与Linux的兼容性,64位程序必须由用户自行指定restorer
+                    if sigaction.flags().contains(SigFlags::SA_RESTORER) {
+                        ret_code_ptr = sigaction.restorer().unwrap().data() as *mut c_void;
+                    } else {
+                        kerror!(
+                            "pid-{:?} forgot to set SA_FLAG_RESTORER for signal {:?}",
+                            ProcessManager::current_pcb().pid(),
+                            sig as i32
+                        );
+                        let r = Syscall::kill(
+                            ProcessManager::current_pcb().pid(),
+                            Signal::SIGSEGV as i32,
+                        );
+                        if r.is_err() {
+                            kerror!("In setup_sigcontext: generate SIGSEGV signal failed");
+                        }
+                        return Err(SystemError::EINVAL);
+                    }
+                    if sigaction.restorer().is_none() {
+                        kerror!(
+                            "restorer in process:{:?} is not defined",
+                            ProcessManager::current_pcb().pid()
+                        );
+                        return Err(SystemError::EINVAL);
+                    }
+                    temp_handler = handler.data() as *mut c_void;
+                }
+            }
+            SaHandlerType::SigIgnore => {
+                return Ok(0);
+            }
+            _ => {
+                return Err(SystemError::EINVAL);
+            }
+        },
+        SigactionType::SaSigaction(_) => {
+            //TODO 这里应该是可以恢复栈的,等后续来做
+            kerror!("trying to recover from sigaction type instead of handler");
+            return Err(SystemError::EINVAL);
+        }
+    }
+    let frame: *mut SigFrame = get_stack(&trap_frame, size_of::<SigFrame>());
+    // kdebug!("frame=0x{:016x}", frame as usize);
+    // 要求这个frame的地址位于用户空间,因此进行校验
+    let r = UserBufferWriter::new(frame, size_of::<SigFrame>(), true);
+    if r.is_err() {
+        // 如果地址区域位于内核空间,则直接报错
+        // todo: 生成一个sigsegv
+        let r = Syscall::kill(ProcessManager::current_pcb().pid(), Signal::SIGSEGV as i32);
+        if r.is_err() {
+            kerror!("In setup frame: generate SIGSEGV signal failed");
+        }
+        kerror!("In setup frame: access check failed");
+        return Err(SystemError::EFAULT);
+    }
+
+    // 将siginfo拷贝到用户栈
+    info.copy_siginfo_to_user(unsafe { &mut ((*frame).info) as *mut SigInfo })
+        .map_err(|e| -> SystemError {
+            let r = Syscall::kill(ProcessManager::current_pcb().pid(), Signal::SIGSEGV as i32);
+            if r.is_err() {
+                kerror!("In copy_siginfo_to_user: generate SIGSEGV signal failed");
+            }
+            return e;
+        })?;
+
+    // todo: 拷贝处理程序备用栈的地址、大小、ss_flags
+
+    unsafe {
+        (*frame)
+            .context
+            .setup_sigcontext(oldset, &trap_frame)
+            .map_err(|e: SystemError| -> SystemError {
+                let r = Syscall::kill(ProcessManager::current_pcb().pid(), Signal::SIGSEGV as i32);
+                if r.is_err() {
+                    kerror!("In setup_sigcontext: generate SIGSEGV signal failed");
+                }
+                return e;
+            })?
+    };
+
+    unsafe {
+        // 在开头检验过sigaction.restorer是否为空了,实际上libc会保证 restorer始终不为空
+        (*frame).ret_code_ptr = ret_code_ptr;
+    }
+
+    unsafe { (*frame).handler = temp_handler };
+    // 传入信号处理函数的第一个参数
+    trap_frame.rdi = sig as u64;
+    trap_frame.rsi = unsafe { &(*frame).info as *const SigInfo as u64 };
+    trap_frame.rsp = frame as u64;
+    trap_frame.rip = unsafe { (*frame).handler as u64 };
+    // 设置cs和ds寄存器
+    trap_frame.cs = (USER_CS.bits() | 0x3) as u64;
+    trap_frame.ds = (USER_DS.bits() | 0x3) as u64;
+
+    // 禁用中断
+    // trap_frame.rflags &= !(0x200);
+
+    return Ok(0);
+}
+
+#[inline(always)]
+fn get_stack(frame: &TrapFrame, size: usize) -> *mut SigFrame {
+    // TODO:在 linux 中会根据 Sigaction 中的一个flag 的值来确定是否使用pcb中的 signal 处理程序备用堆栈,现在的
+    // pcb中也没有这个备用堆栈
+
+    // 默认使用 用户栈的栈顶指针-128字节的红区-sigframe的大小 并且16字节对齐
+    let mut rsp: usize = (frame.rsp as usize) - 128 - size;
+    // 按照要求进行对齐,别问为什么减8,不减8就是错的,可以看
+    // https://sourcegraph.com/github.com/torvalds/linux@dd72f9c7e512da377074d47d990564959b772643/-/blob/arch/x86/kernel/signal.c?L124
+    // 我猜测是跟x86汇编的某些弹栈行为有关系,它可能会出于某种原因递增 rsp
+    rsp &= (!(STACK_ALIGN - 1)) as usize - 8;
+    // rsp &= (!(STACK_ALIGN - 1)) as usize;
+    return rsp as *mut SigFrame;
+}
+
+/// 信号默认处理函数——终止进程
+fn sig_terminate(sig: Signal) {
+    ProcessManager::exit(sig as usize);
+}
+
+/// 信号默认处理函数——终止进程并生成 core dump
+fn sig_terminate_dump(sig: Signal) {
+    ProcessManager::exit(sig as usize);
+    // TODO 生成 coredump 文件
+}
+
+/// 信号默认处理函数——暂停进程
+fn sig_stop(sig: Signal) {
+    let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+    ProcessManager::mark_stop().unwrap_or_else(|e| {
+        kerror!(
+            "sleep error :{:?},failed to sleep process :{:?}, with signal :{:?}",
+            e,
+            ProcessManager::current_pcb(),
+            sig
+        );
+    });
+    drop(guard);
+    sched();
+    // TODO 暂停进程
+}
+/// 信号默认处理函数——继续进程
+fn sig_continue(sig: Signal) {
+    ProcessManager::wakeup_stop(&ProcessManager::current_pcb()).unwrap_or_else(|_| {
+        kerror!(
+            "Failed to wake up process pid = {:?} with signal :{:?}",
+            ProcessManager::current_pcb().pid(),
+            sig
+        );
+    });
+}
+/// 信号默认处理函数——忽略
+fn sig_ignore(_sig: Signal) {
+    return;
+}

+ 1 - 0
kernel/src/arch/x86_64/mod.rs

@@ -25,3 +25,4 @@ pub use self::mm::X86_64MMArch as MMArch;
 pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
 
 pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch;
+pub use crate::arch::ipc::signal::X86_64SignalArch as CurrentSignalArch;

+ 23 - 0
kernel/src/arch/x86_64/process/mod.rs

@@ -13,6 +13,7 @@ use x86::{controlregs::Cr4, segmentation::SegmentSelector};
 use crate::{
     arch::process::table::TSSManager,
     exception::InterruptArch,
+    kwarn,
     libs::spinlock::SpinLockGuard,
     mm::{
         percpu::{PerCpu, PerCpuVar},
@@ -156,6 +157,20 @@ impl ArchPCBInfo {
         self.fp_state.as_mut().unwrap().restore();
     }
 
+    /// 返回浮点寄存器结构体的副本
+    pub fn fp_state(&self) -> &Option<FpState> {
+        &self.fp_state
+    }
+
+    // 清空浮点寄存器
+    pub fn clear_fp_state(&mut self) {
+        if unlikely(self.fp_state.is_none()) {
+            kwarn!("fp_state is none");
+            return;
+        }
+
+        self.fp_state.as_mut().unwrap().clear();
+    }
     pub unsafe fn save_fsbase(&mut self) {
         if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
             self.fsbase = x86::current::segmentation::rdfsbase() as usize;
@@ -191,6 +206,14 @@ impl ArchPCBInfo {
     pub fn gsbase(&self) -> usize {
         self.gsbase
     }
+
+    pub fn cr2_mut(&mut self) -> &mut usize {
+        &mut self.cr2
+    }
+
+    pub fn fp_state_mut(&mut self) -> &mut Option<FpState> {
+        &mut self.fp_state
+    }
 }
 
 impl ProcessControlBlock {

+ 3 - 1
kernel/src/arch/x86_64/syscall.rs

@@ -3,7 +3,9 @@ use core::ffi::c_void;
 use alloc::string::String;
 
 use crate::{
+    arch::ipc::signal::X86_64SignalArch,
     include::bindings::bindings::set_system_trap_gate,
+    ipc::signal_types::SignalArch,
     syscall::{Syscall, SystemError, SYS_RT_SIGRETURN},
 };
 
@@ -39,7 +41,7 @@ pub extern "C" fn syscall_handler(frame: &mut TrapFrame) -> () {
     // 由于进程管理未完成重构,有些系统调用需要在这里临时处理,以后这里的特殊处理要删掉。
     match syscall_num {
         SYS_RT_SIGRETURN => {
-            syscall_return!(SystemError::ENOSYS.to_posix_errno() as usize, frame);
+            syscall_return!(X86_64SignalArch::sys_rt_sigreturn(frame) as usize, frame);
         }
         _ => {}
     }

+ 20 - 6
kernel/src/debug/kallsyms.c

@@ -51,8 +51,9 @@ int read_symbol(FILE *filp, struct kernel_symbol_entry_t *entry)
 {
     // 本函数假设nm命令输出的结果中,每行最大512字节
     char str[512] = {0};
-    char* s = fgets(str, sizeof(str), filp);
-    if (s != str) {
+    char *s = fgets(str, sizeof(str), filp);
+    if (s != str)
+    {
         return -1;
     }
 
@@ -60,15 +61,29 @@ int read_symbol(FILE *filp, struct kernel_symbol_entry_t *entry)
     int retval = sscanf(str, "%llx %c %512c", &entry->vaddr, &entry->type, symbol_name);
 
     // 如果当前行不符合要求
-    if (retval != 3) {
+    if (retval != 3)
+    {
         return -1;
     }
     // malloc一块内存,然后把str的内容拷贝进去,接着修改symbol指针
     size_t len = strlen(symbol_name);
-    if (len >= 1 && symbol_name[len - 1] == '\n') {
+    if (len >= 1 && symbol_name[len - 1] == '\n')
+    {
         symbol_name[len - 1] = '\0';
         len--;
     }
+    // 转义双引号
+    for (int i = 0; i < len; i++)
+    {
+        if (symbol_name[i] == '"')
+        {
+            char temp[len - i];
+            memcpy(temp, symbol_name + i, len - i);
+            symbol_name[i] = '\\';
+            memcpy(symbol_name + i + 1, temp, len - i);
+            i++;
+        }
+    }
     entry->symbol = strdup(symbol_name);
     entry->symbol_length = len + 1; // +1的原因是.asciz指令会在字符串末尾自动添加结束符\0
     return 0;
@@ -191,12 +206,11 @@ void generate_result()
 
         // 输出符号名称
         printf("\t.asciz\t\"%s\"\n", symbol_table[i].symbol);
-        
+
         last_vaddr = symbol_table[i].vaddr;
     }
 
     putchar('\n');
-    
 }
 int main(int argc, char **argv)
 {

+ 18 - 3
kernel/src/driver/tty/mod.rs

@@ -58,7 +58,8 @@ struct TtyCore {
     /// 输出的mpsc队列输入输出端
     output_rx: mpsc::Receiver<u8>,
     output_tx: mpsc::Sender<u8>,
-
+    // 前台进程,以后改成前台进程组
+    // front_job: Option<Pid>,
     /// tty核心的状态
     state: RwLock<TtyCoreState>,
 }
@@ -74,6 +75,8 @@ pub enum TtyError {
     Closed,
     /// End of file(已经读取的字符数,包含eof)
     EOF(usize),
+    /// 接收到信号终止
+    Stopped(usize),
     Unknown(String),
 }
 
@@ -106,7 +109,6 @@ impl TtyCore {
     /// @return Ok(成功传送的字节数)
     /// @return Err(TtyError) 内部错误信息
     pub fn input(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
-        // TODO: 在这里考虑增加对信号发送的处理
         let val = self.write_stdin(buf, block)?;
         // 如果开启了输入回显,那么就写一份到输出缓冲区
         if self.echo_enabled() {
@@ -281,11 +283,24 @@ impl TtyCore {
                     _ => return Err(TtyError::Unknown(format!("{e:?}"))),
                 }
             } else {
+                // TODO: 在这里考虑增加对信号发送的处理
+                // if buf[cnt] == 3 {
+                //     let pid = ProcessManager::current_pcb().pid();
+                //     Signal::SIGKILL.send_signal_info(
+                //         Some(&mut SigInfo::new(
+                //             Signal::SIGKILL,
+                //             0,
+                //             SigCode::SI_USER,
+                //             SigType::Kill(pid),
+                //         )),
+                //         pid,
+                //     );
+                //     return Err(TtyError::Stopped(cnt));
+                // }
                 *r.unwrap() = buf[cnt];
                 cnt += 1;
             }
         }
-
         return Ok(cnt);
     }
 

+ 0 - 144
kernel/src/include/DragonOS/signal.h

@@ -1,144 +0,0 @@
-/**
- * @file signal.h
- * @author longjin ([email protected])
- * @brief signal相关类型在C语言中的导出。(以rust版本为准)
- * @version 0.1
- *
- * @copyright Copyright (c) 2022
- *
- */
-#pragma once
-#include <DragonOS/refcount.h>
-#include <common/atomic.h>
-#include <common/list.h>
-#include <common/spinlock.h>
-#include <common/sys/types.h>
-
-// 系统最大支持的信号数量
-#define MAX_SIG_NUM 64
-// sigset所占用的u64的数量
-#define _NSIG_U64_CNT (MAX_SIG_NUM / 64)
-
-typedef void __signalfn_t(int);
-typedef __signalfn_t *__sighandler_t;
-
-typedef uint64_t sigset_t;
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-#define SIGBUS 7
-#define SIGFPE 8
-#define SIGKILL 9
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGSTKFLT 16
-#define SIGCHLD 17
-#define SIGCONT 18
-#define SIGSTOP 19
-#define SIGTSTP 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGURG 23
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGIO 29
-#define SIGPOLL SIGIO
-
-#define SIGPWR 30
-#define SIGSYS 31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN 32
-#define SIGRTMAX MAX_SIG_NUM
-
-// 注意,该结构体最大16字节
-union __sifields {
-    /* kill() */
-    struct
-    {
-        pid_t _pid; /* 信号发送者的pid */
-    } _kill;
-};
-
-// 注意,该结构体最大大小为32字节
-#define __SIGINFO                                                                                                      \
-    struct                                                                                                             \
-    {                                                                                                                  \
-        int32_t si_signo; /* signal number */                                                                          \
-        int32_t si_code;                                                                                               \
-        int32_t si_errno;                                                                                              \
-        uint32_t reserved; /* 保留备用 */                                                                          \
-        union __sifields _sifields;                                                                                    \
-    }
-
-struct siginfo
-{
-    union {
-        __SIGINFO;
-        uint64_t padding[4]; // 让siginfo占用32字节大小
-    };
-};
-
-/**
- * @brief 信号处理结构体
- *
- */
-struct sigaction
-{
-    // 信号处理函数的指针
-    union {
-        __sighandler_t _sa_handler;
-        void (*_sa_sigaction)(int sig, struct siginfo *sinfo, void *);
-    } _u;
-    uint64_t sa_flags;
-    sigset_t sa_mask;
-    void (*sa_restorer)(void); // 暂时未实现
-};
-
-// ============ sigaction结构体中的的sa_flags的可选值 ===========
-#define SA_FLAG_IGN (1UL << 0)      // 当前sigaction表示忽略信号的动作
-#define SA_FLAG_DFL (1UL << 1)      // 当前sigaction表示系统默认的动作
-#define SA_FLAG_RESTORER (1UL << 2) // 当前sigaction具有用户指定的restorer
-#define SA_FLAG_IMMUTABLE (1UL << 3) // 当前sigaction不可被更改
-
-/**
- * 由于signal_struct总是和sighand_struct一起使用,并且信号处理的过程中必定会对sighand加锁,
- * 因此signal_struct不用加锁
- */
-struct signal_struct
-{
-    atomic_t sig_cnt;
-};
-
-/**
- * @brief 信号处理结构体,位于pcb之中。
- * 请注意,该结构体需要与rust的版本一致,且以rust的为准
- */
-struct sighand_struct
-{
-    spinlock_t siglock;
-    refcount_t count;
-    // 为每个信号注册的处理函数的结构体
-    struct sigaction action[MAX_SIG_NUM];
-};
-
-/**
- * @brief 正在等待的信号的标志位
- */
-struct sigpending
-{
-    sigset_t signal;
-    void *sigqueue; // 信号队列(在rust中实现)
-};

+ 0 - 1
kernel/src/include/bindings/wrapper.h

@@ -30,7 +30,6 @@
 #include <driver/multiboot2/multiboot2.h>
 #include <exception/gate.h>
 #include <include/DragonOS/refcount.h>
-#include <include/DragonOS/signal.h>
 #include <libs/lib_ui/textui.h>
 #include <mm/mm-types.h>
 #include <mm/mm.h>

+ 2 - 0
kernel/src/ipc/mod.rs

@@ -1,2 +1,4 @@
 pub mod pipe;
+pub mod signal;
+pub mod signal_types;
 pub mod syscall;

+ 416 - 0
kernel/src/ipc/signal.rs

@@ -0,0 +1,416 @@
+use core::sync::atomic::compiler_fence;
+
+use alloc::sync::Arc;
+
+use crate::{
+    arch::ipc::signal::{SigCode, SigFlags, SigSet, Signal},
+    ipc::signal_types::SigactionType,
+    kwarn,
+    libs::spinlock::SpinLockGuard,
+    process::{pid::PidType, Pid, ProcessControlBlock, ProcessFlags, ProcessManager},
+    syscall::SystemError,
+};
+
+use super::signal_types::{
+    SaHandlerType, SigInfo, SigType, Sigaction, SignalStruct, SIG_KERNEL_STOP_MASK,
+};
+
+impl Signal {
+    /// 向目标进程发送信号
+    ///
+    /// ## 参数
+    ///
+    /// - `sig` 要发送的信号
+    /// - `info` 要发送的信息
+    /// -  `pid` 进程id(目前只支持pid>0)
+    pub fn send_signal_info(
+        &self,
+        info: Option<&mut SigInfo>,
+        pid: Pid,
+    ) -> Result<i32, SystemError> {
+        // TODO:暂时不支持特殊的信号操作,待引入进程组后补充
+        // 如果 pid 大于 0,那么会发送信号给 pid 指定的进程
+        // 如果 pid 等于 0,那么会发送信号给与调用进程同组的每个进程,包括调用进程自身
+        // 如果 pid 小于 -1,那么会向组 ID 等于该 pid 绝对值的进程组内所有下属进程发送信号。向一个进程组的所有进程发送信号在 shell 作业控制中有特殊有途
+        // 如果 pid 等于 -1,那么信号的发送范围是:调用进程有权将信号发往的每个目标进程,除去 init(进程 ID 为 1)和调用进程自身。如果特权级进程发起这一调用,那么会发送信号给系统中的所有进程,上述两个进程除外。显而易见,有时也将这种信号发送方式称之为广播信号
+        // 如果并无进程与指定的 pid 相匹配,那么 kill() 调用失败,同时将 errno 置为 ESRCH(“查无此进程”)
+        if pid.lt(&Pid::from(0)) {
+            kwarn!("Kill operation not support: pid={:?}", pid);
+            return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+        }
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        // 检查sig是否符合要求,如果不符合要求,则退出。
+        if !self.is_valid() {
+            return Err(SystemError::EINVAL);
+        }
+        let mut retval = Err(SystemError::ESRCH);
+        let pcb = ProcessManager::find(pid);
+
+        if pcb.is_none() {
+            kwarn!("No such process.");
+            return retval;
+        }
+        // println!("Target pcb = {:?}", pcb.as_ref().unwrap());
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        // 发送信号
+        retval = self.send_signal(info, pcb.unwrap(), PidType::PID);
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        return retval;
+    }
+
+    /// @brief 判断是否需要强制发送信号,然后发送信号
+    /// 进入函数后加锁
+    ///
+    /// @return SystemError 错误码
+    fn send_signal(
+        &self,
+        info: Option<&mut SigInfo>,
+        pcb: Arc<ProcessControlBlock>,
+        pt: PidType,
+    ) -> Result<i32, SystemError> {
+        // 是否强制发送信号
+        let mut force_send = false;
+        // signal的信息为空
+
+        if let Some(ref siginfo) = info {
+            force_send = matches!(siginfo.sig_code(), SigCode::Kernel);
+        } else {
+            // todo: 判断signal是否来自于一个祖先进程的namespace,如果是,则强制发送信号
+            //详见 https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/signal.c?r=&mo=32170&fi=1220#1226
+        }
+
+        if !self.prepare_sianal(pcb.clone(), force_send) {
+            return Err(SystemError::EINVAL);
+        }
+        // kdebug!("force send={}", force_send);
+        let pcb_info = pcb.sig_info();
+        let pending = if matches!(pt, PidType::PID) {
+            pcb_info.sig_shared_pending()
+        } else {
+            pcb_info.sig_pending()
+        };
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        // 如果是kill或者目标pcb是内核线程,则无需获取sigqueue,直接发送信号即可
+        if matches!(self, Signal::SIGKILL) || pcb.flags().contains(ProcessFlags::KTHREAD) {
+            //避免死锁
+            drop(pcb_info);
+            self.complete_signal(pcb.clone(), pt);
+        }
+        // 如果不是实时信号的话,同一时刻信号队列里只会有一个待处理的信号,如果重复接收就不做处理
+        else if !self.is_rt_signal() && pending.queue().find(self.clone()).0.is_some() {
+            return Ok(0);
+        } else {
+            // TODO signalfd_notify 完善 signalfd 机制
+            // 如果是其他信号,则加入到sigqueue内,然后complete_signal
+            let new_sig_info = match info {
+                Some(siginfo) => {
+                    // 已经显式指定了siginfo,则直接使用它。
+                    (*siginfo).clone()
+                }
+                None => {
+                    // 不需要显示指定siginfo,因此设置为默认值
+                    SigInfo::new(
+                        self.clone(),
+                        0,
+                        SigCode::User,
+                        SigType::Kill(ProcessManager::current_pcb().pid()),
+                    )
+                }
+            };
+            drop(pcb_info);
+            pcb.sig_info_mut()
+                .sig_pending_mut()
+                .queue_mut()
+                .q
+                .push(new_sig_info);
+
+            if pt == PidType::PGID || pt == PidType::SID {}
+            self.complete_signal(pcb.clone(), pt);
+        }
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        return Ok(0);
+    }
+
+    /// @brief 将信号添加到目标进程的sig_pending。在引入进程组后,本函数还将负责把信号传递给整个进程组。
+    ///
+    /// @param sig 信号
+    /// @param pcb 目标pcb
+    /// @param pt siginfo结构体中,pid字段代表的含义
+    fn complete_signal(&self, pcb: Arc<ProcessControlBlock>, pt: PidType) {
+        // kdebug!("complete_signal");
+        // todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify)
+        // 将这个信号加到目标进程的sig_pending中
+        pcb.sig_info_mut()
+            .sig_pending_mut()
+            .signal_mut()
+            .insert(self.clone().into());
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        // ===== 寻找需要wakeup的目标进程 =====
+        // 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
+        //      todo: 当引入进程组的概念后,需要完善这里,使得它能寻找一个目标进程来唤醒,接着执行信号处理的操作。
+
+        // let _signal = pcb.sig_struct();
+
+        let mut _target: Option<Arc<ProcessControlBlock>> = None;
+
+        // 判断目标进程是否想接收这个信号
+        if self.wants_signal(pcb.clone()) {
+            _target = 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 {
+            /*
+             * Otherwise try to find a suitable thread.
+             * 由于目前每个进程只有1个线程,因此当前情况可以返回。信号队列的dequeue操作不需要考虑同步阻塞的问题。
+             */
+            return;
+        }
+
+        // TODO:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+        // TODO: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。
+        if _target.is_some() {
+            let guard = pcb.sig_struct();
+            signal_wake_up(pcb.clone(), guard, *self == Signal::SIGKILL);
+        }
+    }
+
+    /// @brief 本函数用于检测指定的进程是否想要接收SIG这个信号。
+    /// 当我们对于进程组中的所有进程都运行了这个检查之后,我们将可以找到组内愿意接收信号的进程。
+    /// 这么做是为了防止我们把信号发送给了一个正在或已经退出的进程,或者是不响应该信号的进程。
+    #[inline]
+    fn wants_signal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
+        // 如果改进程屏蔽了这个signal,则不能接收
+        if pcb.sig_info().sig_block().contains(self.clone().into()) {
+            return false;
+        }
+
+        // 如果进程正在退出,则不能接收信号
+        if pcb.flags().contains(ProcessFlags::EXITING) {
+            return false;
+        }
+
+        if *self == Signal::SIGKILL {
+            return true;
+        }
+
+        if pcb.sched_info().state().is_blocked() {
+            return false;
+        }
+
+        // todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项
+
+        // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
+        if pcb.sig_info().sig_pending().signal().bits() == 0 {
+            assert!(pcb.sig_info().sig_pending().queue().q.is_empty());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /// @brief 判断signal的处理是否可能使得整个进程组退出
+    /// @return true 可能会导致退出(不一定)
+    #[allow(dead_code)]
+    #[inline]
+    fn sig_fatal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
+        let action = pcb.sig_struct().handlers[self.clone() as usize - 1].action();
+        // 如果handler是空,采用默认函数,signal处理可能会导致进程退出。
+        match action {
+            SigactionType::SaHandler(handler) => handler.is_sig_default(),
+            SigactionType::SaSigaction(sigaction) => sigaction.is_none(),
+        }
+        // todo: 参照linux的sig_fatal实现完整功能
+    }
+
+    /// 检查信号是否能被发送,并且而且要处理 SIGCONT 和 STOP 信号
+    ///
+    /// ## 参数
+    ///
+    /// - `pcb` 要发送信号的目标pcb
+    ///
+    /// - `force` 是否强制发送(指走 fast path , 不加入 sigpending按顺序处理,直接进入 complete_signal)
+    ///
+    /// ## 返回值
+    ///
+    /// - `true` 能够发送信号
+    ///
+    /// - `false` 不能发送信号
+    fn prepare_sianal(&self, pcb: Arc<ProcessControlBlock>, _force: bool) -> bool {
+        let flush: SigSet;
+        if !(self.into_sigset() & SIG_KERNEL_STOP_MASK).is_empty() {
+            flush = Signal::SIGCONT.into_sigset();
+            pcb.sig_info_mut()
+                .sig_shared_pending_mut()
+                .flush_by_mask(&flush);
+            // TODO 对每个子线程 flush mask
+        } else if *self == Signal::SIGCONT {
+            flush = SIG_KERNEL_STOP_MASK;
+            assert!(!flush.is_empty());
+            pcb.sig_info_mut()
+                .sig_shared_pending_mut()
+                .flush_by_mask(&flush);
+            let _r = ProcessManager::wakeup_stop(&pcb);
+            // TODO 对每个子线程 flush mask
+            // 这里需要补充一段逻辑,详见https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/signal.c#952
+        }
+
+        // 一个被阻塞了的信号肯定是要被处理的
+        if pcb.sig_info().sig_block().contains(self.into_sigset()) {
+            return true;
+        }
+        return !pcb.sig_struct().handlers[self.clone() as usize - 1].is_ignore();
+
+        //TODO 仿照 linux 中的prepare signal完善逻辑,linux 中还会根据例如当前进程状态(Existing)进行判断,现在的信号能否发出就只是根据 ignored 来判断
+    }
+}
+
+/// 因收到信号而唤醒进程
+///
+/// ## 参数
+///
+/// - `pcb` 要唤醒的进程pcb
+/// - `_guard` 信号结构体锁守卫,来保证信号结构体已上锁
+/// - `fatal` 表明这个信号是不是致命的(会导致进程退出)
+#[inline]
+fn signal_wake_up(pcb: Arc<ProcessControlBlock>, _guard: SpinLockGuard<SignalStruct>, fatal: bool) {
+    // 如果是 fatal 的话就唤醒 stop 和 block 的进程来响应,因为唤醒后就会终止
+    // 如果不是 fatal 的就只唤醒 stop 的进程来响应
+    // kdebug!("signal_wake_up");
+    // 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核
+    let r = ProcessManager::wakeup_stop(&pcb);
+    if r.is_ok() {
+        ProcessManager::kick(&pcb);
+    } else {
+        if fatal {
+            let _r = ProcessManager::wakeup(&pcb).map(|_| {
+                ProcessManager::kick(&pcb);
+            });
+        }
+    }
+}
+
+/// @brief 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
+fn recalc_sigpending() {
+    // todo:
+}
+
+/// @brief 刷新指定进程的sighand的sigaction,将满足条件的sigaction恢复为Default
+///     除非某个信号被设置为ignore且force_default为false,否则都不会将其恢复
+///
+/// @param pcb 要被刷新的pcb
+/// @param force_default 是否强制将sigaction恢复成默认状态
+pub fn flush_signal_handlers(pcb: Arc<ProcessControlBlock>, force_default: bool) {
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+    // kdebug!("hand=0x{:018x}", hand as *const sighand_struct as usize);
+    let actions = &mut pcb.sig_struct().handlers;
+
+    for sigaction in actions.iter_mut() {
+        if force_default || !sigaction.is_ignore() {
+            sigaction.set_action(SigactionType::SaHandler(SaHandlerType::SigDefault));
+        }
+        // 清除flags中,除了DFL和IGN以外的所有标志
+        sigaction.set_restorer(None);
+        sigaction.mask_mut().remove(SigSet::all());
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+    }
+    compiler_fence(core::sync::atomic::Ordering::SeqCst);
+}
+
+pub(super) fn do_sigaction(
+    sig: Signal,
+    act: Option<&mut Sigaction>,
+    old_act: Option<&mut Sigaction>,
+) -> Result<(), SystemError> {
+    if sig == Signal::INVALID {
+        return Err(SystemError::EINVAL);
+    }
+    let pcb = ProcessManager::current_pcb();
+    // 指向当前信号的action的引用
+    let action: &mut Sigaction = &mut pcb.sig_struct().handlers[sig as usize - 1];
+
+    // 对比 MUSL 和 relibc , 暂时不设置这个标志位
+    // if action.flags().contains(SigFlags::SA_FLAG_IMMUTABLE) {
+    //     return Err(SystemError::EINVAL);
+    // }
+
+    // 保存原有的 sigaction
+    let old_act: Option<&mut Sigaction> = {
+        if old_act.is_some() {
+            let oa = old_act.unwrap();
+            *(oa) = (*action).clone();
+            Some(oa)
+        } else {
+            None
+        }
+    };
+    // 清除所有的脏的sa_flags位(也就是清除那些未使用的)
+    let act = {
+        if act.is_some() {
+            let ac = act.unwrap();
+            *ac.flags_mut() &= SigFlags::SA_ALL;
+            Some(ac)
+        } else {
+            None
+        }
+    };
+
+    if old_act.is_some() {
+        *old_act.unwrap().flags_mut() &= SigFlags::SA_ALL;
+    }
+
+    if act.is_some() {
+        let ac = act.unwrap();
+        // 将act.sa_mask的SIGKILL SIGSTOP的屏蔽清除
+        ac.mask_mut()
+            .remove(SigSet::from(Signal::SIGKILL.into()) | SigSet::from(Signal::SIGSTOP.into()));
+
+        // 将新的sigaction拷贝到进程的action中
+        *action = *ac;
+        /*
+        * 根据POSIX 3.3.1.3规定:
+        * 1.不管一个信号是否被阻塞,只要将其设置SIG_IGN,如果当前已经存在了正在pending的信号,那么就把这个信号忽略。
+        *
+        * 2.不管一个信号是否被阻塞,只要将其设置SIG_DFL,如果当前已经存在了正在pending的信号,
+              并且对这个信号的默认处理方式是忽略它,那么就会把pending的信号忽略。
+        */
+        if action.is_ignore() {
+            let mut mask: SigSet = SigSet::from_bits_truncate(0);
+            mask.insert(sig.into());
+            pcb.sig_info_mut().sig_pending_mut().flush_by_mask(&mask);
+            // todo: 当有了多个线程后,在这里进行操作,把每个线程的sigqueue都进行刷新
+        }
+    }
+    return Ok(());
+}
+
+/// 设置当前进程的屏蔽信号 (sig_block),待引入 [sigprocmask](https://man7.org/linux/man-pages/man2/sigprocmask.2.html) 系统调用后要删除这个散装函数
+///
+/// ## 参数
+///
+/// - `new_set` 新的屏蔽信号bitmap的值
+pub fn set_current_sig_blocked(new_set: &mut SigSet) {
+    new_set.remove(SigSet::from(Signal::SIGKILL.into()) | SigSet::from(Signal::SIGSTOP.into()));
+    //TODO 把这个散装函数用 sigsetops 替换掉
+    let pcb = ProcessManager::current_pcb();
+
+    /*
+        如果当前pcb的sig_blocked和新的相等,那么就不用改变它。
+        请注意,一个进程的sig_blocked字段不能被其他进程修改!
+    */
+    if pcb.sig_info().sig_block().eq(new_set) {
+        return;
+    }
+
+    let guard = pcb.sig_struct_irq();
+    // todo: 当一个进程有多个线程后,在这里需要设置每个线程的block字段,并且 retarget_shared_pending(虽然我还没搞明白linux这部分是干啥的)
+
+    // 设置当前进程的sig blocked
+    *pcb.sig_info_mut().sig_block_mut() = *new_set;
+    recalc_sigpending();
+    drop(guard);
+}

+ 529 - 0
kernel/src/ipc/signal_types.rs

@@ -0,0 +1,529 @@
+use core::{ffi::c_void, mem::size_of, sync::atomic::AtomicI64};
+
+use alloc::vec::Vec;
+
+use crate::{
+    arch::{
+        asm::bitops::ffz,
+        interrupt::TrapFrame,
+        ipc::signal::{SigCode, SigFlags, SigSet, Signal, MAX_SIG_NUM},
+    },
+    mm::VirtAddr,
+    process::Pid,
+    syscall::{user_access::UserBufferWriter, SystemError},
+};
+
+/// 用户态程序传入的SIG_DFL的值
+pub const USER_SIG_DFL: u64 = 0;
+/// 用户态程序传入的SIG_IGN的值
+pub const USER_SIG_IGN: u64 = 1;
+/// 用户态程序传入的SIG_ERR的值
+pub const USER_SIG_ERR: u64 = 2;
+
+// 因为 Rust 编译器不能在常量声明中正确识别级联的 "|" 运算符(experimental feature: https://github.com/rust-lang/rust/issues/67792),因此
+// 暂时只能通过这种方法来声明这些常量,这些常量暂时没有全部用到,但是都出现在 linux 的判断逻辑中,所以都保留下来了
+#[allow(dead_code)]
+pub const SIG_KERNEL_ONLY_MASK: SigSet =
+    Signal::into_sigset(Signal::SIGSTOP).union(Signal::into_sigset(Signal::SIGKILL));
+
+pub const SIG_KERNEL_STOP_MASK: SigSet = Signal::into_sigset(Signal::SIGSTOP)
+    .union(Signal::into_sigset(Signal::SIGTSTP))
+    .union(Signal::into_sigset(Signal::SIGTTIN))
+    .union(Signal::into_sigset(Signal::SIGTTOU));
+#[allow(dead_code)]
+pub const SIG_KERNEL_COREDUMP_MASK: SigSet = Signal::into_sigset(Signal::SIGQUIT)
+    .union(Signal::into_sigset(Signal::SIGILL))
+    .union(Signal::into_sigset(Signal::SIGTRAP))
+    .union(Signal::into_sigset(Signal::SIGABRT_OR_IOT))
+    .union(Signal::into_sigset(Signal::SIGFPE))
+    .union(Signal::into_sigset(Signal::SIGSEGV))
+    .union(Signal::into_sigset(Signal::SIGBUS))
+    .union(Signal::into_sigset(Signal::SIGSYS))
+    .union(Signal::into_sigset(Signal::SIGXCPU))
+    .union(Signal::into_sigset(Signal::SIGXFSZ));
+#[allow(dead_code)]
+pub const SIG_KERNEL_IGNORE_MASK: SigSet = Signal::into_sigset(Signal::SIGCONT)
+    .union(Signal::into_sigset(Signal::SIGFPE))
+    .union(Signal::into_sigset(Signal::SIGSEGV))
+    .union(Signal::into_sigset(Signal::SIGBUS))
+    .union(Signal::into_sigset(Signal::SIGTRAP))
+    .union(Signal::into_sigset(Signal::SIGCHLD))
+    .union(Signal::into_sigset(Signal::SIGIO_OR_POLL))
+    .union(Signal::into_sigset(Signal::SIGSYS));
+
+/// SignalStruct 在 pcb 中加锁
+#[derive(Debug)]
+pub struct SignalStruct {
+    pub cnt: AtomicI64,
+    /// 如果对应linux,这部分会有一个引用计数,但是没发现在哪里有用到需要计算引用的地方,因此
+    /// 暂时删掉,不然这个Arc会导致其他地方的代码十分丑陋
+    pub handlers: [Sigaction; MAX_SIG_NUM as usize],
+}
+
+impl Default for SignalStruct {
+    fn default() -> Self {
+        Self {
+            cnt: Default::default(),
+            handlers: [Sigaction::default(); MAX_SIG_NUM as usize],
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+#[allow(dead_code)]
+pub enum SigactionType {
+    SaHandler(SaHandlerType),
+    SaSigaction(
+        Option<
+            unsafe extern "C" fn(
+                sig: ::core::ffi::c_int,
+                sinfo: *mut SigInfo,
+                arg1: *mut ::core::ffi::c_void,
+            ),
+        >,
+    ), // 暂时没有用上
+}
+
+impl SigactionType {
+    /// Returns `true` if the sa handler type is [`SaHandler(SaHandlerType::SigIgnore)`].
+    ///
+    /// [`SigIgnore`]: SaHandlerType::SigIgnore
+    pub fn is_ignore(&self) -> bool {
+        return matches!(self, Self::SaHandler(SaHandlerType::SigIgnore));
+    }
+    /// Returns `true` if the sa handler type is [`SaHandler(SaHandlerType::SigCustomized(_))`].
+    ///
+    /// [`SigCustomized`]: SaHandlerType::SigCustomized(_)
+    pub fn is_customized(&self) -> bool {
+        return matches!(self, Self::SaHandler(SaHandlerType::SigCustomized(_)));
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+#[allow(dead_code)]
+pub enum SaHandlerType {
+    SigError, // 暂时没有用上
+    SigDefault,
+    SigIgnore,
+    SigCustomized(VirtAddr),
+}
+
+impl Into<usize> for SaHandlerType {
+    fn into(self) -> usize {
+        match self {
+            Self::SigError => 2 as usize,
+            Self::SigIgnore => 1 as usize,
+            Self::SigDefault => 0 as usize,
+            Self::SigCustomized(handler) => handler.data(),
+        }
+    }
+}
+
+impl SaHandlerType {
+    /// Returns `true` if the sa handler type is [`SigDefault`].
+    ///
+    /// [`SigDefault`]: SaHandlerType::SigDefault
+    pub fn is_sig_default(&self) -> bool {
+        matches!(self, Self::SigDefault)
+    }
+
+    /// Returns `true` if the sa handler type is [`SigIgnore`].
+    ///
+    /// [`SigIgnore`]: SaHandlerType::SigIgnore
+    pub fn is_sig_ignore(&self) -> bool {
+        matches!(self, Self::SigIgnore)
+    }
+
+    /// Returns `true` if the sa handler type is [`SigError`].
+    ///
+    /// [`SigError`]: SaHandlerType::SigError
+    pub fn is_sig_error(&self) -> bool {
+        matches!(self, Self::SigError)
+    }
+}
+
+/// 信号处理结构体
+///
+#[derive(Debug, Copy, Clone)]
+pub struct Sigaction {
+    action: SigactionType,
+    flags: SigFlags,
+    mask: SigSet, // 为了可扩展性而设置的sa_mask
+    /// 信号处理函数执行结束后,将会跳转到这个函数内进行执行,然后执行sigreturn系统调用
+    restorer: Option<VirtAddr>,
+}
+
+impl Default for Sigaction {
+    fn default() -> Self {
+        Self {
+            action: SigactionType::SaHandler(SaHandlerType::SigDefault),
+            flags: Default::default(),
+            mask: Default::default(),
+            restorer: Default::default(),
+        }
+    }
+}
+
+impl Sigaction {
+    /// 判断传入的信号是否被忽略
+    ///
+    /// ## 参数
+    ///
+    /// - `sig` 传入的信号
+    ///
+    /// ## 返回值
+    ///
+    /// - `true` 被忽略
+    /// - `false`未被忽略
+    pub fn is_ignore(&self) -> bool {
+        return self.action.is_ignore();
+    }
+    pub fn new(
+        action: SigactionType,
+        flags: SigFlags,
+        mask: SigSet,
+        restorer: Option<VirtAddr>,
+    ) -> Self {
+        Self {
+            action,
+            flags,
+            mask,
+            restorer,
+        }
+    }
+
+    pub fn action(&self) -> SigactionType {
+        self.action
+    }
+
+    pub fn flags(&self) -> SigFlags {
+        self.flags
+    }
+
+    pub fn restorer(&self) -> Option<VirtAddr> {
+        self.restorer
+    }
+
+    pub fn flags_mut(&mut self) -> &mut SigFlags {
+        &mut self.flags
+    }
+
+    pub fn set_action(&mut self, action: SigactionType) {
+        self.action = action;
+    }
+
+    pub fn mask(&self) -> SigSet {
+        self.mask
+    }
+
+    pub fn mask_mut(&mut self) -> &mut SigSet {
+        &mut self.mask
+    }
+
+    pub fn set_restorer(&mut self, restorer: Option<VirtAddr>) {
+        self.restorer = restorer;
+    }
+
+    /// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
+    pub const DEFAULT_SIGACTION: Sigaction = Sigaction {
+        action: SigactionType::SaHandler(SaHandlerType::SigDefault),
+        flags: SigFlags::empty(),
+        mask: SigSet::from_bits_truncate(0),
+        restorer: None,
+    };
+
+    /// 默认的“忽略信号”的sigaction
+    pub const DEFAULT_SIGACTION_IGNORE: Sigaction = Sigaction {
+        action: SigactionType::SaHandler(SaHandlerType::SigIgnore),
+        flags: SigFlags::empty(),
+        mask: SigSet::from_bits_truncate(0),
+        restorer: None,
+    };
+}
+
+/// 用户态传入的sigaction结构体(符合posix规范)
+/// 请注意,我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct UserSigaction {
+    pub handler: *mut core::ffi::c_void,
+    pub flags: SigFlags,
+    pub restorer: *mut core::ffi::c_void,
+    pub mask: SigSet,
+}
+
+/**
+ * siginfo中,根据signal的来源不同,该info中对应了不同的数据./=
+ * 请注意,该info最大占用16字节
+ */
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct SigInfo {
+    sig_no: i32,
+    sig_code: SigCode,
+    errno: i32,
+    sig_type: SigType,
+}
+
+impl SigInfo {
+    pub fn sig_code(&self) -> SigCode {
+        self.sig_code
+    }
+
+    pub fn set_sig_type(&mut self, sig_type: SigType) {
+        self.sig_type = sig_type;
+    }
+    /// @brief 将siginfo结构体拷贝到用户栈
+    /// ## 参数
+    ///
+    /// `to` 用户空间指针
+    ///
+    /// ## 注意
+    ///
+    /// 该函数对应Linux中的https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/signal.c#3323
+    /// Linux还提供了 https://opengrok.ringotek.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> {
+        // 验证目标地址是否为用户空间
+        let mut user_buffer = UserBufferWriter::new(to, size_of::<SigInfo>(), true)?;
+
+        let retval: Result<i32, SystemError> = Ok(0);
+
+        user_buffer.copy_one_to_user(self, 0)?;
+        return retval;
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum SigType {
+    Kill(Pid),
+    // 后续完善下列中的具体字段
+    // Timer,
+    // Rt,
+    // SigChild,
+    // SigFault,
+    // SigPoll,
+    // SigSys,
+}
+
+impl SigInfo {
+    pub fn new(sig: Signal, sig_errno: i32, sig_code: SigCode, sig_type: SigType) -> Self {
+        Self {
+            sig_no: sig as i32,
+            sig_code,
+            errno: sig_errno,
+            sig_type,
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct SigPending {
+    signal: SigSet,
+    queue: SigQueue,
+}
+
+impl Default for SigPending {
+    fn default() -> Self {
+        SigPending {
+            signal: SigSet::default(),
+            queue: SigQueue::default(),
+        }
+    }
+}
+
+impl SigPending {
+    pub fn signal(&self) -> SigSet {
+        self.signal
+    }
+
+    pub fn queue(&self) -> &SigQueue {
+        &self.queue
+    }
+
+    pub fn queue_mut(&mut self) -> &mut SigQueue {
+        &mut self.queue
+    }
+
+    pub fn signal_mut(&mut self) -> &mut SigSet {
+        &mut self.signal
+    }
+    /// @brief 获取下一个要处理的信号(sig number越小的信号,优先级越高)
+    ///
+    /// @param pending 等待处理的信号
+    /// @param sig_mask 屏蔽了的信号
+    /// @return i32 下一个要处理的信号的number. 如果为0,则无效
+    pub fn next_signal(&self, sig_mask: &SigSet) -> Signal {
+        let mut sig = Signal::INVALID;
+
+        let s = self.signal();
+        let m = *sig_mask;
+        m.is_empty();
+        // 获取第一个待处理的信号的号码
+        let x = s & (!m);
+        if x.bits() != 0 {
+            sig = Signal::from(ffz(x.complement().bits()) + 1);
+            return sig;
+        }
+
+        // 暂时只支持64种信号
+        assert_eq!(MAX_SIG_NUM, 64);
+
+        return sig;
+    }
+    /// @brief 收集信号的信息
+    ///
+    /// @param sig 要收集的信号的信息
+    /// @param pending 信号的排队等待标志
+    /// @return SigInfo 信号的信息
+    pub fn collect_signal(&mut self, sig: Signal) -> SigInfo {
+        let (info, still_pending) = self.queue_mut().find_and_delete(sig);
+
+        // 如果没有仍在等待的信号,则清除pending位
+        if !still_pending {
+            self.signal_mut().remove(sig.into());
+        }
+
+        if info.is_some() {
+            return info.unwrap();
+        } else {
+            // 信号不在sigqueue中,这意味着当前信号是来自快速路径,因此直接把siginfo设置为0即可。
+            let mut ret = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(Pid::from(0)));
+            ret.set_sig_type(SigType::Kill(Pid::new(0)));
+            return ret;
+        }
+    }
+
+    /// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号)
+    /// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock
+    pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
+        // kdebug!("dequeue signal");
+        // 获取下一个要处理的信号的编号
+        let sig = self.next_signal(sig_mask);
+
+        let info: Option<SigInfo>;
+        if sig != Signal::INVALID {
+            // 如果下一个要处理的信号是合法的,则收集其siginfo
+            info = Some(self.collect_signal(sig));
+        } else {
+            info = None;
+        }
+
+        // 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
+        // recalc_sigpending();
+        return (sig, info);
+    }
+    /// @brief 从sigpending中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
+    pub fn flush_by_mask(&mut self, mask: &SigSet) {
+        // 定义过滤器,从sigqueue中删除mask中被置位的信号
+        let filter = |x: &mut SigInfo| {
+            if mask.contains(SigSet::from_bits_truncate(x.sig_no as u64)) {
+                return true;
+            }
+            return false;
+        };
+        let filter_result: Vec<SigInfo> = self.queue.q.drain_filter(filter).collect();
+        // 回收这些siginfo
+        for x in filter_result {
+            drop(x)
+        }
+    }
+}
+
+/// @brief 进程接收到的信号的队列
+#[derive(Debug, Clone)]
+pub struct SigQueue {
+    pub q: Vec<SigInfo>,
+}
+
+#[allow(dead_code)]
+impl SigQueue {
+    /// @brief 初始化一个新的信号队列
+    pub fn new(capacity: usize) -> Self {
+        SigQueue {
+            q: Vec::with_capacity(capacity),
+        }
+    }
+
+    /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
+    ///
+    /// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
+    pub fn find(&self, sig: Signal) -> (Option<&SigInfo>, bool) {
+        // 是否存在多个满足条件的siginfo
+        let mut still_pending = false;
+        let mut info: Option<&SigInfo> = None;
+
+        for x in self.q.iter() {
+            if x.sig_no == sig as i32 {
+                if info.is_some() {
+                    still_pending = true;
+                    break;
+                } else {
+                    info = Some(x);
+                }
+            }
+        }
+        return (info, still_pending);
+    }
+
+    /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除,然后返回这个siginfo
+    ///
+    /// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
+    pub fn find_and_delete(&mut self, sig: Signal) -> (Option<SigInfo>, bool) {
+        // 是否存在多个满足条件的siginfo
+        let mut still_pending = false;
+        let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
+
+        let filter = |x: &mut SigInfo| {
+            if x.sig_no == sig as i32 {
+                if !first {
+                    // 如果之前已经筛选出了一个元素,则不把当前元素删除
+                    still_pending = true;
+                    return false;
+                } else {
+                    // 当前是第一个被筛选出来的元素
+                    first = false;
+                    return true;
+                }
+            }
+            return false;
+        };
+        // 从sigqueue中过滤出结果
+        let mut filter_result: Vec<SigInfo> = self.q.drain_filter(filter).collect();
+        // 筛选出的结果不能大于1个
+        assert!(filter_result.len() <= 1);
+
+        return (filter_result.pop(), still_pending);
+    }
+
+    /// @brief 从C的void*指针转换为static生命周期的可变引用
+    pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue {
+        let sq = p as *mut SigQueue;
+        let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
+        return sq;
+    }
+}
+
+impl Default for SigQueue {
+    fn default() -> Self {
+        Self {
+            q: Default::default(),
+        }
+    }
+}
+
+///
+/// 定义了不同架构下实现 Signal 要实现的接口
+///
+pub trait SignalArch {
+    /// 信号处理函数
+    ///
+    /// ## 参数
+    ///
+    /// - `frame` 中断栈帧
+    unsafe fn do_signal(frame: &mut TrapFrame);
+
+    fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64;
+}

+ 159 - 15
kernel/src/ipc/syscall.rs

@@ -1,15 +1,27 @@
-use core::ffi::c_int;
+use core::{
+    ffi::{c_int, c_void},
+    sync::atomic::compiler_fence,
+};
 
 use crate::{
+    arch::ipc::signal::{SigCode, SigFlags, SigSet, Signal},
     filesystem::vfs::{
         file::{File, FileMode},
         FilePrivateData,
     },
+    kerror, kwarn,
+    mm::VirtAddr,
     process::{Pid, ProcessManager},
     syscall::{user_access::UserBufferWriter, Syscall, SystemError},
 };
 
-use super::pipe::{LockedPipeInode, PipeFsPrivateData};
+use super::{
+    pipe::{LockedPipeInode, PipeFsPrivateData},
+    signal_types::{
+        SaHandlerType, SigInfo, SigType, Sigaction, SigactionType, UserSigaction, USER_SIG_DFL,
+        USER_SIG_ERR, USER_SIG_IGN,
+    },
+};
 
 impl Syscall {
     /// # 创建带参数的匿名管道
@@ -52,26 +64,158 @@ impl Syscall {
         }
     }
 
-    pub fn kill(_pid: Pid, _sig: c_int) -> Result<usize, SystemError> {
-        // todo: 由于进程管理重构,目前删除了signal功能,将来重新实现它。
-        return Err(SystemError::ENOSYS);
+    pub fn kill(pid: Pid, sig: c_int) -> Result<usize, SystemError> {
+        let sig = Signal::from(sig);
+        if sig == Signal::INVALID {
+            // 传入的signal数值不合法
+            kwarn!("Not a valid signal number");
+            return Err(SystemError::EINVAL);
+        }
+
+        // 初始化signal info
+        let mut info = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(pid));
+
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+
+        let retval = sig
+            .send_signal_info(Some(&mut info), pid)
+            .map(|x| x as usize);
+
+        compiler_fence(core::sync::atomic::Ordering::SeqCst);
+
+        return retval;
     }
 
-    /// @brief 用户程序用于设置信号处理动作的函数(遵循posix2008)
+    /// 通用信号注册函数
+    ///
+    /// ## 参数
     ///
-    /// @param regs->r8 signumber 信号的编号
-    /// @param regs->r9 act 新的,将要被设置的sigaction
-    /// @param regs->r10 oact 返回给用户的原本的sigaction(内核将原本的sigaction的值拷贝给这个地址)
+    /// - `sig` 信号的值
+    /// - `act` 用户空间传入的 Sigaction 指针
+    /// - `old_act` 用户空间传入的用来保存旧 Sigaction 的指针
+    /// - `from_user` 用来标识这个函数调用是否来自用户空间
     ///
     /// @return int 错误码
     #[no_mangle]
     pub fn sigaction(
-        _sig: c_int,
-        _act: usize,
-        _old_act: usize,
-        _from_user: bool,
+        sig: c_int,
+        new_act: usize,
+        old_act: usize,
+        from_user: bool,
     ) -> Result<usize, SystemError> {
-        // todo: 由于进程管理重构,目前删除了signal功能,将来重新实现它。
-        return Err(SystemError::ENOSYS);
+        // 请注意:用户态传进来的user_sigaction结构体类型,请注意,这个结构体与内核实际的不一样
+        let act: *mut UserSigaction = new_act as *mut UserSigaction;
+        let mut old_act = old_act as *mut UserSigaction;
+        let mut new_ka: Sigaction = Default::default();
+        let mut old_sigaction: Sigaction = Default::default();
+        // 如果传入的,新的sigaction不为空
+        if !act.is_null() {
+            // 如果参数的范围不在用户空间,则返回错误
+            let r = UserBufferWriter::new(act, core::mem::size_of::<Sigaction>(), from_user);
+            if r.is_err() {
+                return Err(SystemError::EFAULT);
+            }
+            let mask: SigSet = unsafe { (*act).mask };
+            let input_sighandler = unsafe { (*act).handler as u64 };
+            match input_sighandler {
+                USER_SIG_DFL => {
+                    new_ka = Sigaction::DEFAULT_SIGACTION.clone();
+                    *new_ka.flags_mut() = unsafe { (*act).flags };
+                    new_ka.set_restorer(None);
+                }
+
+                USER_SIG_IGN => {
+                    new_ka = Sigaction::DEFAULT_SIGACTION_IGNORE.clone();
+                    *new_ka.flags_mut() = unsafe { (*act).flags };
+
+                    new_ka.set_restorer(None);
+                }
+                _ => {
+                    // 从用户空间获得sigaction结构体
+                    // TODO mask是default还是用户空间传入
+                    new_ka = Sigaction::new(
+                        SigactionType::SaHandler(SaHandlerType::SigCustomized(unsafe {
+                            VirtAddr::new((*act).handler as usize)
+                        })),
+                        unsafe { (*act).flags },
+                        SigSet::default(),
+                        unsafe { Some(VirtAddr::new((*act).restorer as usize)) },
+                    );
+                }
+            }
+
+            // TODO 如果为空,赋默认值?
+            // kdebug!("new_ka={:?}", new_ka);
+            // 如果用户手动给了sa_restorer,那么就置位SA_FLAG_RESTORER,否则报错。(用户必须手动指定restorer)
+            if new_ka.restorer().is_some() {
+                new_ka.flags_mut().insert(SigFlags::SA_RESTORER);
+            } else if new_ka.action().is_customized() {
+                kerror!(
+                "pid:{:?}: in sys_sigaction: User must manually sprcify a sa_restorer for signal {}.",
+                ProcessManager::current_pcb().pid(),
+                sig
+            );
+                return Err(SystemError::EINVAL);
+            }
+            *new_ka.mask_mut() = mask;
+        }
+
+        let sig = Signal::from(sig as i32);
+        // 如果给出的信号值不合法
+        if sig == Signal::INVALID {
+            return Err(SystemError::EINVAL);
+        }
+
+        let retval = super::signal::do_sigaction(
+            sig,
+            if act.is_null() {
+                None
+            } else {
+                Some(&mut new_ka)
+            },
+            if old_act.is_null() {
+                None
+            } else {
+                Some(&mut old_sigaction)
+            },
+        );
+
+        //
+        if (retval == Ok(())) && (!old_act.is_null()) {
+            let r =
+                UserBufferWriter::new(old_act, core::mem::size_of::<UserSigaction>(), from_user);
+            if r.is_err() {
+                return Err(SystemError::EFAULT);
+            }
+
+            let sigaction_handler: VirtAddr;
+            sigaction_handler = match old_sigaction.action() {
+                SigactionType::SaHandler(handler) => {
+                    if let SaHandlerType::SigCustomized(hand) = handler {
+                        hand
+                    } else if handler.is_sig_ignore() {
+                        VirtAddr::new(USER_SIG_IGN as usize)
+                    } else if handler.is_sig_error() {
+                        VirtAddr::new(USER_SIG_ERR as usize)
+                    } else {
+                        VirtAddr::new(USER_SIG_DFL as usize)
+                    }
+                }
+                SigactionType::SaSigaction(_) => {
+                    kerror!("unsupported type: SaSigaction");
+                    VirtAddr::new(USER_SIG_DFL as usize)
+                }
+            };
+
+            unsafe {
+                (*old_act).handler = sigaction_handler.data() as *mut c_void;
+                (*old_act).flags = old_sigaction.flags();
+                (*old_act).mask = old_sigaction.mask();
+                if old_sigaction.restorer().is_some() {
+                    (*old_act).restorer = old_sigaction.restorer().unwrap().data() as *mut c_void;
+                }
+            }
+        }
+        return retval.map(|_| 0);
     }
 }

+ 21 - 7
kernel/src/process/fork.rs

@@ -1,8 +1,9 @@
 use alloc::{string::ToString, sync::Arc};
 
 use crate::{
-    arch::interrupt::TrapFrame, filesystem::procfs::procfs_register_pid, libs::rwlock::RwLock,
-    process::ProcessFlags, syscall::SystemError,
+    arch::interrupt::TrapFrame, filesystem::procfs::procfs_register_pid,
+    ipc::signal::flush_signal_handlers, libs::rwlock::RwLock, process::ProcessFlags,
+    syscall::SystemError,
 };
 
 use super::{
@@ -87,7 +88,13 @@ impl ProcessManager {
             )
         });
 
-        // todo: 拷贝信号相关数据
+        //拷贝信号相关数据
+        ProcessManager::copy_sighand(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
+            panic!(
+                "fork: Failed to copy sighands from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
+                current_pcb.pid(), pcb.pid(), e
+            )
+        });
 
         // 拷贝线程
         ProcessManager::copy_thread(&clone_flags, &current_pcb, &pcb, &current_trapframe).unwrap_or_else(|e| {
@@ -194,11 +201,18 @@ impl ProcessManager {
 
     #[allow(dead_code)]
     fn copy_sighand(
-        _clone_flags: &CloneFlags,
-        _current_pcb: &Arc<ProcessControlBlock>,
-        _new_pcb: &Arc<ProcessControlBlock>,
+        clone_flags: &CloneFlags,
+        current_pcb: &Arc<ProcessControlBlock>,
+        new_pcb: &Arc<ProcessControlBlock>,
     ) -> Result<(), SystemError> {
-        // todo: 由于信号原来写的太烂,移植到新的进程管理的话,需要改动很多。因此决定重写。这里先空着
+        // // 将信号的处理函数设置为default(除了那些被手动屏蔽的)
+        if clone_flags.contains(CloneFlags::CLONE_CLEAR_SIGHAND) {
+            flush_signal_handlers(new_pcb.clone(), false);
+        }
+
+        if clone_flags.contains(CloneFlags::CLONE_SIGHAND) {
+            (*new_pcb.sig_struct()).handlers = current_pcb.sig_struct().handlers.clone();
+        }
         return Ok(());
     }
 }

+ 165 - 4
kernel/src/process/mod.rs

@@ -13,12 +13,18 @@ use alloc::{
 use hashbrown::HashMap;
 
 use crate::{
-    arch::{process::ArchPCBInfo, sched::sched, CurrentIrqArch},
+    arch::{
+        ipc::signal::{SigSet, Signal},
+        process::ArchPCBInfo,
+        sched::sched,
+        CurrentIrqArch,
+    },
     exception::InterruptArch,
     filesystem::{
         procfs::procfs_unregister_pid,
         vfs::{file::FileDescriptorVec, FileType},
     },
+    ipc::signal_types::{SigInfo, SigPending, SignalStruct},
     kdebug, kinfo,
     libs::{
         align::AlignedBox,
@@ -34,7 +40,7 @@ use crate::{
         SchedPolicy, SchedPriority,
     },
     smp::kick_cpu,
-    syscall::SystemError,
+    syscall::{Syscall, SystemError},
 };
 
 use self::kthread::WorkerPrivate;
@@ -46,6 +52,7 @@ pub mod fork;
 pub mod idle;
 pub mod init;
 pub mod kthread;
+pub mod pid;
 pub mod process;
 pub mod syscall;
 
@@ -184,6 +191,32 @@ impl ProcessManager {
         }
     }
 
+    /// 唤醒暂停的进程
+    pub fn wakeup_stop(pcb: &Arc<ProcessControlBlock>) -> Result<(), SystemError> {
+        let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+        let state = pcb.sched_info().state();
+        if let ProcessState::Stopped = state {
+            let mut writer = pcb.sched_info_mut();
+            let state = writer.state();
+            if let ProcessState::Stopped = state {
+                writer.set_state(ProcessState::Runnable);
+                // avoid deadlock
+                drop(writer);
+
+                sched_enqueue(pcb.clone(), true);
+                return Ok(());
+            } else if state.is_runnable() {
+                return Ok(());
+            } else {
+                return Err(SystemError::EINVAL);
+            }
+        } else if state.is_runnable() {
+            return Ok(());
+        } else {
+            return Err(SystemError::EINVAL);
+        }
+    }
+
     /// 标志当前进程永久睡眠,但是发起调度的工作,应该由调用者完成
     ///
     /// ## 注意
@@ -199,7 +232,7 @@ impl ProcessManager {
 
         let pcb = ProcessManager::current_pcb();
         let mut writer = pcb.sched_info_mut_irqsave();
-        if writer.state() != ProcessState::Exited(0) {
+        if !matches!(writer.state(), ProcessState::Exited(_)) {
             writer.set_state(ProcessState::Blocked(interruptable));
             pcb.flags().insert(ProcessFlags::NEED_SCHEDULE);
             drop(writer);
@@ -209,6 +242,30 @@ impl ProcessManager {
         return Err(SystemError::EINTR);
     }
 
+    /// 标志当前进程为停止状态,但是发起调度的工作,应该由调用者完成
+    ///
+    /// ## 注意
+    ///
+    /// - 进入当前函数之前,不能持有sched_info的锁
+    /// - 进入当前函数之前,必须关闭中断
+    pub fn mark_stop() -> Result<(), SystemError> {
+        assert_eq!(
+            CurrentIrqArch::is_irq_enabled(),
+            false,
+            "interrupt must be disabled before enter ProcessManager::mark_sleep()"
+        );
+
+        let pcb = ProcessManager::current_pcb();
+        let mut writer = pcb.sched_info_mut_irqsave();
+        if !matches!(writer.state(), ProcessState::Exited(_)) {
+            writer.set_state(ProcessState::Stopped);
+            pcb.flags().insert(ProcessFlags::NEED_SCHEDULE);
+            drop(writer);
+
+            return Ok(());
+        }
+        return Err(SystemError::EINTR);
+    }
     /// 当子进程退出后向父进程发送通知
     fn exit_notify() {
         let current = ProcessManager::current_pcb();
@@ -219,6 +276,19 @@ impl ProcessManager {
                     .adopt_childen()
                     .unwrap_or_else(|e| panic!("adopte_childen failed: error: {e:?}"))
             };
+            let r = current.parent_pcb.read().upgrade();
+            if r.is_none() {
+                return;
+            }
+            let parent_pcb = r.unwrap();
+            let r = Syscall::kill(parent_pcb.pid(), Signal::SIGCHLD as i32);
+            if r.is_err() {
+                kwarn!(
+                    "failed to send kill signal to {:?}'s parent pcb {:?}",
+                    current.pid(),
+                    parent_pcb.pid()
+                );
+            }
             // todo: 当信号机制重写后,这里需要向父进程发送SIGCHLD信号
         }
     }
@@ -332,7 +402,7 @@ pub enum ProcessState {
     /// - 如果该bool为false,那么,这个进程必须被显式的唤醒,才能重新进入Runnable状态。
     Blocked(bool),
     /// 进程被信号终止
-    // Stopped(SignalNumber),
+    Stopped,
     /// 进程已经退出,usize表示进程的退出码
     Exited(usize),
 }
@@ -353,6 +423,14 @@ impl ProcessState {
     pub fn is_exited(&self) -> bool {
         return matches!(self, ProcessState::Exited(_));
     }
+
+    /// Returns `true` if the process state is [`Stopped`].
+    ///
+    /// [`Stopped`]: ProcessState::Stopped
+    #[inline(always)]
+    pub fn is_stopped(&self) -> bool {
+        matches!(self, ProcessState::Stopped)
+    }
 }
 
 bitflags! {
@@ -395,6 +473,10 @@ pub struct ProcessControlBlock {
     sched_info: RwLock<ProcessSchedulerInfo>,
     /// 与处理器架构相关的信息
     arch_info: SpinLock<ArchPCBInfo>,
+    /// 与信号处理相关的信息(似乎可以是无锁的)
+    sig_info: RwLock<ProcessSignalInfo>,
+    /// 信号处理结构体
+    sig_struct: SpinLock<SignalStruct>,
 
     /// 父进程指针
     parent_pcb: RwLock<Weak<ProcessControlBlock>>,
@@ -460,6 +542,8 @@ impl ProcessControlBlock {
             worker_private: SpinLock::new(None),
             sched_info,
             arch_info,
+            sig_info: RwLock::new(ProcessSignalInfo::default()),
+            sig_struct: SpinLock::new(SignalStruct::default()),
             parent_pcb: RwLock::new(ppcb),
             children: RwLock::new(HashMap::new()),
             wait_queue: WaitQueue::INIT,
@@ -638,6 +722,22 @@ impl ProcessControlBlock {
         }
         return name;
     }
+
+    pub fn sig_info(&self) -> RwLockReadGuard<ProcessSignalInfo> {
+        self.sig_info.read()
+    }
+
+    pub fn sig_info_mut(&self) -> RwLockWriteGuard<ProcessSignalInfo> {
+        self.sig_info.write()
+    }
+
+    pub fn sig_struct(&self) -> SpinLockGuard<SignalStruct> {
+        self.sig_struct.lock()
+    }
+
+    pub fn sig_struct_irq(&self) -> SpinLockGuard<SignalStruct> {
+        self.sig_struct.lock_irqsave()
+    }
 }
 
 impl Drop for ProcessControlBlock {
@@ -948,3 +1048,64 @@ impl Drop for KernelStack {
 pub fn process_init() {
     ProcessManager::init();
 }
+
+#[derive(Debug)]
+pub struct ProcessSignalInfo {
+    // 当前进程
+    sig_block: SigSet,
+    // sig_pending 中存储当前线程要处理的信号
+    sig_pending: SigPending,
+    // sig_shared_pending 中存储当前线程所属进程要处理的信号
+    sig_shared_pending: SigPending,
+}
+
+impl ProcessSignalInfo {
+    pub fn sig_block(&self) -> &SigSet {
+        &self.sig_block
+    }
+
+    pub fn sig_pending(&self) -> &SigPending {
+        &self.sig_pending
+    }
+
+    pub fn sig_pending_mut(&mut self) -> &mut SigPending {
+        &mut self.sig_pending
+    }
+
+    pub fn sig_block_mut(&mut self) -> &mut SigSet {
+        &mut self.sig_block
+    }
+
+    pub fn sig_shared_pending_mut(&mut self) -> &mut SigPending {
+        &mut self.sig_shared_pending
+    }
+
+    pub fn sig_shared_pending(&self) -> &SigPending {
+        &self.sig_shared_pending
+    }
+
+    /// 从 pcb 的 siginfo中取出下一个要处理的信号,先处理线程信号,再处理进程信号
+    ///
+    /// ## 参数
+    ///
+    /// - `sig_mask` 被忽略掉的信号
+    ///
+    pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
+        let res = self.sig_pending.dequeue_signal(sig_mask);
+        if res.0 != Signal::INVALID {
+            return res;
+        } else {
+            return self.sig_shared_pending.dequeue_signal(sig_mask);
+        }
+    }
+}
+
+impl Default for ProcessSignalInfo {
+    fn default() -> Self {
+        Self {
+            sig_block: SigSet::empty(),
+            sig_pending: SigPending::default(),
+            sig_shared_pending: SigPending::default(),
+        }
+    }
+}

+ 18 - 0
kernel/src/process/pid.rs

@@ -0,0 +1,18 @@
+#[allow(dead_code)]
+#[derive(Debug, Clone, Copy)]
+#[repr(u8)]
+pub enum PidType {
+    /// pid类型是进程id
+    PID = 1,
+    TGID = 2,
+    PGID = 3,
+    SID = 4,
+    MAX = 5,
+}
+
+/// 为PidType实现判断相等的trait
+impl PartialEq for PidType {
+    fn eq(&self, other: &PidType) -> bool {
+        *self as u8 == *other as u8
+    }
+}

+ 0 - 1
kernel/src/process/proc-types.h

@@ -1,7 +1,6 @@
 #pragma once
 
 #include "ptrace.h"
-#include <DragonOS/signal.h>
 #include <DragonOS/stdint.h>
 
 // 进程最大可拥有的文件描述符数量

+ 1 - 1
kernel/src/process/syscall.rs

@@ -111,7 +111,7 @@ impl Syscall {
                             return Ok(0);
                         }
                     }
-                    ProcessState::Blocked(_) => {
+                    ProcessState::Blocked(_) | ProcessState::Stopped => {
                         // 指定WUNTRACED则等待暂停的进程,不指定则返回0
                         if !options.contains(WaitOption::WUNTRACED)
                             || options.contains(WaitOption::WNOWAIT)

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

@@ -670,7 +670,7 @@ impl Syscall {
             SYS_KILL => {
                 let pid = Pid::new(args[0]);
                 let sig = args[1] as c_int;
-
+                // kdebug!("KILL SYSCALL RECEIVED");
                 Self::kill(pid, sig)
             }
 

+ 1 - 1
kernel/src/syscall/user_access.rs

@@ -286,7 +286,7 @@ impl<'a> UserBufferWriter<'a> {
     ///
     /// @param data 要写入的数据地址
     /// @param offset 在UserBuffer中的字节偏移量
-    /// @return 返回写入元素的数量
+    /// @return Ok/Err
     ///
     pub fn copy_one_to_user<T: core::marker::Copy>(
         &'a mut self,

+ 1 - 1
user/apps/Makefile

@@ -1,5 +1,5 @@
 
-user_apps_sub_dirs=shell about test_signal
+user_apps_sub_dirs=shell about
 
 ECHO:
 	@echo "$@"

+ 18 - 2
user/apps/test_signal/Makefile

@@ -1,9 +1,25 @@
-OLD_LIBC_INSTALL_PATH=$(ROOT_PATH)/bin/sysroot/usr/old_libc
+CC=$(DragonOS_GCC)/x86_64-elf-gcc
+LD=ld
+OBJCOPY=objcopy
+# 修改这里,把它改为你的relibc的sysroot路径
+RELIBC_OPT=$(DADK_BUILD_CACHE_DIR_RELIBC_0_1_0)
+CFLAGS=-I $(RELIBC_OPT)/include -D__dragonos__
+
+tmp_output_dir=$(ROOT_PATH)/bin/tmp/user
+output_dir=$(DADK_BUILD_CACHE_DIR_TEST_SIGNAL_0_1_0)
+
+
+LIBC_OBJS:=$(shell find $(RELIBC_OPT)/lib -name "*.o" | sort )
+LIBC_OBJS+=$(RELIBC_OPT)/lib/libc.a
 
 all: main.o
 
-	$(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_signal  $(shell find . -name "*.o") $(OLD_LIBC_INSTALL_PATH)/lib/libc.a -T link.lds
+	$(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_signal  $(shell find . -name "*.o") $(LIBC_OBJS) -T link.lds
 
 	$(OBJCOPY) -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test_signal $(output_dir)/test_signal.elf
+	mv $(output_dir)/test_signal.elf $(output_dir)/test_signal
 main.o: main.c
 	$(CC) $(CFLAGS) -c main.c  -o main.o
+
+clean:
+	rm -f *.o

+ 234 - 49
user/apps/test_signal/link.lds

@@ -1,54 +1,239 @@
-
-OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
+/* Script for -z combreloc */
+/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+              "elf64-x86-64")
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(_start)
 
 SECTIONS
 {
-
-	. = 0x800000;
-	
-	
-	.text :
-	{
-		_text = .;
-		
-		*(.text)
-		*(.text.*)
-		
-		_etext = .;
-	}
-	. = ALIGN(8);
-	
-	.data :
-	{
-		_data = .;
-		*(.data)
-		*(.data.*)
-		
-		_edata = .;
-	}
-
-
-	rodata_start_pa = .;
-	.rodata :
-	{
-		_rodata = .;	
-		*(.rodata)
-		*(.rodata.*)
-		_erodata = .;
-	}
-
-	
-	.bss :
-	{
-		_bss = .;
-		*(.bss)
-		*(.bss.*)
-		_ebss = .;
-	}
-
-	_end = .;
-
-
-}
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id  : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+.plt.got        : { *(.plt.got) }
+.plt.sec        : { *(.plt.sec) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
+  /* Adjust the address for the rodata segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+  .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+  .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata          :
+   {
+     PROVIDE_HIDDEN (__tdata_start = .);
+     *(.tdata .tdata.* .gnu.linkonce.td.*)
+   }
+  .tbss           : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array    :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array    :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array    :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt) *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we do not
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .debug_addr     0 : { *(.debug_addr) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}

+ 10 - 10
user/apps/test_signal/main.c

@@ -23,35 +23,35 @@
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
-
+#include <stdbool.h>
 bool handle_ok = false;
-
+int count = 0;
 void handler(int sig)
 {
     printf("handle %d\n", sig);
     handle_ok = true;
+    count++;
 }
 
 int main()
 {
-    printf("Test signal running...\n");
     signal(SIGKILL, &handler);
     printf("registered.\n");
 
-    clock_t last = clock();
-
     while (1)
     {
-        if ((clock() - last) / CLOCKS_PER_SEC >= 1)
-        {
-            // printf("Test signal running\n");
-            last = clock();
-        }
+        // handler(SIGKILL);
+        printf("Test signal running\n");
+        raise(SIGKILL);
         if (handle_ok)
         {
             printf("Handle OK!\n");
             handle_ok = false;
         }
+        if (count > 0)
+        {
+            signal(SIGKILL, SIG_DFL);
+        }
     }
 
     return 0;

+ 1 - 1
user/apps/test_uart/Makefile

@@ -22,4 +22,4 @@ main.o: main.c
 	$(CC) $(CFLAGS) -c main.c  -o main.o
 
 clean:
-	rm -f *.o
+	rm -f *.o

+ 1 - 1
user/dadk/config/relibc-0.1.0.dadk

@@ -6,7 +6,7 @@
     "BuildFromSource": {
       "Git": {
         "url": "https://git.mirrors.dragonos.org/DragonOS-Community/relibc.git",
-        "revision": "66739c1b10"
+        "revision": "0a1b6ce239"
       }
     }
   },

+ 28 - 0
user/dadk/config/test_signal-0.1.0.dadk

@@ -0,0 +1,28 @@
+{
+  "name": "test_signal",
+  "version": "0.1.0",
+  "description": "一个用来测试signal能够正常运行的app",
+  "task_type": {
+    "BuildFromSource": {
+      "Local": {
+        "path": "apps/test_signal"
+      }
+    }
+  },
+  "depends": [
+    {
+      "name": "relibc",
+      "version": "0.1.0"
+    }
+  ],
+  "build": {
+    "build_command": "make"
+  },
+  "install": {
+    "in_dragonos_path": "/bin"
+  },
+  "clean": {
+    "clean_command": "make clean"
+  },
+  "envs": []
+}