1 use alloc::{string::ToString, sync::Arc}; 2 3 use crate::{ 4 arch::interrupt::TrapFrame, filesystem::procfs::procfs_register_pid, libs::rwlock::RwLock, 5 process::ProcessFlags, syscall::SystemError, 6 }; 7 8 use super::{ 9 kthread::{KernelThreadPcbPrivate, WorkerPrivate}, 10 KernelStack, Pid, ProcessControlBlock, ProcessManager, 11 }; 12 13 bitflags! { 14 /// 进程克隆标志 15 pub struct CloneFlags: u32 { 16 /// 在进程间共享文件系统信息 17 const CLONE_FS = (1 << 0); 18 /// 克隆时,与父进程共享信号结构体 19 const CLONE_SIGNAL = (1 << 1); 20 /// 克隆时,与父进程共享信号处理结构体 21 const CLONE_SIGHAND = (1 << 2); 22 /// 克隆时,将原本被设置为SIG_IGNORE的信号,设置回SIG_DEFAULT 23 const CLONE_CLEAR_SIGHAND = (1 << 3); 24 /// 在进程间共享虚拟内存空间 25 const CLONE_VM = (1 << 4); 26 /// 拷贝线程 27 const CLONE_THREAD = (1 << 5); 28 /// 共享打开的文件 29 const CLONE_FILES = (1 << 6); 30 } 31 } 32 33 impl ProcessManager { 34 /// 创建一个新进程 35 /// 36 /// ## 参数 37 /// 38 /// - `current_trapframe`: 当前进程的trapframe 39 /// - `clone_flags`: 进程克隆标志 40 /// 41 /// ## 返回值 42 /// 43 /// - 成功:返回新进程的pid 44 /// - 失败:返回Err(SystemError),fork失败的话,子线程不会执行。 45 /// 46 /// ## Safety 47 /// 48 /// - fork失败的话,子线程不会执行。 49 pub fn fork( 50 current_trapframe: &mut TrapFrame, 51 clone_flags: CloneFlags, 52 ) -> Result<Pid, SystemError> { 53 let current_pcb = ProcessManager::current_pcb(); 54 let new_kstack = KernelStack::new()?; 55 let name = current_pcb.basic().name().to_string(); 56 let pcb = ProcessControlBlock::new(name, new_kstack); 57 58 // 克隆架构相关信息 59 *pcb.arch_info() = current_pcb.arch_info_irqsave().clone(); 60 61 // 为内核线程设置worker private字段。(也许由内核线程机制去做会更好?) 62 if current_pcb.flags().contains(ProcessFlags::KTHREAD) { 63 *pcb.worker_private() = Some(WorkerPrivate::KernelThread(KernelThreadPcbPrivate::new())) 64 } 65 66 // 拷贝标志位 67 ProcessManager::copy_flags(&clone_flags, &pcb).unwrap_or_else(|e| { 68 panic!( 69 "fork: Failed to copy flags from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 70 current_pcb.pid(), pcb.pid(), e 71 ) 72 }); 73 74 // 拷贝用户地址空间 75 ProcessManager::copy_mm(&clone_flags, ¤t_pcb, &pcb).unwrap_or_else(|e| { 76 panic!( 77 "fork: Failed to copy mm from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 78 current_pcb.pid(), pcb.pid(), e 79 ) 80 }); 81 82 // 拷贝文件描述符表 83 ProcessManager::copy_files(&clone_flags, ¤t_pcb, &pcb).unwrap_or_else(|e| { 84 panic!( 85 "fork: Failed to copy files from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 86 current_pcb.pid(), pcb.pid(), e 87 ) 88 }); 89 90 // todo: 拷贝信号相关数据 91 92 // 拷贝线程 93 ProcessManager::copy_thread(&clone_flags, ¤t_pcb, &pcb, ¤t_trapframe).unwrap_or_else(|e| { 94 panic!( 95 "fork: Failed to copy thread from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 96 current_pcb.pid(), pcb.pid(), e 97 ) 98 }); 99 100 ProcessManager::add_pcb(pcb.clone()); 101 102 // 向procfs注册进程 103 procfs_register_pid(pcb.pid()).unwrap_or_else(|e| { 104 panic!( 105 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}", 106 pcb.pid(), 107 e 108 ) 109 }); 110 111 ProcessManager::wakeup(&pcb).unwrap_or_else(|e| { 112 panic!( 113 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}", 114 pcb.pid(), 115 e 116 ) 117 }); 118 119 return Ok(pcb.pid()); 120 } 121 122 fn copy_flags( 123 clone_flags: &CloneFlags, 124 new_pcb: &Arc<ProcessControlBlock>, 125 ) -> Result<(), SystemError> { 126 if clone_flags.contains(CloneFlags::CLONE_VM) { 127 new_pcb.flags().insert(ProcessFlags::VFORK); 128 } 129 *new_pcb.flags.lock() = ProcessManager::current_pcb().flags().clone(); 130 return Ok(()); 131 } 132 133 /// 拷贝进程的地址空间 134 /// 135 /// ## 参数 136 /// 137 /// - `clone_vm`: 是否与父进程共享地址空间。true表示共享 138 /// - `new_pcb`: 新进程的pcb 139 /// 140 /// ## 返回值 141 /// 142 /// - 成功:返回Ok(()) 143 /// - 失败:返回Err(SystemError) 144 /// 145 /// ## Panic 146 /// 147 /// - 如果当前进程没有用户地址空间,则panic 148 fn copy_mm( 149 clone_flags: &CloneFlags, 150 current_pcb: &Arc<ProcessControlBlock>, 151 new_pcb: &Arc<ProcessControlBlock>, 152 ) -> Result<(), SystemError> { 153 let old_address_space = current_pcb.basic().user_vm().unwrap_or_else(|| { 154 panic!( 155 "copy_mm: Failed to get address space of current process, current pid: [{:?}]", 156 current_pcb.pid() 157 ) 158 }); 159 160 if clone_flags.contains(CloneFlags::CLONE_VM) { 161 unsafe { new_pcb.basic_mut().set_user_vm(Some(old_address_space)) }; 162 return Ok(()); 163 } 164 165 let new_address_space = old_address_space.write().try_clone().unwrap_or_else(|e| { 166 panic!( 167 "copy_mm: Failed to clone address space of current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", 168 current_pcb.pid(), new_pcb.pid(), e 169 ) 170 }); 171 unsafe { new_pcb.basic_mut().set_user_vm(Some(new_address_space)) }; 172 return Ok(()); 173 } 174 175 fn copy_files( 176 clone_flags: &CloneFlags, 177 current_pcb: &Arc<ProcessControlBlock>, 178 new_pcb: &Arc<ProcessControlBlock>, 179 ) -> Result<(), SystemError> { 180 // 如果不共享文件描述符表,则拷贝文件描述符表 181 if !clone_flags.contains(CloneFlags::CLONE_FILES) { 182 let new_fd_table = current_pcb.basic().fd_table().unwrap().read().clone(); 183 let new_fd_table = Arc::new(RwLock::new(new_fd_table)); 184 new_pcb.basic_mut().set_fd_table(Some(new_fd_table)); 185 } 186 187 // 如果共享文件描述符表,则直接拷贝指针 188 new_pcb 189 .basic_mut() 190 .set_fd_table(current_pcb.basic().fd_table().clone()); 191 192 return Ok(()); 193 } 194 195 #[allow(dead_code)] 196 fn copy_sighand( 197 _clone_flags: &CloneFlags, 198 _current_pcb: &Arc<ProcessControlBlock>, 199 _new_pcb: &Arc<ProcessControlBlock>, 200 ) -> Result<(), SystemError> { 201 // todo: 由于信号原来写的太烂,移植到新的进程管理的话,需要改动很多。因此决定重写。这里先空着 202 return Ok(()); 203 } 204 } 205