fork.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. use core::{intrinsics::unlikely, sync::atomic::Ordering};
  2. use alloc::{string::ToString, sync::Arc};
  3. use log::error;
  4. use system_error::SystemError;
  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. sched::{sched_cgroup_fork, sched_fork},
  13. smp::core::smp_get_processor_id,
  14. syscall::user_access::UserBufferWriter,
  15. };
  16. use super::{
  17. kthread::{KernelThreadPcbPrivate, WorkerPrivate},
  18. KernelStack, Pid, ProcessControlBlock, ProcessManager,
  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. /// ## clone与clone3系统调用的参数载体
  78. ///
  79. /// 因为这两个系统调用的参数很多,所以有这样一个载体更灵活
  80. ///
  81. /// 仅仅作为参数传递
  82. #[derive(Debug, Clone, Copy)]
  83. #[allow(dead_code)]
  84. pub struct KernelCloneArgs {
  85. pub flags: CloneFlags,
  86. // 下列属性均来自用户空间
  87. pub pidfd: VirtAddr,
  88. pub child_tid: VirtAddr,
  89. pub parent_tid: VirtAddr,
  90. pub set_tid: VirtAddr,
  91. /// 进程退出时发送的信号
  92. pub exit_signal: Signal,
  93. pub stack: usize,
  94. // clone3用到
  95. pub stack_size: usize,
  96. pub tls: usize,
  97. pub set_tid_size: usize,
  98. pub cgroup: i32,
  99. pub io_thread: bool,
  100. pub kthread: bool,
  101. pub idle: bool,
  102. pub func: VirtAddr,
  103. pub fn_arg: VirtAddr,
  104. // cgrp 和 cset?
  105. }
  106. impl KernelCloneArgs {
  107. pub fn new() -> Self {
  108. let null_addr = VirtAddr::new(0);
  109. Self {
  110. flags: unsafe { CloneFlags::from_bits_unchecked(0) },
  111. pidfd: null_addr,
  112. child_tid: null_addr,
  113. parent_tid: null_addr,
  114. set_tid: null_addr,
  115. exit_signal: Signal::SIGCHLD,
  116. stack: 0,
  117. stack_size: 0,
  118. tls: 0,
  119. set_tid_size: 0,
  120. cgroup: 0,
  121. io_thread: false,
  122. kthread: false,
  123. idle: false,
  124. func: null_addr,
  125. fn_arg: null_addr,
  126. }
  127. }
  128. }
  129. impl ProcessManager {
  130. /// 创建一个新进程
  131. ///
  132. /// ## 参数
  133. ///
  134. /// - `current_trapframe`: 当前进程的trapframe
  135. /// - `clone_flags`: 进程克隆标志
  136. ///
  137. /// ## 返回值
  138. ///
  139. /// - 成功:返回新进程的pid
  140. /// - 失败:返回Err(SystemError),fork失败的话,子线程不会执行。
  141. ///
  142. /// ## Safety
  143. ///
  144. /// - fork失败的话,子线程不会执行。
  145. pub fn fork(
  146. current_trapframe: &TrapFrame,
  147. clone_flags: CloneFlags,
  148. ) -> Result<Pid, SystemError> {
  149. let current_pcb = ProcessManager::current_pcb();
  150. let new_kstack: KernelStack = KernelStack::new()?;
  151. let name = current_pcb.basic().name().to_string();
  152. let pcb = ProcessControlBlock::new(name, new_kstack);
  153. pcb.sig_info_mut()
  154. .set_tty(current_pcb.sig_info_irqsave().tty());
  155. let mut args = KernelCloneArgs::new();
  156. args.flags = clone_flags;
  157. args.exit_signal = Signal::SIGCHLD;
  158. Self::copy_process(&current_pcb, &pcb, args, current_trapframe).map_err(|e| {
  159. error!(
  160. "fork: Failed to copy process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  161. current_pcb.pid(),
  162. pcb.pid(),
  163. e
  164. );
  165. e
  166. })?;
  167. ProcessManager::add_pcb(pcb.clone());
  168. // 向procfs注册进程
  169. procfs_register_pid(pcb.pid()).unwrap_or_else(|e| {
  170. panic!(
  171. "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}",
  172. pcb.pid(),
  173. e
  174. )
  175. });
  176. pcb.sched_info().set_on_cpu(Some(smp_get_processor_id()));
  177. ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
  178. panic!(
  179. "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
  180. pcb.pid(),
  181. e
  182. )
  183. });
  184. return Ok(pcb.pid());
  185. }
  186. fn copy_flags(
  187. clone_flags: &CloneFlags,
  188. new_pcb: &Arc<ProcessControlBlock>,
  189. ) -> Result<(), SystemError> {
  190. if clone_flags.contains(CloneFlags::CLONE_VM) {
  191. new_pcb.flags().insert(ProcessFlags::VFORK);
  192. }
  193. *new_pcb.flags.get_mut() = *ProcessManager::current_pcb().flags();
  194. return Ok(());
  195. }
  196. /// 拷贝进程的地址空间
  197. ///
  198. /// ## 参数
  199. ///
  200. /// - `clone_vm`: 是否与父进程共享地址空间。true表示共享
  201. /// - `new_pcb`: 新进程的pcb
  202. ///
  203. /// ## 返回值
  204. ///
  205. /// - 成功:返回Ok(())
  206. /// - 失败:返回Err(SystemError)
  207. ///
  208. /// ## Panic
  209. ///
  210. /// - 如果当前进程没有用户地址空间,则panic
  211. #[inline(never)]
  212. fn copy_mm(
  213. clone_flags: &CloneFlags,
  214. current_pcb: &Arc<ProcessControlBlock>,
  215. new_pcb: &Arc<ProcessControlBlock>,
  216. ) -> Result<(), SystemError> {
  217. let old_address_space = current_pcb.basic().user_vm().unwrap_or_else(|| {
  218. panic!(
  219. "copy_mm: Failed to get address space of current process, current pid: [{:?}]",
  220. current_pcb.pid()
  221. )
  222. });
  223. if clone_flags.contains(CloneFlags::CLONE_VM) {
  224. unsafe { new_pcb.basic_mut().set_user_vm(Some(old_address_space)) };
  225. return Ok(());
  226. }
  227. let new_address_space = old_address_space.write_irqsave().try_clone().unwrap_or_else(|e| {
  228. panic!(
  229. "copy_mm: Failed to clone address space of current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  230. current_pcb.pid(), new_pcb.pid(), e
  231. )
  232. });
  233. unsafe { new_pcb.basic_mut().set_user_vm(Some(new_address_space)) };
  234. return Ok(());
  235. }
  236. #[inline(never)]
  237. fn copy_files(
  238. clone_flags: &CloneFlags,
  239. current_pcb: &Arc<ProcessControlBlock>,
  240. new_pcb: &Arc<ProcessControlBlock>,
  241. ) -> Result<(), SystemError> {
  242. // 如果不共享文件描述符表,则拷贝文件描述符表
  243. if !clone_flags.contains(CloneFlags::CLONE_FILES) {
  244. let new_fd_table = current_pcb.basic().fd_table().unwrap().read().clone();
  245. let new_fd_table = Arc::new(RwLock::new(new_fd_table));
  246. new_pcb.basic_mut().set_fd_table(Some(new_fd_table));
  247. } else {
  248. // 如果共享文件描述符表,则直接拷贝指针
  249. new_pcb
  250. .basic_mut()
  251. .set_fd_table(current_pcb.basic().fd_table().clone());
  252. }
  253. return Ok(());
  254. }
  255. #[allow(dead_code)]
  256. fn copy_sighand(
  257. clone_flags: &CloneFlags,
  258. current_pcb: &Arc<ProcessControlBlock>,
  259. new_pcb: &Arc<ProcessControlBlock>,
  260. ) -> Result<(), SystemError> {
  261. // // 将信号的处理函数设置为default(除了那些被手动屏蔽的)
  262. if clone_flags.contains(CloneFlags::CLONE_CLEAR_SIGHAND) {
  263. flush_signal_handlers(new_pcb.clone(), false);
  264. }
  265. if clone_flags.contains(CloneFlags::CLONE_SIGHAND) {
  266. new_pcb.sig_struct_irqsave().handlers = current_pcb.sig_struct_irqsave().handlers;
  267. }
  268. return Ok(());
  269. }
  270. /// 拷贝进程信息
  271. ///
  272. /// ## panic:
  273. /// 某一步拷贝失败时会引发panic
  274. /// 例如:copy_mm等失败时会触发panic
  275. ///
  276. /// ## 参数
  277. ///
  278. /// - clone_flags 标志位
  279. /// - current_pcb 拷贝源pcb
  280. /// - pcb 目标pcb
  281. ///
  282. /// ## return
  283. /// - 发生错误时返回Err(SystemError)
  284. #[inline(never)]
  285. pub fn copy_process(
  286. current_pcb: &Arc<ProcessControlBlock>,
  287. pcb: &Arc<ProcessControlBlock>,
  288. clone_args: KernelCloneArgs,
  289. current_trapframe: &TrapFrame,
  290. ) -> Result<(), SystemError> {
  291. let clone_flags = clone_args.flags;
  292. // 不允许与不同namespace的进程共享根目录
  293. if (clone_flags == (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS))
  294. || clone_flags == (CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_FS)
  295. {
  296. return Err(SystemError::EINVAL);
  297. }
  298. // 线程组必须共享信号,分离线程只能在线程组内启动。
  299. if clone_flags.contains(CloneFlags::CLONE_THREAD)
  300. && !clone_flags.contains(CloneFlags::CLONE_SIGHAND)
  301. {
  302. return Err(SystemError::EINVAL);
  303. }
  304. // 共享信号处理器意味着共享vm。
  305. // 线程组也意味着共享vm。阻止这种情况可以简化其他代码。
  306. if clone_flags.contains(CloneFlags::CLONE_SIGHAND)
  307. && !clone_flags.contains(CloneFlags::CLONE_VM)
  308. {
  309. return Err(SystemError::EINVAL);
  310. }
  311. // TODO: 处理CLONE_PARENT 与 SIGNAL_UNKILLABLE的情况
  312. // 如果新进程使用不同的 pid 或 namespace,
  313. // 则不允许它与分叉任务共享线程组。
  314. if clone_flags.contains(CloneFlags::CLONE_THREAD)
  315. && clone_flags.contains(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWPID)
  316. {
  317. return Err(SystemError::EINVAL);
  318. // TODO: 判断新进程与当前进程namespace是否相同,不同则返回错误
  319. }
  320. // 如果新进程将处于不同的time namespace,
  321. // 则不能让它共享vm或线程组。
  322. if clone_flags.contains(CloneFlags::CLONE_THREAD | CloneFlags::CLONE_VM) {
  323. // TODO: 判断time namespace,不同则返回错误
  324. }
  325. if clone_flags.contains(CloneFlags::CLONE_PIDFD)
  326. && clone_flags.contains(CloneFlags::CLONE_DETACHED | CloneFlags::CLONE_THREAD)
  327. {
  328. return Err(SystemError::EINVAL);
  329. }
  330. // TODO: 克隆前应该锁信号处理,等待克隆完成后再处理
  331. // 克隆架构相关
  332. let guard = current_pcb.arch_info_irqsave();
  333. unsafe { pcb.arch_info().clone_from(&guard) };
  334. drop(guard);
  335. // 为内核线程设置WorkerPrivate
  336. if current_pcb.flags().contains(ProcessFlags::KTHREAD) {
  337. *pcb.worker_private() =
  338. Some(WorkerPrivate::KernelThread(KernelThreadPcbPrivate::new()));
  339. }
  340. // 设置clear_child_tid,在线程结束时将其置0以通知父进程
  341. if clone_flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) {
  342. pcb.thread.write_irqsave().clear_child_tid = Some(clone_args.child_tid);
  343. }
  344. // 设置child_tid,意味着子线程能够知道自己的id
  345. if clone_flags.contains(CloneFlags::CLONE_CHILD_SETTID) {
  346. pcb.thread.write_irqsave().set_child_tid = Some(clone_args.child_tid);
  347. }
  348. // 将子进程/线程的id存储在用户态传进的地址中
  349. if clone_flags.contains(CloneFlags::CLONE_PARENT_SETTID) {
  350. let mut writer = UserBufferWriter::new(
  351. clone_args.parent_tid.data() as *mut i32,
  352. core::mem::size_of::<i32>(),
  353. true,
  354. )?;
  355. writer.copy_one_to_user(&(pcb.pid().0 as i32), 0)?;
  356. }
  357. sched_fork(pcb).unwrap_or_else(|e| {
  358. panic!(
  359. "fork: Failed to set sched info from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  360. current_pcb.pid(), pcb.pid(), e
  361. )
  362. });
  363. // 拷贝标志位
  364. Self::copy_flags(&clone_flags, pcb).unwrap_or_else(|e| {
  365. panic!(
  366. "fork: Failed to copy flags from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  367. current_pcb.pid(), pcb.pid(), e
  368. )
  369. });
  370. // 拷贝用户地址空间
  371. Self::copy_mm(&clone_flags, current_pcb, pcb).unwrap_or_else(|e| {
  372. panic!(
  373. "fork: Failed to copy mm from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  374. current_pcb.pid(), pcb.pid(), e
  375. )
  376. });
  377. // 拷贝文件描述符表
  378. Self::copy_files(&clone_flags, current_pcb, pcb).unwrap_or_else(|e| {
  379. panic!(
  380. "fork: Failed to copy files from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  381. current_pcb.pid(), pcb.pid(), e
  382. )
  383. });
  384. // 拷贝信号相关数据
  385. Self::copy_sighand(&clone_flags, current_pcb, pcb).unwrap_or_else(|e| {
  386. panic!(
  387. "fork: Failed to copy sighand from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  388. current_pcb.pid(), pcb.pid(), e
  389. )
  390. });
  391. // 拷贝线程
  392. Self::copy_thread(current_pcb, pcb, clone_args,current_trapframe).unwrap_or_else(|e| {
  393. panic!(
  394. "fork: Failed to copy thread from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
  395. current_pcb.pid(), pcb.pid(), e
  396. )
  397. });
  398. // 设置线程组id、组长
  399. if clone_flags.contains(CloneFlags::CLONE_THREAD) {
  400. pcb.thread.write_irqsave().group_leader =
  401. current_pcb.thread.read_irqsave().group_leader.clone();
  402. unsafe {
  403. let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
  404. (*ptr).tgid = current_pcb.tgid;
  405. }
  406. } else {
  407. pcb.thread.write_irqsave().group_leader = Arc::downgrade(pcb);
  408. unsafe {
  409. let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
  410. (*ptr).tgid = pcb.tgid;
  411. }
  412. }
  413. // CLONE_PARENT re-uses the old parent
  414. if clone_flags.contains(CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD) {
  415. *pcb.real_parent_pcb.write_irqsave() =
  416. current_pcb.real_parent_pcb.read_irqsave().clone();
  417. if clone_flags.contains(CloneFlags::CLONE_THREAD) {
  418. pcb.exit_signal.store(Signal::INVALID, Ordering::SeqCst);
  419. } else {
  420. let leader = current_pcb.thread.read_irqsave().group_leader();
  421. if unlikely(leader.is_none()) {
  422. panic!(
  423. "fork: Failed to get leader of current process, current pid: [{:?}]",
  424. current_pcb.pid()
  425. );
  426. }
  427. pcb.exit_signal.store(
  428. leader.unwrap().exit_signal.load(Ordering::SeqCst),
  429. Ordering::SeqCst,
  430. );
  431. }
  432. } else {
  433. // 新创建的进程,设置其父进程为当前进程
  434. *pcb.real_parent_pcb.write_irqsave() = Arc::downgrade(current_pcb);
  435. pcb.exit_signal
  436. .store(clone_args.exit_signal, Ordering::SeqCst);
  437. }
  438. // todo: 增加线程组相关的逻辑。 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/fork.c#2437
  439. sched_cgroup_fork(pcb);
  440. Ok(())
  441. }
  442. }