xref: /DragonOS/kernel/src/process/fork.rs (revision b7b843beddea12cdedda90f6129b7c9980876112)
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, &current_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, &current_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, &current_pcb, &pcb, &current_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         } else {
186             // 如果共享文件描述符表,则直接拷贝指针
187             new_pcb
188                 .basic_mut()
189                 .set_fd_table(current_pcb.basic().fd_table().clone());
190         }
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