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