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 相关依赖项
This commit is contained in:
Chiichen
2023-10-24 12:02:20 +08:00
committed by GitHub
parent d7f5742a20
commit 3c82aa56d1
29 changed files with 2353 additions and 261 deletions

View File

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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 {

View File

@ -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);
}
_ => {}
}

View File

@ -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)
{

View File

@ -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);
}

View File

@ -1,144 +0,0 @@
/**
* @file signal.h
* @author longjin (longjin@RinGoTek.cn)
* @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中实现)
};

View File

@ -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>

View File

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

416
kernel/src/ipc/signal.rs Normal file
View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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(());
}
}

View File

@ -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
kernel/src/process/pid.rs Normal file
View File

@ -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
}
}

View File

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

View File

@ -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)

View File

@ -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)
}

View File

@ -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,