1 use core::ffi::c_void; 2 3 use alloc::{string::String, vec::Vec}; 4 5 use super::{fork::CloneFlags, Pid, ProcessManager, ProcessState}; 6 use crate::{ 7 arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch}, 8 exception::InterruptArch, 9 filesystem::vfs::MAX_PATHLEN, 10 process::ProcessControlBlock, 11 syscall::{ 12 user_access::{ 13 check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter, 14 }, 15 Syscall, SystemError, 16 }, 17 }; 18 19 impl Syscall { 20 pub fn fork(frame: &mut TrapFrame) -> Result<usize, SystemError> { 21 let r = ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()); 22 return r; 23 } 24 25 pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> { 26 ProcessManager::fork( 27 frame, 28 CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL, 29 ) 30 .map(|pid| pid.into()) 31 } 32 33 pub fn execve( 34 path: *const u8, 35 argv: *const *const u8, 36 envp: *const *const u8, 37 frame: &mut TrapFrame, 38 ) -> Result<(), SystemError> { 39 // kdebug!( 40 // "execve path: {:?}, argv: {:?}, envp: {:?}\n", 41 // path, 42 // argv, 43 // envp 44 // ); 45 if path.is_null() { 46 return Err(SystemError::EINVAL); 47 } 48 49 let x = || { 50 let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 51 let argv: Vec<String> = check_and_clone_cstr_array(argv)?; 52 let envp: Vec<String> = check_and_clone_cstr_array(envp)?; 53 Ok((path, argv, envp)) 54 }; 55 let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x(); 56 if let Err(e) = r { 57 panic!("Failed to execve: {:?}", e); 58 } 59 let (path, argv, envp) = r.unwrap(); 60 ProcessManager::current_pcb() 61 .basic_mut() 62 .set_name(ProcessControlBlock::generate_name(&path, &argv)); 63 64 return Self::do_execve(path, argv, envp, frame); 65 } 66 67 pub fn wait4( 68 pid: i64, 69 wstatus: *mut i32, 70 options: i32, 71 rusage: *mut c_void, 72 ) -> Result<usize, SystemError> { 73 let mut _rusage_buf = 74 UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?; 75 76 let mut wstatus_buf = 77 UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?; 78 79 // 暂时不支持options选项 80 if options != 0 { 81 return Err(SystemError::EINVAL); 82 } 83 84 let cur_pcb = ProcessManager::current_pcb(); 85 let rd_childen = cur_pcb.children.read(); 86 87 if pid > 0 { 88 let pid = Pid(pid as usize); 89 let child_pcb = rd_childen.get(&pid).ok_or(SystemError::ECHILD)?.clone(); 90 drop(rd_childen); 91 92 // 获取退出码 93 if let ProcessState::Exited(status) = child_pcb.sched_info().state() { 94 if !wstatus.is_null() { 95 wstatus_buf.copy_one_to_user(&status, 0)?; 96 } 97 return Ok(pid.into()); 98 } 99 // 等待指定进程 100 child_pcb.wait_queue.sleep(); 101 } else if pid < -1 { 102 // TODO 判断是否pgid == -pid(等待指定组任意进程) 103 // 暂时不支持 104 return Err(SystemError::EINVAL); 105 } else if pid == 0 { 106 // TODO 判断是否pgid == current_pgid(等待当前组任意进程) 107 // 暂时不支持 108 return Err(SystemError::EINVAL); 109 } else { 110 // 等待任意子进程(这两) 111 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 112 for (pid, pcb) in rd_childen.iter() { 113 if pcb.sched_info().state().is_exited() { 114 if !wstatus.is_null() { 115 wstatus_buf.copy_one_to_user(&0, 0)?; 116 } 117 return Ok(pid.clone().into()); 118 } else { 119 unsafe { pcb.wait_queue.sleep_without_schedule() }; 120 } 121 } 122 drop(irq_guard); 123 sched(); 124 } 125 126 return Ok(0); 127 } 128 129 /// # 退出进程 130 /// 131 /// ## 参数 132 /// 133 /// - status: 退出状态 134 pub fn exit(status: usize) -> ! { 135 ProcessManager::exit(status); 136 } 137 138 /// @brief 获取当前进程的pid 139 pub fn getpid() -> Result<Pid, SystemError> { 140 let current_pcb = ProcessManager::current_pcb(); 141 return Ok(current_pcb.pid()); 142 } 143 144 /// @brief 获取指定进程的pgid 145 /// 146 /// @param pid 指定一个进程号 147 /// 148 /// @return 成功,指定进程的进程组id 149 /// @return 错误,不存在该进程 150 pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> { 151 if pid == Pid(0) { 152 let current_pcb = ProcessManager::current_pcb(); 153 pid = current_pcb.pid(); 154 } 155 let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; 156 return Ok(target_proc.basic().pgid()); 157 } 158 /// @brief 获取当前进程的父进程id 159 160 /// 若为initproc则ppid设置为0 161 pub fn getppid() -> Result<Pid, SystemError> { 162 let current_pcb = ProcessManager::current_pcb(); 163 return Ok(current_pcb.basic().ppid()); 164 } 165 } 166