sys_clone.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. use crate::arch::interrupt::TrapFrame;
  2. use crate::arch::syscall::nr::SYS_CLONE;
  3. use crate::filesystem::procfs::procfs_register_pid;
  4. use crate::mm::{verify_area, VirtAddr};
  5. use crate::process::fork::{CloneFlags, KernelCloneArgs};
  6. use crate::process::{KernelStack, ProcessControlBlock, ProcessManager};
  7. use crate::sched::completion::Completion;
  8. use crate::syscall::table::{FormattedSyscallParam, Syscall};
  9. use crate::syscall::user_access::UserBufferWriter;
  10. use alloc::vec::Vec;
  11. use alloc::{string::ToString, sync::Arc};
  12. use system_error::SystemError;
  13. pub struct SysClone;
  14. impl SysClone {
  15. fn parent_tid(args: &[usize]) -> VirtAddr {
  16. VirtAddr::new(args[2])
  17. }
  18. fn child_tid(args: &[usize]) -> VirtAddr {
  19. VirtAddr::new(args[3])
  20. }
  21. fn flags(args: &[usize]) -> CloneFlags {
  22. CloneFlags::from_bits_truncate(args[0] as u64)
  23. }
  24. fn stack(args: &[usize]) -> usize {
  25. args[1]
  26. }
  27. fn tls(args: &[usize]) -> usize {
  28. args[4]
  29. }
  30. }
  31. impl Syscall for SysClone {
  32. fn num_args(&self) -> usize {
  33. 5
  34. }
  35. fn handle(&self, args: &[usize], frame: &mut TrapFrame) -> Result<usize, SystemError> {
  36. let parent_tid = Self::parent_tid(args);
  37. let child_tid = Self::child_tid(args);
  38. // 地址校验
  39. verify_area(parent_tid, core::mem::size_of::<i32>())?;
  40. verify_area(child_tid, core::mem::size_of::<i32>())?;
  41. let flags = Self::flags(args);
  42. let stack = Self::stack(args);
  43. let tls = Self::tls(args);
  44. let mut clone_args = KernelCloneArgs::new();
  45. clone_args.flags = flags;
  46. clone_args.stack = stack;
  47. clone_args.parent_tid = parent_tid;
  48. clone_args.child_tid = child_tid;
  49. clone_args.tls = tls;
  50. let vfork = Arc::new(Completion::new());
  51. if flags.contains(CloneFlags::CLONE_PIDFD)
  52. && flags.contains(CloneFlags::CLONE_PARENT_SETTID)
  53. {
  54. return Err(SystemError::EINVAL);
  55. }
  56. let current_pcb = ProcessManager::current_pcb();
  57. let new_kstack = KernelStack::new()?;
  58. let name = current_pcb.basic().name().to_string();
  59. let pcb = ProcessControlBlock::new(name, new_kstack);
  60. // 克隆pcb
  61. ProcessManager::copy_process(&current_pcb, &pcb, clone_args, frame)?;
  62. // 向procfs注册进程
  63. procfs_register_pid(pcb.pid()).unwrap_or_else(|e| {
  64. panic!(
  65. "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}",
  66. pcb.pid(),
  67. e
  68. )
  69. });
  70. if flags.contains(CloneFlags::CLONE_VFORK) {
  71. pcb.thread.write_irqsave().vfork_done = Some(vfork.clone());
  72. }
  73. if pcb.thread.read_irqsave().set_child_tid.is_some() {
  74. let addr = pcb.thread.read_irqsave().set_child_tid.unwrap();
  75. let mut writer =
  76. UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
  77. writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?;
  78. }
  79. ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
  80. panic!(
  81. "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
  82. pcb.pid(),
  83. e
  84. )
  85. });
  86. if flags.contains(CloneFlags::CLONE_VFORK) {
  87. // 等待子进程结束或者exec;
  88. vfork.wait_for_completion_interruptible()?;
  89. }
  90. return Ok(pcb.pid().0);
  91. }
  92. fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
  93. vec![
  94. FormattedSyscallParam::new(
  95. "parent_tid",
  96. format!("{:#x}", Self::parent_tid(args).data()),
  97. ),
  98. FormattedSyscallParam::new("child_tid", format!("{:#x}", Self::child_tid(args).data())),
  99. FormattedSyscallParam::new("flags", format!("{:#x}", Self::flags(args))),
  100. FormattedSyscallParam::new("stack", format!("{:#x}", Self::stack(args))),
  101. FormattedSyscallParam::new("tls", format!("{:#x}", Self::tls(args))),
  102. ]
  103. }
  104. }
  105. syscall_table_macros::declare_syscall!(SYS_CLONE, SysClone);