允许用户自定义信号处理函数 (#112)

* new: 用户注册信号处理函数,能够进入自定义的handler

* 修复忘了传信号的数字给用户的处理函数的bug

* new:sigreturn

* 删除注释
This commit is contained in:
login 2022-12-17 16:27:50 +08:00 committed by GitHub
parent 0e0c187484
commit 6efd474033
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 566 additions and 100 deletions

View File

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

View File

@ -112,6 +112,7 @@ struct sigaction
#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加锁

View File

@ -16,13 +16,13 @@
#include <common/crc7.h>
#include <common/crc8.h>
#include <common/gfp.h>
#include <common/glib.h>
#include <common/kfifo.h>
#include <common/list.h>
#include <common/lz4.h>
#include <common/printk.h>
#include <common/spinlock.h>
#include <common/unistd.h>
#include <common/glib.h>
#include <driver/timers/rtc/rtc.h>
#include <include/DragonOS/refcount.h>
#include <include/DragonOS/signal.h>

View File

@ -7,10 +7,11 @@ use crate::{
},
include::bindings::bindings::{
pid_t, process_control_block, process_do_exit, process_find_pcb_by_pid, pt_regs,
spinlock_t, verify_area, EINVAL, ENOTSUP, EPERM, ESRCH, PF_EXITING, PF_KTHREAD,
PF_SIGNALED, PF_WAKEKILL, PROC_INTERRUPTIBLE, USER_CS, USER_DS, USER_MAX_LINEAR_ADDR,
spinlock_t, verify_area, EFAULT, EINVAL, ENOTSUP, EPERM, ESRCH, NULL, PF_EXITING,
PF_KTHREAD, PF_SIGNALED, PF_WAKEKILL, PROC_INTERRUPTIBLE, USER_CS, USER_DS,
USER_MAX_LINEAR_ADDR,
},
ipc::signal_types::sigset_add,
ipc::signal_types::{sigset_add, user_sigaction},
kBUG, kdebug, kerror, kwarn,
libs::{
ffi_convert::FFIBind2Rust,
@ -19,7 +20,6 @@ use crate::{
spin_unlock_irqrestore,
},
},
println,
process::{
pid::PidType,
process::{process_is_stopped, process_kick, process_wake_up_state},
@ -27,28 +27,34 @@ use crate::{
};
use super::signal_types::{
si_code_val, sigaction, sigaction__union_u, sigcontext, sigframe, sighand_struct, siginfo,
signal_struct, sigpending, sigset_clear, sigset_del, sigset_t, SignalNumber, MAX_SIG_NUM,
SA_FLAG_DFL, SA_FLAG_IGN, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT,
si_code_val, sig_is_member, sigaction, sigaction__union_u, sigcontext, sigframe,
sighand_struct, siginfo, signal_struct, sigpending, sigset_clear, sigset_del, sigset_delmask,
sigset_equal, sigset_init, sigset_t, SigQueue, SignalNumber, MAX_SIG_NUM, SA_ALL_FLAGS,
SA_FLAG_DFL, SA_FLAG_IGN, SA_FLAG_IMMUTABLE, SA_FLAG_RESTORER, STACK_ALIGN, USER_SIG_DFL,
USER_SIG_IGN, _NSIG_U64_CNT,
};
use super::signal_types::{__siginfo_union, __siginfo_union_data};
/// 默认信号处理程序占位符用于在sighand结构体中的action数组中占位
pub static DEFAULT_SIGACTION: sigaction = sigaction {
_u: sigaction__union_u { _sa_handler: None },
_u: sigaction__union_u {
_sa_handler: NULL as u64,
},
sa_flags: SA_FLAG_DFL,
sa_mask: 0,
sa_restorer: None,
sa_restorer: NULL as u64,
};
/// 默认的“忽略信号”的sigaction
#[allow(dead_code)]
pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction {
_u: sigaction__union_u { _sa_handler: None },
_u: sigaction__union_u {
_sa_handler: NULL as u64,
},
sa_flags: SA_FLAG_IGN,
sa_mask: 0,
sa_restorer: None,
sa_restorer: NULL as u64,
};
/// @brief kill系统调用向指定的进程发送信号
@ -56,13 +62,6 @@ pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction {
/// @param regs->r9 sig 信号
#[no_mangle]
pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 {
println!(
"sys kill, target pid={}, file={}, line={}",
regs.r8,
file!(),
line!()
);
let pid: pid_t = regs.r8 as pid_t;
let sig: SignalNumber = SignalNumber::from(regs.r9 as i32);
if sig == SignalNumber::INVALID {
@ -343,18 +342,6 @@ fn wants_signal(sig: SignalNumber, pcb: &process_control_block) -> bool {
return !has_sig_pending(pcb);
}
/// @brief 判断指定的信号在sigset中的对应位是否被置位
/// @return true: 给定的信号在sigset中被置位
/// @return false: 给定的信号在sigset中没有被置位
#[inline]
fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool {
return if 1 & (set >> ((_sig as u32) - 1)) != 0 {
true
} else {
false
};
}
/// @brief 判断signal的处理是否可能使得整个进程组退出
/// @return true 可能会导致退出(不一定)
#[allow(dead_code)]
@ -367,7 +354,7 @@ fn sig_fatal(pcb: &process_control_block, sig: SignalNumber) -> bool {
};
// 如果handler是空采用默认函数signal处理可能会导致进程退出。
if handler.is_none() {
if handler == NULL.into() {
return true;
} else {
return false;
@ -626,7 +613,7 @@ fn setup_frame(
) -> Result<i32, i32> {
let mut err = 0;
let frame: *mut sigframe = get_stack(ka, &regs, size_of::<sigframe>());
// kdebug!("frame=0x{:016x}", frame as usize);
// 要求这个frame的地址位于用户空间因此进行校验
let access_check_ok = unsafe { verify_area(frame as u64, size_of::<sigframe>() as u64) };
if !access_check_ok {
@ -640,7 +627,7 @@ fn setup_frame(
(*frame).arg0 = sig as u64;
(*frame).arg1 = &((*frame).info) as *const siginfo as usize;
(*frame).arg2 = &((*frame).context) as *const sigcontext as usize;
(*frame).handler = ka._u._sa_handler.unwrap() as *mut core::ffi::c_void;
(*frame).handler = ka._u._sa_handler as usize as *mut c_void;
}
// 将siginfo拷贝到用户栈
@ -653,8 +640,7 @@ fn setup_frame(
// 为了与Linux的兼容性64位程序必须由用户自行指定restorer
if ka.sa_flags & SA_FLAG_RESTORER != 0 {
unsafe {
(*frame).ret_code_ptr =
(&mut ka.sa_restorer.unwrap()) as *mut unsafe extern "C" fn() as *mut c_void;
(*frame).ret_code_ptr = ka.sa_restorer as usize as *mut c_void;
}
} else {
kerror!(
@ -668,11 +654,13 @@ fn setup_frame(
// todo: 在这里生成一个sigsegv,然后core dump
return Err(1);
}
// 传入信号处理函数的第一个参数
regs.rdi = sig as u64;
regs.rsi = unsafe { &(*frame).info as *const siginfo as u64 };
regs.rsp = frame as u64;
regs.rip = unsafe { ka._u._sa_handler.unwrap() as *const unsafe extern "C" fn() as u64 };
regs.rip = unsafe { ka._u._sa_handler };
// todo: 传入新版的sa_sigaction的处理函数的第三个参数
// 如果handler位于内核空间
if regs.rip >= USER_MAX_LINEAR_ADDR {
@ -737,6 +725,25 @@ fn setup_sigcontext(context: &mut sigcontext, mask: &sigset_t, regs: &pt_regs) -
return Ok(0);
}
/// @brief 将指定的sigcontext恢复到当前进程的内核栈帧中,并将当前线程结构体的几个参数进行恢复
///
/// @param context 要被恢复的context
/// @param regs 目标栈帧也就是把context恢复到这个栈帧中
///
/// @return bool true -> 成功恢复
/// false -> 执行失败
fn restore_sigcontext(context: *const sigcontext, regs: &mut pt_regs) -> bool {
let mut current_thread = current_pcb().thread;
unsafe {
*regs = (*context).regs;
(*current_thread).trap_num = (*context).trap_num;
(*current_thread).cr2 = (*context).cr2;
(*current_thread).err_code = (*context).err_code;
}
return true;
}
/// @brief 刷新指定进程的sighand的sigaction将满足条件的sigaction恢复为Default
/// 除非某个信号被设置为ignore且force_default为false否则都不会将其恢复
///
@ -759,3 +766,260 @@ pub fn flush_signal_handlers(pcb: *mut process_control_block, force_default: boo
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
}
/// @brief 用户程序用于设置信号处理动作的函数遵循posix2008
///
/// @param regs->r8 signumber 信号的编号
/// @param regs->r9 act 新的将要被设置的sigaction
/// @param regs->r10 oact 返回给用户的原本的sigaction内核将原本的sigaction的值拷贝给这个地址
///
/// @return int 错误码
#[no_mangle]
pub extern "C" fn sys_sigaction(regs: &mut pt_regs) -> u64 {
// 请注意用户态传进来的user_sigaction结构体类型请注意这个结构体与内核实际的不一样
let act = regs.r9 as usize as *mut user_sigaction;
let mut old_act = regs.r10 as usize as *mut user_sigaction;
let mut new_ka: sigaction = Default::default();
let mut old_ka: sigaction = Default::default();
// 如果传入的新的sigaction不为空
if !act.is_null() {
// 如果参数的范围不在用户空间,则返回错误
if unsafe { !verify_area(act as usize as u64, size_of::<sigaction>() as u64) } {
return (-(EFAULT as i64)) as u64;
}
let mask: sigset_t = unsafe { (*act).sa_mask };
let _input_sah = unsafe { (*act).sa_handler as u64 };
match _input_sah {
USER_SIG_DFL | USER_SIG_IGN => {
if _input_sah == USER_SIG_DFL {
new_ka = DEFAULT_SIGACTION;
new_ka.sa_flags =
(unsafe { (*act).sa_flags } & (!(SA_FLAG_DFL | SA_FLAG_IGN))) | SA_FLAG_DFL;
} else {
new_ka = DEFAULT_SIGACTION_IGNORE;
new_ka.sa_flags =
(unsafe { (*act).sa_flags } & (!(SA_FLAG_DFL | SA_FLAG_IGN))) | SA_FLAG_IGN;
}
let sar = unsafe { (*act).sa_restorer };
new_ka.sa_restorer = sar as u64;
}
_ => {
// 从用户空间获得sigaction结构体
new_ka = sigaction {
_u: sigaction__union_u {
_sa_handler: unsafe { (*act).sa_handler as u64 },
},
sa_flags: unsafe { (*act).sa_flags },
sa_mask: sigset_t::default(),
sa_restorer: unsafe { (*act).sa_restorer as u64 },
};
}
}
// 如果用户手动给了sa_restorer那么就置位SA_FLAG_RESTORER否则报错。用户必须手动指定restorer
if new_ka.sa_restorer != NULL as u64 {
new_ka.sa_flags |= SA_FLAG_RESTORER;
} else {
kwarn!(
"pid:{}: in sys_sigaction: User must manually sprcify a sa_restorer for signal {}.",
current_pcb().pid,
regs.r8.clone()
);
}
sigset_init(&mut new_ka.sa_mask, mask);
}
let sig = SignalNumber::from(regs.r8 as i32);
// 如果给出的信号值不合法
if sig == SignalNumber::INVALID {
return (-(EINVAL as i64)) as u64;
}
let retval = do_sigaction(
sig,
if act.is_null() {
None
} else {
Some(&mut new_ka)
},
if old_act.is_null() {
None
} else {
Some(&mut old_ka)
},
);
// 将原本的sigaction拷贝到用户程序指定的地址
if (retval == 0) && (!old_act.is_null()) {
if unsafe { !verify_area(old_act as usize as u64, size_of::<sigaction>() as u64) } {
return (-(EFAULT as i64)) as u64;
}
// todo: 检查这里old_ka的mask是否位SIG_IGN SIG_DFL,如果是则将_sa_handler字段替换为对应的值
let sah: u64;
let flag = old_ka.sa_flags & (SA_FLAG_DFL | SA_FLAG_IGN);
match flag {
SA_FLAG_DFL => {
sah = USER_SIG_DFL;
}
SA_FLAG_IGN => {
sah = USER_SIG_IGN;
}
_ => sah = unsafe { old_ka._u._sa_handler },
}
unsafe {
(*old_act).sa_handler = sah as *mut c_void;
(*old_act).sa_flags = old_ka.sa_flags;
(*old_act).sa_mask = old_ka.sa_mask;
(*old_act).sa_restorer = old_ka.sa_restorer as *mut c_void;
}
}
return retval as u64;
}
fn do_sigaction(
sig: SignalNumber,
act: Option<&mut sigaction>,
old_act: Option<&mut sigaction>,
) -> i32 {
let pcb = current_pcb();
// 指向当前信号的action的引用
let action =
sigaction::convert_mut(unsafe { &mut (*(pcb.sighand)).action[(sig as usize) - 1] })
.unwrap();
spin_lock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
if (action.sa_flags & SA_FLAG_IMMUTABLE) != 0 {
spin_unlock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
return -(EINVAL as i32);
}
// 如果需要保存原有的sigaction
// 写的这么恶心还得感谢rust的所有权系统...old_act的所有权被传入了这个闭包之后必须要把所有权返回给外面。也许是我不会用才导致写的这么丑但是它确实能跑
let old_act: Option<&mut sigaction> = {
if old_act.is_some() {
let oa = old_act.unwrap();
*(oa) = *action;
Some(oa)
} else {
None
}
};
// 清除所有的脏的sa_flags位也就是清除那些未使用的
let act = {
if act.is_some() {
let ac = act.unwrap();
ac.sa_flags &= SA_ALL_FLAGS;
Some(ac)
} else {
None
}
};
if old_act.is_some() {
old_act.unwrap().sa_flags &= SA_ALL_FLAGS;
}
if act.is_some() {
let ac = act.unwrap();
// 将act.sa_mask的SIGKILL SIGSTOP的屏蔽清除
sigset_delmask(
&mut ac.sa_mask,
sigmask(SignalNumber::SIGKILL) | sigmask(SignalNumber::SIGSTOP),
);
// 将新的sigaction拷贝到进程的action中
*action = *ac;
/*
* POSIX 3.3.1.3
* 1.SIG_IGNpending的信号
*
* 2.SIG_DFLpending的信号
pending的信号忽略
*/
if action.ignored(sig) {
let mut mask: sigset_t = 0;
sigset_clear(&mut mask);
sigset_add(&mut mask, sig);
let sq = pcb.sig_pending.sigqueue as *mut SigQueue;
let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
sq.flush_by_mask(&mask);
// todo: 当有了多个线程后在这里进行操作把每个线程的sigqueue都进行刷新
}
}
spin_unlock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
return 0;
}
/// @brief 对于给定的signal number将u64中对应的位进行置位
pub fn sigmask(sig: SignalNumber) -> u64 {
// 减1的原因是sigset的第0位表示信号1
return 1u64 << ((sig as i32) - 1);
}
#[no_mangle]
pub extern "C" fn sys_rt_sigreturn(regs: &mut pt_regs) -> u64 {
// kdebug!(
// "sigreturn, pid={}, regs.rsp=0x{:018x}",
// current_pcb().pid,
// regs.rsp
// );
let frame = regs.rsp as usize as *mut sigframe;
// 如果当前的rsp不来自用户态则认为产生了错误或被SROP攻击
if unsafe { !verify_area(frame as u64, size_of::<sigframe>() as u64) } {
// todo这里改为生成一个sigsegv
// 退出进程
unsafe {
process_do_exit(SignalNumber::SIGSEGV as u64);
}
}
let mut sigmask: sigset_t = unsafe { (*frame).context.oldmask };
set_current_sig_blocked(&mut sigmask);
// 从用户栈恢复sigcontext
if restore_sigcontext(unsafe { &mut (*frame).context }, regs) == false {
// todo这里改为生成一个sigsegv
// 退出进程
unsafe {
process_do_exit(SignalNumber::SIGSEGV as u64);
}
}
// 由于系统调用的返回值会被系统调用模块被存放在rax寄存器因此为了还原原来的那个系统调用的返回值我们需要在这里返回恢复后的rax的值
return regs.rax;
}
fn set_current_sig_blocked(new_set: &mut sigset_t) {
sigset_delmask(
new_set,
sigmask(SignalNumber::SIGKILL) | sigmask(SignalNumber::SIGSTOP),
);
let mut pcb = current_pcb();
/*
pcb的sig_blocked和新的相等
sig_blocked字段不能被其他进程修改
*/
if sigset_equal(&pcb.sig_blocked, new_set) {
return;
}
let lock: &mut spinlock_t = &mut sighand_struct::convert_mut(pcb.sighand).unwrap().siglock;
spin_lock_irq(lock);
// todo: 当一个进程有多个线程后在这里需要设置每个线程的block字段并且 retarget_shared_pending虽然我还没搞明白linux这部分是干啥的
// 设置当前进程的sig blocked
pcb.sig_blocked = *new_set;
recalc_sigpending();
spin_unlock_irq(lock);
}

View File

@ -6,6 +6,7 @@ use core::fmt::Debug;
use alloc::vec::Vec;
use crate::include::bindings::bindings::NULL;
// todo: 将这里更换为手动编写的ffi绑定
use crate::include::bindings::bindings::atomic_t;
use crate::include::bindings::bindings::pt_regs;
@ -18,8 +19,12 @@ use crate::libs::refcount::RefCount;
/// 请注意sigset_t这个bitmap, 第0位表示sig=1的信号。也就是说SignalNumber-1才是sigset_t中对应的位
pub type sigset_t = u64;
pub type __signalfn_t = ::core::option::Option<unsafe extern "C" fn(arg1: ::core::ffi::c_int)>;
/// 存储信号处理函数的地址(来自用户态)
pub type __signalfn_t = u64;
pub type __sighandler_t = __signalfn_t;
/// 存储信号处理恢复函数的地址(来自用户态)
pub type __sigrestorer_fn_t = u64;
pub type __sigrestorer_t = __sigrestorer_fn_t;
/// 最大的信号数量改动这个值的时候请同步到signal.h)
pub const MAX_SIG_NUM: i32 = 64;
@ -70,14 +75,27 @@ impl core::fmt::Debug for sigaction__union_u {
impl Default for sigaction__union_u {
fn default() -> Self {
Self { _sa_handler: None }
Self {
_sa_handler: NULL as u64,
}
}
}
// ============ sigaction结构体中的的sa_flags的可选值 ===========
pub const SA_FLAG_IGN: u64 = 1u64 << 0; // 当前sigaction表示忽略信号的动作
pub const SA_FLAG_DFL: u64 = 1u64 << 1; // 当前sigaction表示系统默认的动作
// ============ sigaction结构体中的的sa_flags的可选值 begin ===========
pub const SA_FLAG_DFL: u64 = 1u64 << 0; // 当前sigaction表示系统默认的动作
pub const SA_FLAG_IGN: u64 = 1u64 << 1; // 当前sigaction表示忽略信号的动作
pub const SA_FLAG_RESTORER: u64 = 1u64 << 2; // 当前sigaction具有用户指定的restorer
pub const SA_FLAG_IMMUTABLE: u64 = 1u64 << 3; // 当前sigaction不可被更改
/// 所有的sa_flags的mask。用于去除那些不存在的sa_flags位)
pub const SA_ALL_FLAGS: u64 = SA_FLAG_IGN | SA_FLAG_DFL | SA_FLAG_RESTORER | SA_FLAG_IMMUTABLE;
// ============ sigaction结构体中的的sa_flags的可选值 end ===========
/// 用户态程序传入的SIG_DFL的值
pub const USER_SIG_DFL: u64 = 1u64 << 0;
/// 用户态程序传入的SIG_IGN的值
pub const USER_SIG_IGN: u64 = 1u64 << 1;
/**
* @brief
@ -87,9 +105,9 @@ pub const SA_FLAG_RESTORER: u64 = 1u64 << 2; // 当前sigaction具有用户指
pub struct sigaction {
pub _u: sigaction__union_u,
pub sa_flags: u64,
pub sa_mask: sigset_t,
pub sa_mask: sigset_t, // 为了可扩展性而设置的sa_mask
/// 信号处理函数执行结束后将会跳转到这个函数内进行执行然后执行sigreturn系统调用
pub sa_restorer: ::core::option::Option<unsafe extern "C" fn()>,
pub sa_restorer: __sigrestorer_t,
}
impl Default for sigaction {
@ -103,6 +121,30 @@ impl Default for sigaction {
}
}
impl sigaction {
/// @brief 判断这个sigaction是否被忽略
pub fn ignored(&self, _sig: SignalNumber) -> bool {
if (self.sa_flags & SA_FLAG_IGN) != 0 {
return true;
}
// todo: 增加对sa_flags为SA_FLAG_DFL,但是默认处理函数为忽略的情况的判断
return false;
}
}
/// @brief 用户态传入的sigaction结构体符合posix规范
/// 请注意我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
#[repr(C)]
#[derive(Debug)]
pub struct user_sigaction {
pub sa_handler: *mut core::ffi::c_void,
pub sa_sigaction: *mut core::ffi::c_void,
pub sa_mask: sigset_t,
pub sa_flags: u64,
pub sa_restorer: *mut core::ffi::c_void,
}
/**
* sigaction结构体中指向的处理函数
*/
@ -485,6 +527,23 @@ impl SigQueue {
return (filter_result.pop(), still_pending);
}
/// @brief 从sigqueue中删除mask中被置位的信号。也就是说比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
pub fn flush_by_mask(&mut self, mask: &sigset_t) {
// 定义过滤器从sigqueue中删除mask中被置位的信号
let filter = |x: &mut siginfo| {
if sig_is_member(mask, SignalNumber::from(unsafe { x._sinfo.data.si_signo })) {
true
} else {
false
}
};
let filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
// 回收这些siginfo
for x in filter_result {
drop(x)
}
}
}
impl Default for SigQueue {
@ -509,8 +568,8 @@ pub fn sigset_del(set: &mut sigset_t, sig: SignalNumber) {
/// @brief 将指定的信号在sigset中的对应bit进行置位
#[inline]
pub fn sigset_add(set: &mut sigset_t, _sig: SignalNumber) {
*set |= 1 << ((_sig as u32) - 1);
pub fn sigset_add(set: &mut sigset_t, sig: SignalNumber) {
*set |= 1 << ((sig as u32) - 1);
}
/// @brief 将sigset清零
@ -519,6 +578,46 @@ pub fn sigset_clear(set: &mut sigset_t) {
*set = 0;
}
/// @brief 将mask中置为1的位在sigset中清零
#[inline]
pub fn sigset_delmask(set: &mut sigset_t, mask: u64) {
*set &= !mask;
}
/// @brief 判断两个sigset是否相等
#[inline]
pub fn sigset_equal(a: &sigset_t, b: &sigset_t) -> bool {
if _NSIG_U64_CNT == 1{
return *a == *b;
}
return false;
}
/// @brief 使用指定的值初始化sigset为支持将来超过64个signal留下接口
#[inline]
pub fn sigset_init(new_set: &mut sigset_t, mask: u64) {
*new_set = mask;
match _NSIG_U64_CNT {
1 => {}
_ => {
// 暂时不支持大于64个信号
todo!();
}
};
}
/// @brief 判断指定的信号在sigset中的对应位是否被置位
/// @return true: 给定的信号在sigset中被置位
/// @return false: 给定的信号在sigset中没有被置位
#[inline]
pub fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool {
return if 1 & (set >> ((_sig as u32) - 1)) != 0 {
true
} else {
false
};
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct sigframe {
@ -544,7 +643,7 @@ pub struct sigcontext {
pub regs: pt_regs, // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
pub trap_num: u64, // 用来保存线程结构体中的trap_num字段
pub oldmask: u64, // 暂存的执行信号处理函数之前的sigmask
pub oldmask: u64, // 暂存的执行信号处理函数之前的被设置block的信号
pub cr2: u64, // 用来保存线程结构体中的cr2字段
pub err_code: u64, // 用来保存线程结构体中的err_code字段
// todo: 支持x87浮点处理器后在这里增加浮点处理器的状态结构体指针

View File

@ -20,6 +20,8 @@ extern uint64_t sys_mstat(struct pt_regs *regs);
extern uint64_t sys_open(struct pt_regs *regs);
extern uint64_t sys_unlink_at(struct pt_regs *regs);
extern uint64_t sys_kill(struct pt_regs *regs);
extern uint64_t sys_sigaction(struct pt_regs * regs);
extern uint64_t sys_rt_sigreturn(struct pt_regs * regs);
/**
* @brief
@ -586,6 +588,8 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
[21] = sys_mstat,
[22] = sys_unlink_at,
[23] = sys_kill,
[24 ... 254] = system_call_not_exists,
[24] = sys_sigaction,
[25] = sys_rt_sigreturn,
[26 ... 254] = system_call_not_exists,
[255] = sys_ahci_end_req,
};

View File

@ -32,8 +32,10 @@
#define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_PIPE 20 // 创建管道
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用

View File

@ -1,12 +1,12 @@
/**
* @file main.c
* @file main.c
* @author longjin (longjin@RinGoTek.cn)
* @brief signal用的程序
* @version 0.1
* @date 2022-12-06
*
*
* @copyright Copyright (c) 2022
*
*
*/
/**
@ -14,8 +14,8 @@
* 1.DragonOS的控制台输入 exec bin/test_signal.elf &
* , '&',
* 2.kill对应的进程的pid (,:"[1] 生成的pid")
*
*/
*
*/
#include <libc/src/math.h>
#include <libc/src/stdio.h>
@ -23,16 +23,36 @@
#include <libc/src/time.h>
#include <libc/src/unistd.h>
#include <libc/src/include/signal.h>
bool handle_ok = false;
void handler(int sig)
{
printf("handle %d\n", sig);
handle_ok = true;
}
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){
if ((clock() - last) / CLOCKS_PER_SEC >= 1)
{
// printf("Test signal running\n");
last = clock();
}
if (handle_ok)
{
printf("Handle OK!\n");
handle_ok = false;
}
}
return 0;
}

View File

@ -11,6 +11,15 @@ ifeq ($(ARCH), __x86_64__)
libc_sub_dirs += sysdeps/x86_64
endif
libc_objs:= $(shell find ./*.c)
ECHO:
@echo "$@"
$(libc_objs): ECHO
$(CC) $(CFLAGS) -c $@ -o $@.o
clean:
cargo clean
rm -rf $(GARBAGE)
@ -20,7 +29,7 @@ clean:
cd .. ;\
done
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o dirent.o time.o libc_rust
libc: $(libc_objs) libc_rust
@list='$(libc_sub_dirs)'; for subdir in $$list; do \
echo "make all in $$subdir";\
cd $$subdir;\
@ -28,36 +37,6 @@ libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o diren
cd ..;\
done
unistd.o: unistd.c
$(CC) $(CFLAGS) -c unistd.c -o unistd.o
fcntl.o: fcntl.c
$(CC) $(CFLAGS) -c fcntl.c -o fcntl.o
malloc.o: malloc.c
$(CC) $(CFLAGS) -c malloc.c -o malloc.o
errno.o: errno.c
$(CC) $(CFLAGS) -c errno.c -o errno.o
printf.o: printf.c
$(CC) $(CFLAGS) -c printf.c -o printf.o
stdlib.o: stdlib.c
$(CC) $(CFLAGS) -c stdlib.c -o stdlib.o
ctype.o: ctype.c
$(CC) $(CFLAGS) -c ctype.c -o ctype.o
string.o: string.c
$(CC) $(CFLAGS) -c string.c -o string.o
dirent.o: dirent.c
$(CC) $(CFLAGS) -c dirent.c -o dirent.o
time.o: time.c
$(CC) $(CFLAGS) -c time.c -o time.o
libc_rust:
rustup default nightly
cargo +nightly build --release --target ./x86_64-unknown-none.json

View File

@ -1,4 +1,5 @@
#pragma once
#include <libc/src/unistd.h>
#define SIGHUP 1
#define SIGINT 2
@ -37,4 +38,52 @@
/* These should not be considered constants from userland. */
#define SIGRTMIN 32
#define SIGRTMAX MAX_SIG_NUM
#define SIGRTMAX MAX_SIG_NUM
typedef void (*__sighandler_t) (int);
// 注意该结构体最大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; \
}
typedef struct
{
union {
__SIGINFO;
uint64_t padding[4]; // 让siginfo占用32字节大小
};
} siginfo_t;
typedef struct
{
uint64_t set;
} sigset_t;
struct sigaction
{
// sa_handler和sa_sigaction二选1
__sighandler_t sa_handler;
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
uint64_t sa_flags;
void (*sa_restorer)(void);
};
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
int signal(int signum, __sighandler_t handler);

View File

@ -0,0 +1,44 @@
#include <libc/src/include/signal.h>
#include <libc/src/printf.h>
#include <libc/src/stddef.h>
#include <libsystem/syscall.h>
#pragma GCC push_options
#pragma GCC optimize("O0")
void __libc_sa_restorer()
{
// 在这里发起sigreturn,请注意由于内核需要读取到原来的do_signal时保存的栈帧因此这里不能发生函数调用会导致函数压栈只能够这样来完成sigreturn
__asm__ __volatile__("int $0x80 \n\t" ::"a"(SYS_RT_SIGRETURN) : "memory");
}
#pragma GCC pop_options
/**
* @brief
*
* @param signum
* @param handler
* @return int
*/
int signal(int signum, __sighandler_t handler)
{
struct sigaction sa = {0};
sa.sa_handler = handler;
// 由于DragonOS必须由用户程序指定一个sa_restorer因此这里设置为libc的sa_restorer
sa.sa_restorer = &__libc_sa_restorer;
// printf("handler address: %#018lx\n", handler);
// printf("restorer address: %#018lx\n", &__libc_sa_restorer);
sigaction(SIGKILL, &sa, NULL);
}
/**
* @brief
*
* @param signum
* @param act NULL
* @param oldact NULL
* @return int posix
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return syscall_invoke(SYS_SIGACTION, (uint64_t)signum, (uint64_t)act, (uint64_t)oldact, 0, 0, 0, 0, 0);
}

View File

@ -15,20 +15,22 @@
#define SYS_BRK 9
#define SYS_SBRK 10
#define SYS_REBOOT 11 // 重启
#define SYS_CHDIR 12 // 切换工作目录
#define SYS_REBOOT 11 // 重启
#define SYS_CHDIR 12 // 切换工作目录
#define SYS_GET_DENTS 13 // 获取目录中的数据
#define SYS_EXECVE 14 // 执行新的应用程序
#define SYS_WAIT4 15 // 等待进程退出
#define SYS_EXIT 16 // 进程退出
#define SYS_MKDIR 17 // 创建文件夹
#define SYS_EXECVE 14 // 执行新的应用程序
#define SYS_WAIT4 15 // 等待进程退出
#define SYS_EXIT 16 // 进程退出
#define SYS_MKDIR 17 // 创建文件夹
#define SYS_NANOSLEEP 18 // 纳秒级休眠
#define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_PIPE 20
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
/**
* @brief
@ -44,4 +46,5 @@
* @param arg7
* @return long
*/
long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7);
long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4,
uint64_t arg5, uint64_t arg6, uint64_t arg7);