Эх сурвалжийг харах

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>
火花 3 долоо хоног өмнө
parent
commit
aa394c1f6f

+ 75 - 81
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<WaitIdInfo>,
@@ -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<UserBufferWriter<'_>>,
     options: WaitOption,
     rusage_buf: Option<&mut RUsage>,
 ) -> Result<usize, SystemError> {
-    // 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<usize, SystemError> {
 
     '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;
+        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<Result<usize, SystemError>> = 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;
+            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())?;
                 }
-                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::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);
     }
 

+ 5 - 0
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() };

+ 0 - 2
kernel/src/process/process_group.rs

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

+ 0 - 2
kernel/src/process/session.rs

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

+ 2 - 2
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

+ 1 - 1
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 => {

+ 0 - 1
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