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 resource::{RLimit64, RLimitID, RUsage, RUsageWho}, 13 KernelStack, Pid, ProcessManager, ProcessState, 14 }; 15 use crate::{ 16 arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch, MMArch}, 17 exception::InterruptArch, 18 filesystem::{ 19 procfs::procfs_register_pid, 20 vfs::{file::FileDescriptorVec, MAX_PATHLEN}, 21 }, 22 include::bindings::bindings::verify_area, 23 mm::{ucontext::UserStack, MemoryManagementArch, VirtAddr}, 24 process::ProcessControlBlock, 25 sched::completion::Completion, 26 syscall::{ 27 user_access::{ 28 check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter, 29 }, 30 Syscall, SystemError, 31 }, 32 }; 33 34 impl Syscall { 35 pub fn fork(frame: &mut TrapFrame) -> Result<usize, SystemError> { 36 let r = ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()); 37 return r; 38 } 39 40 pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> { 41 ProcessManager::fork( 42 frame, 43 CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL, 44 ) 45 .map(|pid| pid.into()) 46 } 47 48 pub fn execve( 49 path: *const u8, 50 argv: *const *const u8, 51 envp: *const *const u8, 52 frame: &mut TrapFrame, 53 ) -> Result<(), SystemError> { 54 // kdebug!( 55 // "execve path: {:?}, argv: {:?}, envp: {:?}\n", 56 // path, 57 // argv, 58 // envp 59 // ); 60 // kdebug!( 61 // "before execve: strong count: {}", 62 // Arc::strong_count(&ProcessManager::current_pcb()) 63 // ); 64 65 if path.is_null() { 66 return Err(SystemError::EINVAL); 67 } 68 69 let x = || { 70 let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 71 let argv: Vec<String> = check_and_clone_cstr_array(argv)?; 72 let envp: Vec<String> = check_and_clone_cstr_array(envp)?; 73 Ok((path, argv, envp)) 74 }; 75 let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x(); 76 if let Err(e) = r { 77 panic!("Failed to execve: {:?}", e); 78 } 79 let (path, argv, envp) = r.unwrap(); 80 ProcessManager::current_pcb() 81 .basic_mut() 82 .set_name(ProcessControlBlock::generate_name(&path, &argv)); 83 84 Self::do_execve(path, argv, envp, frame)?; 85 86 // 关闭设置了O_CLOEXEC的文件描述符 87 let fd_table = ProcessManager::current_pcb().fd_table(); 88 fd_table.write().close_on_exec(); 89 // kdebug!( 90 // "after execve: strong count: {}", 91 // Arc::strong_count(&ProcessManager::current_pcb()) 92 // ); 93 94 return Ok(()); 95 } 96 97 pub fn wait4( 98 pid: i64, 99 wstatus: *mut i32, 100 options: i32, 101 rusage: *mut c_void, 102 ) -> Result<usize, SystemError> { 103 let ret = WaitOption::from_bits(options as u32); 104 let options = match ret { 105 Some(options) => options, 106 None => { 107 return Err(SystemError::EINVAL); 108 } 109 }; 110 111 let mut _rusage_buf = 112 UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?; 113 114 let mut wstatus_buf = 115 UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?; 116 117 let cur_pcb = ProcessManager::current_pcb(); 118 let rd_childen = cur_pcb.children.read(); 119 120 if pid > 0 { 121 let pid = Pid(pid as usize); 122 let child_pcb = ProcessManager::find(pid).ok_or(SystemError::ECHILD)?; 123 drop(rd_childen); 124 125 loop { 126 let state = child_pcb.sched_info().state(); 127 // 获取退出码 128 match state { 129 ProcessState::Runnable => { 130 if options.contains(WaitOption::WNOHANG) 131 || options.contains(WaitOption::WNOWAIT) 132 { 133 if !wstatus.is_null() { 134 wstatus_buf.copy_one_to_user(&WaitOption::WCONTINUED.bits(), 0)?; 135 } 136 return Ok(0); 137 } 138 } 139 ProcessState::Blocked(_) | ProcessState::Stopped => { 140 // 指定WUNTRACED则等待暂停的进程,不指定则返回0 141 if !options.contains(WaitOption::WUNTRACED) 142 || options.contains(WaitOption::WNOWAIT) 143 { 144 if !wstatus.is_null() { 145 wstatus_buf.copy_one_to_user(&WaitOption::WSTOPPED.bits(), 0)?; 146 } 147 return Ok(0); 148 } 149 } 150 ProcessState::Exited(status) => { 151 // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid); 152 if !wstatus.is_null() { 153 wstatus_buf.copy_one_to_user( 154 &(status as u32 | WaitOption::WEXITED.bits()), 155 0, 156 )?; 157 } 158 drop(child_pcb); 159 // kdebug!("wait4: to release {pid:?}"); 160 unsafe { ProcessManager::release(pid) }; 161 return Ok(pid.into()); 162 } 163 }; 164 165 // 等待指定进程 166 child_pcb.wait_queue.sleep(); 167 } 168 } else if pid < -1 { 169 // TODO 判断是否pgid == -pid(等待指定组任意进程) 170 // 暂时不支持 171 return Err(SystemError::EINVAL); 172 } else if pid == 0 { 173 // TODO 判断是否pgid == current_pgid(等待当前组任意进程) 174 // 暂时不支持 175 return Err(SystemError::EINVAL); 176 } else { 177 // 等待任意子进程(这两) 178 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 179 for pid in rd_childen.iter() { 180 let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?; 181 if pcb.sched_info().state().is_exited() { 182 if !wstatus.is_null() { 183 wstatus_buf.copy_one_to_user(&0, 0)?; 184 } 185 return Ok(pid.clone().into()); 186 } else { 187 unsafe { pcb.wait_queue.sleep_without_schedule() }; 188 } 189 } 190 drop(irq_guard); 191 sched(); 192 } 193 194 return Ok(0); 195 } 196 197 /// # 退出进程 198 /// 199 /// ## 参数 200 /// 201 /// - status: 退出状态 202 pub fn exit(status: usize) -> ! { 203 ProcessManager::exit(status); 204 } 205 206 /// @brief 获取当前进程的pid 207 pub fn getpid() -> Result<Pid, SystemError> { 208 let current_pcb = ProcessManager::current_pcb(); 209 return Ok(current_pcb.tgid()); 210 } 211 212 /// @brief 获取指定进程的pgid 213 /// 214 /// @param pid 指定一个进程号 215 /// 216 /// @return 成功,指定进程的进程组id 217 /// @return 错误,不存在该进程 218 pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> { 219 if pid == Pid(0) { 220 let current_pcb = ProcessManager::current_pcb(); 221 pid = current_pcb.pid(); 222 } 223 let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; 224 return Ok(target_proc.basic().pgid()); 225 } 226 /// @brief 获取当前进程的父进程id 227 228 /// 若为initproc则ppid设置为0 229 pub fn getppid() -> Result<Pid, SystemError> { 230 let current_pcb = ProcessManager::current_pcb(); 231 return Ok(current_pcb.basic().ppid()); 232 } 233 234 pub fn clone( 235 current_trapframe: &mut TrapFrame, 236 clone_args: KernelCloneArgs, 237 ) -> Result<usize, SystemError> { 238 let flags = clone_args.flags; 239 240 let vfork = Arc::new(Completion::new()); 241 242 if flags.contains(CloneFlags::CLONE_PIDFD) 243 && flags.contains(CloneFlags::CLONE_PARENT_SETTID) 244 { 245 return Err(SystemError::EINVAL); 246 } 247 248 let current_pcb = ProcessManager::current_pcb(); 249 let new_kstack = KernelStack::new()?; 250 let name = current_pcb.basic().name().to_string(); 251 let pcb = ProcessControlBlock::new(name, new_kstack); 252 // 克隆pcb 253 ProcessManager::copy_process(¤t_pcb, &pcb, clone_args, current_trapframe)?; 254 ProcessManager::add_pcb(pcb.clone()); 255 256 // 向procfs注册进程 257 procfs_register_pid(pcb.pid()).unwrap_or_else(|e| { 258 panic!( 259 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}", 260 pcb.pid(), 261 e 262 ) 263 }); 264 265 if flags.contains(CloneFlags::CLONE_VFORK) { 266 pcb.thread.write().vfork_done = Some(vfork.clone()); 267 } 268 269 if pcb.thread.read().set_child_tid.is_some() { 270 let addr = pcb.thread.read().set_child_tid.unwrap(); 271 let mut writer = 272 UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?; 273 writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?; 274 } 275 276 ProcessManager::wakeup(&pcb).unwrap_or_else(|e| { 277 panic!( 278 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}", 279 pcb.pid(), 280 e 281 ) 282 }); 283 284 if flags.contains(CloneFlags::CLONE_VFORK) { 285 // 等待子进程结束或者exec; 286 vfork.wait_for_completion_interruptible()?; 287 } 288 289 return Ok(pcb.pid().0); 290 } 291 292 /// 设置线程地址 293 pub fn set_tid_address(ptr: usize) -> Result<usize, SystemError> { 294 if !unsafe { verify_area(ptr as u64, core::mem::size_of::<i32>() as u64) } { 295 return Err(SystemError::EFAULT); 296 } 297 298 let pcb = ProcessManager::current_pcb(); 299 pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr)); 300 Ok(pcb.pid.0) 301 } 302 303 pub fn gettid() -> Result<Pid, SystemError> { 304 let pcb = ProcessManager::current_pcb(); 305 Ok(pcb.pid) 306 } 307 308 pub fn getuid() -> Result<usize, SystemError> { 309 // todo: 增加credit功能之后,需要修改 310 return Ok(0); 311 } 312 313 pub fn getgid() -> Result<usize, SystemError> { 314 // todo: 增加credit功能之后,需要修改 315 return Ok(0); 316 } 317 318 pub fn geteuid() -> Result<usize, SystemError> { 319 // todo: 增加credit功能之后,需要修改 320 return Ok(0); 321 } 322 323 pub fn getegid() -> Result<usize, SystemError> { 324 // todo: 增加credit功能之后,需要修改 325 return Ok(0); 326 } 327 328 pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result<usize, SystemError> { 329 let who = RUsageWho::try_from(who)?; 330 let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::<RUsage>(), true)?; 331 let pcb = ProcessManager::current_pcb(); 332 let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?; 333 334 let ubuf = writer.buffer::<RUsage>(0).unwrap(); 335 ubuf.copy_from_slice(&[rusage]); 336 337 return Ok(0); 338 } 339 340 /// # 设置资源限制 341 /// 342 /// TODO: 目前暂时不支持设置资源限制,只提供读取默认值的功能 343 /// 344 /// ## 参数 345 /// 346 /// - pid: 进程号 347 /// - resource: 资源类型 348 /// - new_limit: 新的资源限制 349 /// - old_limit: 旧的资源限制 350 /// 351 /// ## 返回值 352 /// 353 /// - 成功,0 354 /// - 如果old_limit不为NULL,则返回旧的资源限制到old_limit 355 /// 356 pub fn prlimit64( 357 _pid: Pid, 358 resource: usize, 359 new_limit: *const RLimit64, 360 old_limit: *mut RLimit64, 361 ) -> Result<usize, SystemError> { 362 let resource = RLimitID::try_from(resource)?; 363 let mut writer = None; 364 365 if new_limit.is_null() { 366 return Err(SystemError::EINVAL); 367 } 368 369 if !old_limit.is_null() { 370 writer = Some(UserBufferWriter::new( 371 old_limit, 372 core::mem::size_of::<RLimit64>(), 373 true, 374 )?); 375 } 376 377 let _reader = UserBufferReader::new(new_limit, core::mem::size_of::<RLimit64>(), true)?; 378 379 match resource { 380 RLimitID::Stack => { 381 if let Some(mut writer) = writer { 382 let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0]; 383 rlimit.rlim_cur = UserStack::DEFAULT_USER_STACK_SIZE as u64; 384 rlimit.rlim_max = UserStack::DEFAULT_USER_STACK_SIZE as u64; 385 } 386 return Ok(0); 387 } 388 389 RLimitID::Nofile => { 390 if let Some(mut writer) = writer { 391 let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0]; 392 rlimit.rlim_cur = FileDescriptorVec::PROCESS_MAX_FD as u64; 393 rlimit.rlim_max = FileDescriptorVec::PROCESS_MAX_FD as u64; 394 } 395 return Ok(0); 396 } 397 398 RLimitID::As | RLimitID::Rss => { 399 if let Some(mut writer) = writer { 400 let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0]; 401 rlimit.rlim_cur = MMArch::USER_END_VADDR.data() as u64; 402 rlimit.rlim_max = MMArch::USER_END_VADDR.data() as u64; 403 } 404 return Ok(0); 405 } 406 407 _ => { 408 return Err(SystemError::ENOSYS); 409 } 410 } 411 } 412 } 413