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