mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 19:33:26 +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:
@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user