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