1 use core::ffi::c_void; 2 3 use alloc::{ 4 string::{String, ToString}, 5 sync::Arc, 6 vec::Vec, 7 }; 8 9 use super::{ 10 abi::WaitOption, 11 fork::{CloneFlags, KernelCloneArgs}, 12 KernelStack, Pid, ProcessManager, ProcessState, 13 }; 14 use crate::{ 15 arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch}, 16 exception::InterruptArch, 17 filesystem::{procfs::procfs_register_pid, vfs::MAX_PATHLEN}, 18 include::bindings::bindings::verify_area, 19 mm::VirtAddr, 20 process::ProcessControlBlock, 21 sched::completion::Completion, 22 syscall::{ 23 user_access::{ 24 check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter, 25 }, 26 Syscall, SystemError, 27 }, 28 }; 29 30 impl Syscall { 31 pub fn fork(frame: &mut TrapFrame) -> Result<usize, SystemError> { 32 let r = ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()); 33 return r; 34 } 35 36 pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> { 37 ProcessManager::fork( 38 frame, 39 CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL, 40 ) 41 .map(|pid| pid.into()) 42 } 43 44 pub fn execve( 45 path: *const u8, 46 argv: *const *const u8, 47 envp: *const *const u8, 48 frame: &mut TrapFrame, 49 ) -> Result<(), SystemError> { 50 // kdebug!( 51 // "execve path: {:?}, argv: {:?}, envp: {:?}\n", 52 // path, 53 // argv, 54 // envp 55 // ); 56 // kdebug!( 57 // "before execve: strong count: {}", 58 // Arc::strong_count(&ProcessManager::current_pcb()) 59 // ); 60 61 if path.is_null() { 62 return Err(SystemError::EINVAL); 63 } 64 65 let x = || { 66 let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 67 let argv: Vec<String> = check_and_clone_cstr_array(argv)?; 68 let envp: Vec<String> = check_and_clone_cstr_array(envp)?; 69 Ok((path, argv, envp)) 70 }; 71 let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x(); 72 if let Err(e) = r { 73 panic!("Failed to execve: {:?}", e); 74 } 75 let (path, argv, envp) = r.unwrap(); 76 ProcessManager::current_pcb() 77 .basic_mut() 78 .set_name(ProcessControlBlock::generate_name(&path, &argv)); 79 80 Self::do_execve(path, argv, envp, frame)?; 81 82 // 关闭设置了O_CLOEXEC的文件描述符 83 let fd_table = ProcessManager::current_pcb().fd_table(); 84 fd_table.write().close_on_exec(); 85 // kdebug!( 86 // "after execve: strong count: {}", 87 // Arc::strong_count(&ProcessManager::current_pcb()) 88 // ); 89 90 return Ok(()); 91 } 92 93 pub fn wait4( 94 pid: i64, 95 wstatus: *mut i32, 96 options: i32, 97 rusage: *mut c_void, 98 ) -> Result<usize, SystemError> { 99 let ret = WaitOption::from_bits(options as u32); 100 let options = match ret { 101 Some(options) => options, 102 None => { 103 return Err(SystemError::EINVAL); 104 } 105 }; 106 107 let mut _rusage_buf = 108 UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?; 109 110 let mut wstatus_buf = 111 UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?; 112 113 let cur_pcb = ProcessManager::current_pcb(); 114 let rd_childen = cur_pcb.children.read(); 115 116 if pid > 0 { 117 let pid = Pid(pid as usize); 118 let child_pcb = ProcessManager::find(pid).ok_or(SystemError::ECHILD)?; 119 drop(rd_childen); 120 121 loop { 122 let state = child_pcb.sched_info().state(); 123 // 获取退出码 124 match state { 125 ProcessState::Runnable => { 126 if options.contains(WaitOption::WNOHANG) 127 || options.contains(WaitOption::WNOWAIT) 128 { 129 if !wstatus.is_null() { 130 wstatus_buf.copy_one_to_user(&WaitOption::WCONTINUED.bits(), 0)?; 131 } 132 return Ok(0); 133 } 134 } 135 ProcessState::Blocked(_) | ProcessState::Stopped => { 136 // 指定WUNTRACED则等待暂停的进程,不指定则返回0 137 if !options.contains(WaitOption::WUNTRACED) 138 || options.contains(WaitOption::WNOWAIT) 139 { 140 if !wstatus.is_null() { 141 wstatus_buf.copy_one_to_user(&WaitOption::WSTOPPED.bits(), 0)?; 142 } 143 return Ok(0); 144 } 145 } 146 ProcessState::Exited(status) => { 147 // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid); 148 if !wstatus.is_null() { 149 wstatus_buf.copy_one_to_user( 150 &(status as u32 | WaitOption::WEXITED.bits()), 151 0, 152 )?; 153 } 154 drop(child_pcb); 155 // kdebug!("wait4: to release {pid:?}"); 156 unsafe { ProcessManager::release(pid) }; 157 return Ok(pid.into()); 158 } 159 }; 160 161 // 等待指定进程 162 child_pcb.wait_queue.sleep(); 163 } 164 } else if pid < -1 { 165 // TODO 判断是否pgid == -pid(等待指定组任意进程) 166 // 暂时不支持 167 return Err(SystemError::EINVAL); 168 } else if pid == 0 { 169 // TODO 判断是否pgid == current_pgid(等待当前组任意进程) 170 // 暂时不支持 171 return Err(SystemError::EINVAL); 172 } else { 173 // 等待任意子进程(这两) 174 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 175 for pid in rd_childen.iter() { 176 let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?; 177 if pcb.sched_info().state().is_exited() { 178 if !wstatus.is_null() { 179 wstatus_buf.copy_one_to_user(&0, 0)?; 180 } 181 return Ok(pid.clone().into()); 182 } else { 183 unsafe { pcb.wait_queue.sleep_without_schedule() }; 184 } 185 } 186 drop(irq_guard); 187 sched(); 188 } 189 190 return Ok(0); 191 } 192 193 /// # 退出进程 194 /// 195 /// ## 参数 196 /// 197 /// - status: 退出状态 198 pub fn exit(status: usize) -> ! { 199 ProcessManager::exit(status); 200 } 201 202 /// @brief 获取当前进程的pid 203 pub fn getpid() -> Result<Pid, SystemError> { 204 let current_pcb = ProcessManager::current_pcb(); 205 return Ok(current_pcb.tgid()); 206 } 207 208 /// @brief 获取指定进程的pgid 209 /// 210 /// @param pid 指定一个进程号 211 /// 212 /// @return 成功,指定进程的进程组id 213 /// @return 错误,不存在该进程 214 pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> { 215 if pid == Pid(0) { 216 let current_pcb = ProcessManager::current_pcb(); 217 pid = current_pcb.pid(); 218 } 219 let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; 220 return Ok(target_proc.basic().pgid()); 221 } 222 /// @brief 获取当前进程的父进程id 223 224 /// 若为initproc则ppid设置为0 225 pub fn getppid() -> Result<Pid, SystemError> { 226 let current_pcb = ProcessManager::current_pcb(); 227 return Ok(current_pcb.basic().ppid()); 228 } 229 230 pub fn clone( 231 current_trapframe: &mut TrapFrame, 232 clone_args: KernelCloneArgs, 233 ) -> Result<usize, SystemError> { 234 let flags = clone_args.flags; 235 236 let vfork = Arc::new(Completion::new()); 237 238 if flags.contains(CloneFlags::CLONE_PIDFD) 239 && flags.contains(CloneFlags::CLONE_PARENT_SETTID) 240 { 241 return Err(SystemError::EINVAL); 242 } 243 244 let current_pcb = ProcessManager::current_pcb(); 245 let new_kstack = KernelStack::new()?; 246 let name = current_pcb.basic().name().to_string(); 247 let pcb = ProcessControlBlock::new(name, new_kstack); 248 // 克隆pcb 249 ProcessManager::copy_process(¤t_pcb, &pcb, clone_args, current_trapframe)?; 250 ProcessManager::add_pcb(pcb.clone()); 251 252 // 向procfs注册进程 253 procfs_register_pid(pcb.pid()).unwrap_or_else(|e| { 254 panic!( 255 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}", 256 pcb.pid(), 257 e 258 ) 259 }); 260 261 if flags.contains(CloneFlags::CLONE_VFORK) { 262 pcb.thread.write().vfork_done = Some(vfork.clone()); 263 } 264 265 if pcb.thread.read().set_child_tid.is_some() { 266 let addr = pcb.thread.read().set_child_tid.unwrap(); 267 let mut writer = 268 UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?; 269 writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?; 270 } 271 272 ProcessManager::wakeup(&pcb).unwrap_or_else(|e| { 273 panic!( 274 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}", 275 pcb.pid(), 276 e 277 ) 278 }); 279 280 if flags.contains(CloneFlags::CLONE_VFORK) { 281 // 等待子进程结束或者exec; 282 vfork.wait_for_completion_interruptible()?; 283 } 284 285 return Ok(pcb.pid().0); 286 } 287 288 /// 设置线程地址 289 pub fn set_tid_address(ptr: usize) -> Result<usize, SystemError> { 290 if !unsafe { verify_area(ptr as u64, core::mem::size_of::<i32>() as u64) } { 291 return Err(SystemError::EFAULT); 292 } 293 294 let pcb = ProcessManager::current_pcb(); 295 pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr)); 296 Ok(pcb.pid.0) 297 } 298 299 pub fn gettid() -> Result<Pid, SystemError> { 300 let pcb = ProcessManager::current_pcb(); 301 Ok(pcb.pid) 302 } 303 304 pub fn getuid() -> Result<usize, SystemError> { 305 // todo: 增加credit功能之后,需要修改 306 return Ok(0); 307 } 308 309 pub fn getgid() -> Result<usize, SystemError> { 310 // todo: 增加credit功能之后,需要修改 311 return Ok(0); 312 } 313 314 pub fn geteuid() -> Result<usize, SystemError> { 315 // todo: 增加credit功能之后,需要修改 316 return Ok(0); 317 } 318 319 pub fn getegid() -> Result<usize, SystemError> { 320 // todo: 增加credit功能之后,需要修改 321 return Ok(0); 322 } 323 } 324