diff --git a/kernel/src/process/exit.rs b/kernel/src/process/exit.rs index e2382328..cee1ce1f 100644 --- a/kernel/src/process/exit.rs +++ b/kernel/src/process/exit.rs @@ -1,26 +1,23 @@ -use core::intrinsics::likely; - use alloc::sync::Arc; -use log::warn; +use core::intrinsics::likely; use system_error::SystemError; use crate::{ arch::ipc::signal::{SigChildCode, Signal}, + ipc::syscall::PidConverter, sched::{schedule, SchedMode}, syscall::user_access::UserBufferWriter, time::{sleep::nanosleep, Duration}, }; use super::{ - abi::WaitOption, pid::PidType, resource::RUsage, Pid, ProcessControlBlock, ProcessManager, - ProcessState, + abi::WaitOption, resource::RUsage, Pid, ProcessControlBlock, ProcessManager, ProcessState, }; /// 内核wait4时的参数 #[derive(Debug)] pub struct KernelWaitOption<'a> { - pub pid_type: PidType, - pub pid: Pid, + pub pid_converter: PidConverter, pub options: WaitOption, pub ret_status: i32, pub ret_info: Option, @@ -37,10 +34,9 @@ pub struct WaitIdInfo { } impl KernelWaitOption<'_> { - pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self { + pub fn new(pid_converter: PidConverter, options: WaitOption) -> Self { Self { - pid_type, - pid, + pid_converter, options, ret_status: 0, ret_info: None, @@ -51,36 +47,15 @@ impl KernelWaitOption<'_> { } pub fn kernel_wait4( - mut pid: i64, + pid: i32, wstatus_buf: Option>, options: WaitOption, rusage_buf: Option<&mut RUsage>, ) -> Result { - // i64::MIN is not defined - 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 converter = PidConverter::from_id(pid); // 构造参数 - let mut kwo = KernelWaitOption::new(pidtype, pid, options); + let mut kwo = KernelWaitOption::new(converter, options); kwo.options.insert(WaitOption::WEXITED); kwo.ret_rusage = rusage_buf; @@ -131,59 +106,78 @@ fn do_wait(kwo: &mut KernelWaitOption) -> Result { 'outer: loop { kwo.no_task_error = Some(SystemError::ECHILD); - let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD); - - if kwo.pid_type != PidType::MAX && child_pcb.is_err() { - notask!('outer); - } - - if kwo.pid_type == PidType::PID { - let child_pcb = child_pcb.unwrap(); - // 获取weak引用,以便于在do_waitpid中能正常drop pcb - let child_weak = Arc::downgrade(&child_pcb); - let r = do_waitpid(child_pcb, kwo); - if let Some(r) = r { - retval = r; - break 'outer; - } else if let Err(SystemError::ESRCH) = child_weak.upgrade().unwrap().wait_queue.sleep() - { - // 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; + match kwo.pid_converter { + PidConverter::Pid(pid) => { + let child_pcb = ProcessManager::find(pid) + .ok_or(SystemError::ECHILD) + .unwrap(); + // 获取weak引用,以便于在do_waitpid中能正常drop pcb + let child_weak = Arc::downgrade(&child_pcb); + let r: Option> = do_waitpid(child_pcb, kwo); + if let Some(r) = r { + retval = r; + break 'outer; + } else if let Err(SystemError::ESRCH) = + child_weak.upgrade().unwrap().wait_queue.sleep() + { + // log::debug!("do_wait: child_pcb sleep failed"); + continue; } - 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; + } + PidConverter::All => { + // 等待任意子进程 + // 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)?; + 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); } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 1aa904dd..2e4b6de2 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -404,6 +404,11 @@ impl ProcessManager { /// ## 参数 /// /// - `exit_code` : 进程的退出码 + /// + /// ## 注意 + /// 对于正常退出的进程,状态码应该先左移八位,以便用户态读取的时候正常返回退出码;而对于被信号终止的进程,状态码则是最低七位,无需进行移位操作。 + /// + /// 因此注意,传入的`exit_code`应该是已经完成了移位操作的 pub fn exit(exit_code: usize) -> ! { // 关中断 let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; diff --git a/kernel/src/process/process_group.rs b/kernel/src/process/process_group.rs index 751c8ec4..313285b0 100644 --- a/kernel/src/process/process_group.rs +++ b/kernel/src/process/process_group.rs @@ -17,14 +17,12 @@ pub type Pgid = Pid; pub static ALL_PROCESS_GROUP: SpinLock>>> = SpinLock::new(None); -#[derive(Debug)] pub struct ProcessGroup { /// 进程组pgid pub pgid: Pgid, pub process_group_inner: SpinLock, } -#[derive(Debug)] pub struct PGInner { pub processes: BTreeMap>, pub leader: Option>, diff --git a/kernel/src/process/session.rs b/kernel/src/process/session.rs index 45ac06b4..3aeeb6b0 100644 --- a/kernel/src/process/session.rs +++ b/kernel/src/process/session.rs @@ -16,13 +16,11 @@ pub type Sid = Pid; /// 系统中所有会话 pub static ALL_SESSION: SpinLock>>> = SpinLock::new(None); -#[derive(Debug)] pub struct Session { pub sid: Sid, pub session_inner: SpinLock, } -#[derive(Debug)] pub struct SessionInner { pub process_groups: BTreeMap>, pub leader: Option>, diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index 2276113a..1d95c86b 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -206,7 +206,7 @@ impl Syscall { } pub fn wait4( - pid: i64, + pid: i32, wstatus: *mut i32, options: i32, rusage: *mut c_void, @@ -248,7 +248,7 @@ impl Syscall { /// /// - status: 退出状态 pub fn exit(status: usize) -> ! { - ProcessManager::exit(status); + ProcessManager::exit((status & 0xff) << 8); } /// @brief 获取当前进程的pid diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 730c58a4..079c60c9 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -295,7 +295,7 @@ impl Syscall { let rusage = args[3] as *mut c_void; // 权限校验 // todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小 - Self::wait4(pid.into(), wstatus, options, rusage) + Self::wait4(pid, wstatus, options, rusage) } SYS_EXIT => { diff --git a/user/sysconfig/etc/reach/system/shell.service b/user/sysconfig/etc/reach/system/shell.service index 942924e2..94adc314 100644 --- a/user/sysconfig/etc/reach/system/shell.service +++ b/user/sysconfig/etc/reach/system/shell.service @@ -6,6 +6,5 @@ Type=simple ExecStart=/bin/NovaShell Restart=always ExecStartPre=-/bin/about.elf -ExecStartPre=/bin/busybox stty erase 127 Environment=PATH=/bin:/usr/bin:/usr/local/bin Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib