mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-24 04:53:23 +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,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)
|
||||
|
Reference in New Issue
Block a user