feat(wait): 调整内核wait4函数参数类型 (#1175)

* feat:补充wait4的逻辑,添加对进程组的判断

* fix: 修复进程退出码的返回,将正常退出的进程的退出码移动至高8位

* fix: 移除session和processgroup的debug trait

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix: 删除shell.service文件中对于backspace的单独设置

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix: 更新exit函数文档,明确状态码移位规则

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

---------

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
This commit is contained in:
火花 2025-05-24 13:31:20 +08:00 committed by GitHub
parent ae987c6f9a
commit aa394c1f6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 84 additions and 90 deletions

View File

@ -1,26 +1,23 @@
use core::intrinsics::likely;
use alloc::sync::Arc; use alloc::sync::Arc;
use log::warn; use core::intrinsics::likely;
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
arch::ipc::signal::{SigChildCode, Signal}, arch::ipc::signal::{SigChildCode, Signal},
ipc::syscall::PidConverter,
sched::{schedule, SchedMode}, sched::{schedule, SchedMode},
syscall::user_access::UserBufferWriter, syscall::user_access::UserBufferWriter,
time::{sleep::nanosleep, Duration}, time::{sleep::nanosleep, Duration},
}; };
use super::{ use super::{
abi::WaitOption, pid::PidType, resource::RUsage, Pid, ProcessControlBlock, ProcessManager, abi::WaitOption, resource::RUsage, Pid, ProcessControlBlock, ProcessManager, ProcessState,
ProcessState,
}; };
/// 内核wait4时的参数 /// 内核wait4时的参数
#[derive(Debug)] #[derive(Debug)]
pub struct KernelWaitOption<'a> { pub struct KernelWaitOption<'a> {
pub pid_type: PidType, pub pid_converter: PidConverter,
pub pid: Pid,
pub options: WaitOption, pub options: WaitOption,
pub ret_status: i32, pub ret_status: i32,
pub ret_info: Option<WaitIdInfo>, pub ret_info: Option<WaitIdInfo>,
@ -37,10 +34,9 @@ pub struct WaitIdInfo {
} }
impl KernelWaitOption<'_> { impl KernelWaitOption<'_> {
pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self { pub fn new(pid_converter: PidConverter, options: WaitOption) -> Self {
Self { Self {
pid_type, pid_converter,
pid,
options, options,
ret_status: 0, ret_status: 0,
ret_info: None, ret_info: None,
@ -51,36 +47,15 @@ impl KernelWaitOption<'_> {
} }
pub fn kernel_wait4( pub fn kernel_wait4(
mut pid: i64, pid: i32,
wstatus_buf: Option<UserBufferWriter<'_>>, wstatus_buf: Option<UserBufferWriter<'_>>,
options: WaitOption, options: WaitOption,
rusage_buf: Option<&mut RUsage>, rusage_buf: Option<&mut RUsage>,
) -> Result<usize, SystemError> { ) -> Result<usize, SystemError> {
// i64::MIN is not defined let converter = PidConverter::from_id(pid);
if pid == i64::MIN {
return Err(SystemError::ESRCH);
}
// 判断pid类型
let pidtype: PidType;
if pid == -1 {
pidtype = PidType::MAX;
} else if pid < 0 {
pidtype = PidType::PGID;
warn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
pid = -pid;
} else if pid == 0 {
pidtype = PidType::PGID;
warn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
pid = ProcessManager::current_pcb().pid().data() as i64;
} else {
pidtype = PidType::PID;
}
let pid = Pid(pid as usize);
// 构造参数 // 构造参数
let mut kwo = KernelWaitOption::new(pidtype, pid, options); let mut kwo = KernelWaitOption::new(converter, options);
kwo.options.insert(WaitOption::WEXITED); kwo.options.insert(WaitOption::WEXITED);
kwo.ret_rusage = rusage_buf; kwo.ret_rusage = rusage_buf;
@ -131,59 +106,78 @@ fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
'outer: loop { 'outer: loop {
kwo.no_task_error = Some(SystemError::ECHILD); kwo.no_task_error = Some(SystemError::ECHILD);
let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD); match kwo.pid_converter {
PidConverter::Pid(pid) => {
if kwo.pid_type != PidType::MAX && child_pcb.is_err() { let child_pcb = ProcessManager::find(pid)
notask!('outer); .ok_or(SystemError::ECHILD)
} .unwrap();
// 获取weak引用以便于在do_waitpid中能正常drop pcb
if kwo.pid_type == PidType::PID { let child_weak = Arc::downgrade(&child_pcb);
let child_pcb = child_pcb.unwrap(); let r: Option<Result<usize, SystemError>> = do_waitpid(child_pcb, kwo);
// 获取weak引用以便于在do_waitpid中能正常drop pcb if let Some(r) = r {
let child_weak = Arc::downgrade(&child_pcb); retval = r;
let r = do_waitpid(child_pcb, kwo); break 'outer;
if let Some(r) = r { } else if let Err(SystemError::ESRCH) =
retval = r; child_weak.upgrade().unwrap().wait_queue.sleep()
break 'outer; {
} else if let Err(SystemError::ESRCH) = child_weak.upgrade().unwrap().wait_queue.sleep() // log::debug!("do_wait: child_pcb sleep failed");
{ continue;
// log::debug!("do_wait: child_pcb sleep failed");
continue;
}
} else if kwo.pid_type == PidType::MAX {
// 等待任意子进程
// todo: 这里有问题应当让当前进程sleep到自身的child_wait等待队列上这样才高效。还没实现
let current_pcb = ProcessManager::current_pcb();
loop {
let rd_childen = current_pcb.children.read();
if rd_childen.is_empty() {
break;
} }
for pid in rd_childen.iter() { }
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?; PidConverter::All => {
let sched_guard = pcb.sched_info().inner_lock_read_irqsave(); // 等待任意子进程
let state = sched_guard.state(); // todo: 这里有问题应当让当前进程sleep到自身的child_wait等待队列上这样才高效。还没实现
if state.is_exited() { let current_pcb = ProcessManager::current_pcb();
kwo.ret_status = state.exit_code().unwrap() as i32; loop {
kwo.no_task_error = None; let rd_childen = current_pcb.children.read();
// 由于pcb的drop方法里面要获取父进程的children字段的写锁所以这里不能直接drop pcb if rd_childen.is_empty() {
// 而是要先break到外层循环以便释放父进程的children字段的锁,才能drop pcb。 break;
// 否则会死锁。
tmp_child_pcb = Some(pcb.clone());
unsafe { ProcessManager::release(*pid) };
retval = Ok((*pid).into());
break 'outer;
} }
for pid in rd_childen.iter() {
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
let sched_guard = pcb.sched_info().inner_lock_read_irqsave();
let state = sched_guard.state();
if state.is_exited() {
kwo.ret_status = state.exit_code().unwrap() as i32;
kwo.no_task_error = None;
// 由于pcb的drop方法里面要获取父进程的children字段的写锁所以这里不能直接drop pcb
// 而是要先break到外层循环以便释放父进程的children字段的锁,才能drop pcb。
// 否则会死锁。
tmp_child_pcb = Some(pcb.clone());
unsafe { ProcessManager::release(*pid) };
retval = Ok((*pid).into());
break 'outer;
}
}
drop(rd_childen);
nanosleep(Duration::from_millis(100).into())?;
}
}
PidConverter::Pgid(pgid) => {
let pg = ProcessManager::find_process_group(pgid).ok_or(SystemError::ESRCH)?;
loop {
let inner = pg.process_group_inner.lock();
for (_, pcb) in inner.processes.iter() {
let sched_guard = pcb.sched_info().inner_lock_read_irqsave();
let state = sched_guard.state();
if state.is_exited() {
kwo.ret_status = state.exit_code().unwrap() as i32;
kwo.no_task_error = None;
// 由于pcb的drop方法里面要获取父进程的children字段的写锁所以这里不能直接drop pcb
// 而是要先break到外层循环以便释放父进程的children字段的锁,才能drop pcb。
// 否则会死锁。
tmp_child_pcb = Some(pcb.clone());
let pid = pcb.pid();
unsafe { ProcessManager::release(pid) };
retval = Ok((pid).into());
break 'outer;
}
}
drop(inner);
nanosleep(Duration::from_millis(100).into())?;
} }
drop(rd_childen);
nanosleep(Duration::from_millis(100).into())?;
} }
} else {
// todo: 对于pgid的处理
warn!("kernel_wait4: currently not support {:?}", kwo.pid_type);
return Err(SystemError::EINVAL);
} }
notask!('outer); notask!('outer);
} }

View File

@ -404,6 +404,11 @@ impl ProcessManager {
/// ## 参数 /// ## 参数
/// ///
/// - `exit_code` : 进程的退出码 /// - `exit_code` : 进程的退出码
///
/// ## 注意
/// 对于正常退出的进程,状态码应该先左移八位,以便用户态读取的时候正常返回退出码;而对于被信号终止的进程,状态码则是最低七位,无需进行移位操作。
///
/// 因此注意,传入的`exit_code`应该是已经完成了移位操作的
pub fn exit(exit_code: usize) -> ! { pub fn exit(exit_code: usize) -> ! {
// 关中断 // 关中断
let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };

View File

@ -17,14 +17,12 @@ pub type Pgid = Pid;
pub static ALL_PROCESS_GROUP: SpinLock<Option<HashMap<Pgid, Arc<ProcessGroup>>>> = pub static ALL_PROCESS_GROUP: SpinLock<Option<HashMap<Pgid, Arc<ProcessGroup>>>> =
SpinLock::new(None); SpinLock::new(None);
#[derive(Debug)]
pub struct ProcessGroup { pub struct ProcessGroup {
/// 进程组pgid /// 进程组pgid
pub pgid: Pgid, pub pgid: Pgid,
pub process_group_inner: SpinLock<PGInner>, pub process_group_inner: SpinLock<PGInner>,
} }
#[derive(Debug)]
pub struct PGInner { pub struct PGInner {
pub processes: BTreeMap<Pid, Arc<ProcessControlBlock>>, pub processes: BTreeMap<Pid, Arc<ProcessControlBlock>>,
pub leader: Option<Arc<ProcessControlBlock>>, pub leader: Option<Arc<ProcessControlBlock>>,

View File

@ -16,13 +16,11 @@ pub type Sid = Pid;
/// 系统中所有会话 /// 系统中所有会话
pub static ALL_SESSION: SpinLock<Option<HashMap<Sid, Arc<Session>>>> = SpinLock::new(None); pub static ALL_SESSION: SpinLock<Option<HashMap<Sid, Arc<Session>>>> = SpinLock::new(None);
#[derive(Debug)]
pub struct Session { pub struct Session {
pub sid: Sid, pub sid: Sid,
pub session_inner: SpinLock<SessionInner>, pub session_inner: SpinLock<SessionInner>,
} }
#[derive(Debug)]
pub struct SessionInner { pub struct SessionInner {
pub process_groups: BTreeMap<Pgid, Arc<ProcessGroup>>, pub process_groups: BTreeMap<Pgid, Arc<ProcessGroup>>,
pub leader: Option<Arc<ProcessControlBlock>>, pub leader: Option<Arc<ProcessControlBlock>>,

View File

@ -206,7 +206,7 @@ impl Syscall {
} }
pub fn wait4( pub fn wait4(
pid: i64, pid: i32,
wstatus: *mut i32, wstatus: *mut i32,
options: i32, options: i32,
rusage: *mut c_void, rusage: *mut c_void,
@ -248,7 +248,7 @@ impl Syscall {
/// ///
/// - status: 退出状态 /// - status: 退出状态
pub fn exit(status: usize) -> ! { pub fn exit(status: usize) -> ! {
ProcessManager::exit(status); ProcessManager::exit((status & 0xff) << 8);
} }
/// @brief 获取当前进程的pid /// @brief 获取当前进程的pid

View File

@ -295,7 +295,7 @@ impl Syscall {
let rusage = args[3] as *mut c_void; let rusage = args[3] as *mut c_void;
// 权限校验 // 权限校验
// todo: 引入rusage之后更正以下权限校验代码中rusage的大小 // todo: 引入rusage之后更正以下权限校验代码中rusage的大小
Self::wait4(pid.into(), wstatus, options, rusage) Self::wait4(pid, wstatus, options, rusage)
} }
SYS_EXIT => { SYS_EXIT => {

View File

@ -6,6 +6,5 @@ Type=simple
ExecStart=/bin/NovaShell ExecStart=/bin/NovaShell
Restart=always Restart=always
ExecStartPre=-/bin/about.elf ExecStartPre=-/bin/about.elf
ExecStartPre=/bin/busybox stty erase 127
Environment=PATH=/bin:/usr/bin:/usr/local/bin Environment=PATH=/bin:/usr/bin:/usr/local/bin
Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib