1 use alloc::{string::ToString, sync::Arc}; 2 3 use crate::{ 4 arch::interrupt::TrapFrame, 5 filesystem::procfs::procfs_register_pid, 6 ipc::signal::flush_signal_handlers, 7 libs::rwlock::RwLock, 8 mm::VirtAddr, 9 process::ProcessFlags, 10 syscall::{user_access::UserBufferWriter, SystemError}, 11 }; 12 13 use super::{ 14 kthread::{KernelThreadPcbPrivate, WorkerPrivate}, 15 KernelStack, Pid, ProcessControlBlock, ProcessManager, 16 }; 17 18 bitflags! { 19 /// 进程克隆标志 20 pub struct CloneFlags: u64 { 21 /// 在进程间共享虚拟内存空间 22 const CLONE_VM = 0x00000100; 23 /// 在进程间共享文件系统信息 24 const CLONE_FS = 0x00000200; 25 /// 共享打开的文件 26 const CLONE_FILES = 0x00000400; 27 /// 克隆时,与父进程共享信号处理结构体 28 const CLONE_SIGHAND = 0x00000800; 29 /// 返回进程的文件描述符 30 const CLONE_PIDFD = 0x00001000; 31 /// 使克隆对象成为父进程的跟踪对象 32 const CLONE_PTRACE = 0x00002000; 33 /// 在执行 exec() 或 _exit() 之前挂起父进程的执行 34 const CLONE_VFORK = 0x00004000; 35 /// 使克隆对象的父进程为调用进程的父进程 36 const CLONE_PARENT = 0x00008000; 37 /// 拷贝线程 38 const CLONE_THREAD = 0x00010000; 39 /// 创建一个新的命名空间,其中包含独立的文件系统挂载点层次结构。 40 const CLONE_NEWNS = 0x00020000; 41 /// 与父进程共享 System V 信号量。 42 const CLONE_SYSVSEM = 0x00040000; 43 /// 设置其线程本地存储 44 const CLONE_SETTLS = 0x00080000; 45 /// 设置partent_tid地址为子进程线程 ID 46 const CLONE_PARENT_SETTID = 0x00100000; 47 /// 在子进程中设置一个清除线程 ID 的用户空间地址 48 const CLONE_CHILD_CLEARTID = 0x00200000; 49 /// 创建一个新线程,将其设置为分离状态 50 const CLONE_DETACHED = 0x00400000; 51 /// 使其在创建者进程或线程视角下成为无法跟踪的。 52 const CLONE_UNTRACED = 0x00800000; 53 /// 设置其子进程线程 ID 54 const CLONE_CHILD_SETTID = 0x01000000; 55 /// 将其放置在一个新的 cgroup 命名空间中 56 const CLONE_NEWCGROUP = 0x02000000; 57 /// 将其放置在一个新的 UTS 命名空间中 58 const CLONE_NEWUTS = 0x04000000; 59 /// 将其放置在一个新的 IPC 命名空间中 60 const CLONE_NEWIPC = 0x08000000; 61 /// 将其放置在一个新的用户命名空间中 62 const CLONE_NEWUSER = 0x10000000; 63 /// 将其放置在一个新的 PID 命名空间中 64 const CLONE_NEWPID = 0x20000000; 65 /// 将其放置在一个新的网络命名空间中 66 const CLONE_NEWNET = 0x40000000; 67 /// 在新的 I/O 上下文中运行它 68 const CLONE_IO = 0x80000000; 69 /// 克隆时,与父进程共享信号结构体 70 const CLONE_SIGNAL = 0x00010000 | 0x00000800; 71 /// 克隆时,将原本被设置为SIG_IGNORE的信号,设置回SIG_DEFAULT 72 const CLONE_CLEAR_SIGHAND = 0x100000000; 73 } 74 } 75 76 /// ## clone与clone3系统调用的参数载体 77 /// 78 /// 因为这两个系统调用的参数很多,所以有这样一个载体更灵活 79 /// 80 /// 仅仅作为参数传递 81 #[derive(Debug, Clone, Copy)] 82 pub struct KernelCloneArgs { 83 pub flags: CloneFlags, 84 85 // 下列属性均来自用户空间 86 pub pidfd: VirtAddr, 87 pub child_tid: VirtAddr, 88 pub parent_tid: VirtAddr, 89 pub set_tid: VirtAddr, 90 91 pub exit_signal: i32, 92 93 pub stack: usize, 94 // clone3用到 95 pub stack_size: usize, 96 pub tls: usize, 97 98 pub set_tid_size: usize, 99 pub cgroup: i32, 100 101 pub io_thread: bool, 102 pub kthread: bool, 103 pub idle: bool, 104 pub func: VirtAddr, 105 pub fn_arg: VirtAddr, 106 // cgrp 和 cset? 107 } 108 109 impl KernelCloneArgs { 110 pub fn new() -> Self { 111 let null_addr = VirtAddr::new(0); 112 Self { 113 flags: unsafe { CloneFlags::from_bits_unchecked(0) }, 114 pidfd: null_addr, 115 child_tid: null_addr, 116 parent_tid: null_addr, 117 set_tid: null_addr, 118 exit_signal: 0, 119 stack: 0, 120 stack_size: 0, 121 tls: 0, 122 set_tid_size: 0, 123 cgroup: 0, 124 io_thread: false, 125 kthread: false, 126 idle: false, 127 func: null_addr, 128 fn_arg: null_addr, 129 } 130 } 131 } 132 133 impl ProcessManager { 134 /// 创建一个新进程 135 /// 136 /// ## 参数 137 /// 138 /// - `current_trapframe`: 当前进程的trapframe 139 /// - `clone_flags`: 进程克隆标志 140 /// 141 /// ## 返回值 142 /// 143 /// - 成功:返回新进程的pid 144 /// - 失败:返回Err(SystemError),fork失败的话,子线程不会执行。 145 /// 146 /// ## Safety 147 /// 148 /// - fork失败的话,子线程不会执行。 149 pub fn fork( 150 current_trapframe: &mut TrapFrame, 151 clone_flags: CloneFlags, 152 ) -> Result<Pid, SystemError> { 153 let current_pcb = ProcessManager::current_pcb(); 154 let new_kstack = KernelStack::new()?; 155 let name = current_pcb.basic().name().to_string(); 156 let pcb = ProcessControlBlock::new(name, new_kstack); 157 158 let mut args = KernelCloneArgs::new(); 159 args.flags = clone_flags; 160 Self::copy_process(¤t_pcb, &pcb, args, current_trapframe)?; 161 162 ProcessManager::add_pcb(pcb.clone()); 163 164 // 向procfs注册进程 165 procfs_register_pid(pcb.pid()).unwrap_or_else(|e| { 166 panic!( 167 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}", 168 pcb.pid(), 169 e 170 ) 171 }); 172 173 ProcessManager::wakeup(&pcb).unwrap_or_else(|e| { 174 panic!( 175 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}", 176 pcb.pid(), 177 e 178 ) 179 }); 180 181 return Ok(pcb.pid()); 182 } 183 184 fn copy_flags( 185 clone_flags: &CloneFlags, 186 new_pcb: &Arc<ProcessControlBlock>, 187 ) -> Result<(), SystemError> { 188 if clone_flags.contains(CloneFlags::CLONE_VM) { 189 new_pcb.flags().insert(ProcessFlags::VFORK); 190 } 191 *new_pcb.flags.lock() = ProcessManager::current_pcb().flags().clone(); 192 return Ok(()); 193 } 194 195 /// 拷贝进程的地址空间 196 /// 197 /// ## 参数 198 /// 199 /// - `clone_vm`: 是否与父进程共享地址空间。true表示共享 200 /// - `new_pcb`: 新进程的pcb 201 /// 202 /// ## 返回值 203 /// 204 /// - 成功:返回Ok(()) 205 /// - 失败:返回Err(SystemError) 206 /// 207 /// ## Panic 208 /// 209 /// - 如果当前进程没有用户地址空间,则panic 210 fn copy_mm( 211 clone_flags: &CloneFlags, 212 current_pcb: &Arc<ProcessControlBlock>, 213 new_pcb: &Arc<ProcessControlBlock>, 214 ) -> Result<(), SystemError> { 215 let old_address_space = current_pcb.basic().user_vm().unwrap_or_else(|| { 216 panic!( 217 "copy_mm: Failed to get address space of current process, current pid: [{:?}]", 218 current_pcb.pid() 219 ) 220 }); 221 222 if clone_flags.contains(CloneFlags::CLONE_VM) { 223 unsafe { new_pcb.basic_mut().set_user_vm(Some(old_address_space)) }; 224 return Ok(()); 225 } 226 let new_address_space = old_address_space.write().try_clone().unwrap_or_else(|e| { 227 panic!( 228 "copy_mm: Failed to clone address space of current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 229 current_pcb.pid(), new_pcb.pid(), e 230 ) 231 }); 232 unsafe { new_pcb.basic_mut().set_user_vm(Some(new_address_space)) }; 233 return Ok(()); 234 } 235 236 fn copy_files( 237 clone_flags: &CloneFlags, 238 current_pcb: &Arc<ProcessControlBlock>, 239 new_pcb: &Arc<ProcessControlBlock>, 240 ) -> Result<(), SystemError> { 241 // 如果不共享文件描述符表,则拷贝文件描述符表 242 if !clone_flags.contains(CloneFlags::CLONE_FILES) { 243 let new_fd_table = current_pcb.basic().fd_table().unwrap().read().clone(); 244 let new_fd_table = Arc::new(RwLock::new(new_fd_table)); 245 new_pcb.basic_mut().set_fd_table(Some(new_fd_table)); 246 } else { 247 // 如果共享文件描述符表,则直接拷贝指针 248 new_pcb 249 .basic_mut() 250 .set_fd_table(current_pcb.basic().fd_table().clone()); 251 } 252 253 return Ok(()); 254 } 255 256 #[allow(dead_code)] 257 fn copy_sighand( 258 clone_flags: &CloneFlags, 259 current_pcb: &Arc<ProcessControlBlock>, 260 new_pcb: &Arc<ProcessControlBlock>, 261 ) -> Result<(), SystemError> { 262 // // 将信号的处理函数设置为default(除了那些被手动屏蔽的) 263 if clone_flags.contains(CloneFlags::CLONE_CLEAR_SIGHAND) { 264 flush_signal_handlers(new_pcb.clone(), false); 265 } 266 267 if clone_flags.contains(CloneFlags::CLONE_SIGHAND) { 268 (*new_pcb.sig_struct()).handlers = current_pcb.sig_struct().handlers.clone(); 269 } 270 return Ok(()); 271 } 272 273 /// 拷贝进程信息 274 /// 275 /// ## panic: 276 /// 某一步拷贝失败时会引发panic 277 /// 例如:copy_mm等失败时会触发panic 278 /// 279 /// ## 参数 280 /// 281 /// - clone_flags 标志位 282 /// - des_pcb 目标pcb 283 /// - src_pcb 拷贝源pcb 284 /// 285 /// ## return 286 /// - 发生错误时返回Err(SystemError) 287 pub fn copy_process( 288 current_pcb: &Arc<ProcessControlBlock>, 289 pcb: &Arc<ProcessControlBlock>, 290 clone_args: KernelCloneArgs, 291 current_trapframe: &mut TrapFrame, 292 ) -> Result<(), SystemError> { 293 let clone_flags = clone_args.flags; 294 // 不允许与不同namespace的进程共享根目录 295 if (clone_flags == (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS)) 296 || clone_flags == (CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_FS) 297 { 298 return Err(SystemError::EINVAL); 299 } 300 301 // 线程组必须共享信号,分离线程只能在线程组内启动。 302 if clone_flags.contains(CloneFlags::CLONE_THREAD) 303 && !clone_flags.contains(CloneFlags::CLONE_SIGHAND) 304 { 305 return Err(SystemError::EINVAL); 306 } 307 308 // 共享信号处理器意味着共享vm。 309 // 线程组也意味着共享vm。阻止这种情况可以简化其他代码。 310 if clone_flags.contains(CloneFlags::CLONE_SIGHAND) 311 && !clone_flags.contains(CloneFlags::CLONE_VM) 312 { 313 return Err(SystemError::EINVAL); 314 } 315 316 // TODO: 处理CLONE_PARENT 与 SIGNAL_UNKILLABLE的情况 317 318 // 如果新进程使用不同的 pid 或 namespace, 319 // 则不允许它与分叉任务共享线程组。 320 if clone_flags.contains(CloneFlags::CLONE_THREAD) { 321 if clone_flags.contains(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWPID) { 322 return Err(SystemError::EINVAL); 323 } 324 // TODO: 判断新进程与当前进程namespace是否相同,不同则返回错误 325 } 326 327 // 如果新进程将处于不同的time namespace, 328 // 则不能让它共享vm或线程组。 329 if clone_flags.contains(CloneFlags::CLONE_THREAD | CloneFlags::CLONE_VM) { 330 // TODO: 判断time namespace,不同则返回错误 331 } 332 333 if clone_flags.contains(CloneFlags::CLONE_PIDFD) 334 && clone_flags.contains(CloneFlags::CLONE_DETACHED | CloneFlags::CLONE_THREAD) 335 { 336 return Err(SystemError::EINVAL); 337 } 338 339 // TODO: 克隆前应该锁信号处理,等待克隆完成后再处理 340 341 // 克隆架构相关 342 *pcb.arch_info() = current_pcb.arch_info_irqsave().clone(); 343 344 // 为内核线程设置WorkerPrivate 345 if current_pcb.flags().contains(ProcessFlags::KTHREAD) { 346 *pcb.worker_private() = 347 Some(WorkerPrivate::KernelThread(KernelThreadPcbPrivate::new())); 348 } 349 350 // 设置clear_child_tid,在线程结束时将其置0以通知父进程 351 if clone_flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) { 352 pcb.thread.write().clear_child_tid = Some(clone_args.child_tid); 353 } 354 355 // 设置child_tid,意味着子线程能够知道自己的id 356 if clone_flags.contains(CloneFlags::CLONE_CHILD_SETTID) { 357 pcb.thread.write().set_child_tid = Some(clone_args.child_tid); 358 } 359 360 // 将子进程/线程的id存储在用户态传进的地址中 361 if clone_flags.contains(CloneFlags::CLONE_PARENT_SETTID) { 362 let mut writer = UserBufferWriter::new( 363 clone_args.parent_tid.data() as *mut i32, 364 core::mem::size_of::<i32>(), 365 true, 366 )?; 367 368 writer.copy_one_to_user(&(pcb.pid().0 as i32), 0)?; 369 } 370 371 // 拷贝标志位 372 Self::copy_flags(&clone_flags, &pcb).unwrap_or_else(|e| { 373 panic!( 374 "fork: Failed to copy flags from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 375 current_pcb.pid(), pcb.pid(), e 376 ) 377 }); 378 379 // 拷贝用户地址空间 380 Self::copy_mm(&clone_flags, ¤t_pcb, &pcb).unwrap_or_else(|e| { 381 panic!( 382 "fork: Failed to copy mm from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 383 current_pcb.pid(), pcb.pid(), e 384 ) 385 }); 386 387 // 拷贝文件描述符表 388 Self::copy_files(&clone_flags, ¤t_pcb, &pcb).unwrap_or_else(|e| { 389 panic!( 390 "fork: Failed to copy files from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 391 current_pcb.pid(), pcb.pid(), e 392 ) 393 }); 394 395 // todo: 拷贝信号相关数据 396 397 // 拷贝线程 398 Self::copy_thread(¤t_pcb, &pcb, clone_args,¤t_trapframe).unwrap_or_else(|e| { 399 panic!( 400 "fork: Failed to copy thread from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 401 current_pcb.pid(), pcb.pid(), e 402 ) 403 }); 404 405 Ok(()) 406 } 407 } 408