mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
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:
parent
d7f5742a20
commit
3c82aa56d1
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -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",
|
||||
|
@ -60,9 +60,10 @@ impl FpState {
|
||||
}
|
||||
}
|
||||
|
||||
/// 清空fp_state
|
||||
/// 清空浮点寄存器
|
||||
#[allow(dead_code)]
|
||||
pub fn clear(&mut self) {
|
||||
*self = Self::default();
|
||||
self.restore();
|
||||
}
|
||||
}
|
||||
|
@ -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
kernel/src/arch/x86_64/ipc/signal.rs
Normal file
679
kernel/src/arch/x86_64/ipc/signal.rs
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
@ -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,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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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中实现)
|
||||
};
|
@ -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>
|
||||
|
@ -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
416
kernel/src/ipc/signal.rs
Normal 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);
|
||||
}
|
529
kernel/src/ipc/signal_types.rs
Normal file
529
kernel/src/ipc/signal_types.rs
Normal 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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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, ¤t_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, ¤t_pcb, &pcb, ¤t_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(());
|
||||
}
|
||||
}
|
||||
|
@ -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
18
kernel/src/process/pid.rs
Normal 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
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "ptrace.h"
|
||||
#include <DragonOS/signal.h>
|
||||
#include <DragonOS/stdint.h>
|
||||
|
||||
// 进程最大可拥有的文件描述符数量
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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,5 +1,5 @@
|
||||
|
||||
user_apps_sub_dirs=shell about test_signal
|
||||
user_apps_sub_dirs=shell about
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
@ -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
|
@ -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_*) }
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -22,4 +22,4 @@ main.o: main.c
|
||||
$(CC) $(CFLAGS) -c main.c -o main.o
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f *.o
|
||||
|
@ -6,7 +6,7 @@
|
||||
"BuildFromSource": {
|
||||
"Git": {
|
||||
"url": "https://git.mirrors.dragonos.org/DragonOS-Community/relibc.git",
|
||||
"revision": "66739c1b10"
|
||||
"revision": "0a1b6ce239"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
28
user/dadk/config/test_signal-0.1.0.dadk
Normal file
28
user/dadk/config/test_signal-0.1.0.dadk
Normal file
@ -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": []
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user