diff --git a/kernel/src/arch/x86_64/ipc/signal.rs b/kernel/src/arch/x86_64/ipc/signal.rs index aebfc489..960ae1b1 100644 --- a/kernel/src/arch/x86_64/ipc/signal.rs +++ b/kernel/src/arch/x86_64/ipc/signal.rs @@ -24,9 +24,10 @@ pub const STACK_ALIGN: u64 = 16; /// 信号最大值 pub const MAX_SIG_NUM: usize = 64; #[allow(dead_code)] -#[derive(Debug, Clone, Copy, Eq)] +#[derive(Eq)] #[repr(usize)] #[allow(non_camel_case_types)] +#[atomic_enum] pub enum Signal { INVALID = 0, SIGHUP = 1, diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 5e199b72..f980a436 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -57,6 +57,8 @@ mod virt; #[macro_use] extern crate alloc; #[macro_use] +extern crate atomic_enum; +#[macro_use] extern crate bitflags; extern crate elf; #[macro_use] diff --git a/kernel/src/net/mod.rs b/kernel/src/net/mod.rs index b8e71107..be91217d 100644 --- a/kernel/src/net/mod.rs +++ b/kernel/src/net/mod.rs @@ -197,7 +197,7 @@ pub trait Socket: Sync + Send + Debug { _optval: &[u8], ) -> Result<(), SystemError> { kwarn!("setsockopt is not implemented"); - return Err(SystemError::ENOSYS); + return Ok(()); } } diff --git a/kernel/src/process/fork.rs b/kernel/src/process/fork.rs index c9b17d88..6860640c 100644 --- a/kernel/src/process/fork.rs +++ b/kernel/src/process/fork.rs @@ -1,7 +1,9 @@ +use core::{intrinsics::unlikely, sync::atomic::Ordering}; + use alloc::{string::ToString, sync::Arc}; use crate::{ - arch::interrupt::TrapFrame, + arch::{interrupt::TrapFrame, ipc::signal::Signal}, filesystem::procfs::procfs_register_pid, ipc::signal::flush_signal_handlers, libs::rwlock::RwLock, @@ -88,7 +90,8 @@ pub struct KernelCloneArgs { pub parent_tid: VirtAddr, pub set_tid: VirtAddr, - pub exit_signal: i32, + /// 进程退出时发送的信号 + pub exit_signal: Signal, pub stack: usize, // clone3用到 @@ -115,7 +118,7 @@ impl KernelCloneArgs { child_tid: null_addr, parent_tid: null_addr, set_tid: null_addr, - exit_signal: 0, + exit_signal: Signal::SIGCHLD, stack: 0, stack_size: 0, tls: 0, @@ -157,6 +160,8 @@ impl ProcessManager { let mut args = KernelCloneArgs::new(); args.flags = clone_flags; + args.exit_signal = Signal::SIGCHLD; + Self::copy_process(¤t_pcb, &pcb, args, current_trapframe)?; ProcessManager::add_pcb(pcb.clone()); @@ -394,7 +399,13 @@ impl ProcessManager { ) }); - // todo: 拷贝信号相关数据 + // 拷贝信号相关数据 + Self::copy_sighand(&clone_flags, ¤t_pcb, &pcb).map_err(|e| { + panic!( + "fork: Failed to copy sighand from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", + current_pcb.pid(), pcb.pid(), e + ) + })?; // 拷贝线程 Self::copy_thread(¤t_pcb, &pcb, clone_args,¤t_trapframe).unwrap_or_else(|e| { @@ -404,6 +415,50 @@ impl ProcessManager { ) }); + // 设置线程组id、组长 + if clone_flags.contains(CloneFlags::CLONE_THREAD) { + pcb.thread.write().group_leader = current_pcb.thread.read().group_leader.clone(); + unsafe { + let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock; + (*ptr).tgid = current_pcb.tgid; + } + } else { + pcb.thread.write().group_leader = Arc::downgrade(&pcb); + unsafe { + let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock; + (*ptr).tgid = pcb.tgid; + } + } + + // CLONE_PARENT re-uses the old parent + if clone_flags.contains(CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD) { + *pcb.real_parent_pcb.write() = current_pcb.real_parent_pcb.read().clone(); + + if clone_flags.contains(CloneFlags::CLONE_THREAD) { + pcb.exit_signal.store(Signal::INVALID, Ordering::SeqCst); + } else { + let leader = current_pcb.thread.read().group_leader(); + if unlikely(leader.is_none()) { + panic!( + "fork: Failed to get leader of current process, current pid: [{:?}]", + current_pcb.pid() + ); + } + + pcb.exit_signal.store( + leader.unwrap().exit_signal.load(Ordering::SeqCst), + Ordering::SeqCst, + ); + } + } else { + // 新创建的进程,设置其父进程为当前进程 + *pcb.real_parent_pcb.write() = Arc::downgrade(¤t_pcb); + pcb.exit_signal + .store(clone_args.exit_signal, Ordering::SeqCst); + } + + // todo: 增加线程组相关的逻辑。 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/fork.c#2437 + Ok(()) } } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 028b94d4..13b229ad 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -15,7 +15,7 @@ use hashbrown::HashMap; use crate::{ arch::{ - ipc::signal::{SigSet, Signal}, + ipc::signal::{AtomicSignal, SigSet, Signal}, process::ArchPCBInfo, sched::sched, CurrentIrqArch, @@ -308,7 +308,8 @@ impl ProcessManager { parent_pcb.pid() ); } - // todo: 当信号机制重写后,这里需要向父进程发送SIGCHLD信号 + // todo: 这里需要向父进程发送SIGCHLD信号 + // todo: 这里还需要根据线程组的信息,决定信号的发送 } } @@ -511,6 +512,8 @@ bitflags! { pub struct ProcessControlBlock { /// 当前进程的pid pid: Pid, + /// 当前进程的线程组id(这个值在同一个线程组内永远不变) + tgid: Pid, basic: RwLock, /// 当前进程的自旋锁持有计数 @@ -532,9 +535,13 @@ pub struct ProcessControlBlock { sig_info: RwLock, /// 信号处理结构体 sig_struct: SpinLock, + /// 退出信号S + exit_signal: AtomicSignal, /// 父进程指针 parent_pcb: RwLock>, + /// 真实父进程指针 + real_parent_pcb: RwLock>, /// 子进程链表 children: RwLock>, @@ -593,6 +600,7 @@ impl ProcessControlBlock { let pcb = Self { pid, + tgid: pid, basic: basic_info, preempt_count, flags, @@ -603,7 +611,9 @@ impl ProcessControlBlock { arch_info, sig_info: RwLock::new(ProcessSignalInfo::default()), sig_struct: SpinLock::new(SignalStruct::default()), - parent_pcb: RwLock::new(ppcb), + exit_signal: AtomicSignal::new(Signal::SIGCHLD), + parent_pcb: RwLock::new(ppcb.clone()), + real_parent_pcb: RwLock::new(ppcb), children: RwLock::new(Vec::new()), wait_queue: WaitQueue::INIT, thread: RwLock::new(ThreadInfo::new()), @@ -768,6 +778,11 @@ impl ProcessControlBlock { return self.pid; } + #[inline(always)] + pub fn tgid(&self) -> Pid { + return self.tgid; + } + /// 获取文件描述符表的Arc指针 #[inline(always)] pub fn fd_table(&self) -> Arc> { @@ -895,6 +910,8 @@ pub struct ThreadInfo { set_child_tid: Option, vfork_done: Option>, + /// 线程组的组长 + group_leader: Weak, } impl ThreadInfo { @@ -903,8 +920,13 @@ impl ThreadInfo { clear_child_tid: None, set_child_tid: None, vfork_done: None, + group_leader: Weak::default(), } } + + pub fn group_leader(&self) -> Option> { + return self.group_leader.upgrade(); + } } /// 进程的基本信息 diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index c0569a4f..08bbaf77 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -202,7 +202,7 @@ impl Syscall { /// @brief 获取当前进程的pid pub fn getpid() -> Result { let current_pcb = ProcessManager::current_pcb(); - return Ok(current_pcb.pid()); + return Ok(current_pcb.tgid()); } /// @brief 获取指定进程的pgid @@ -295,4 +295,9 @@ impl Syscall { pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr)); Ok(pcb.pid.0) } + + pub fn gettid() -> Result { + let pcb = ProcessManager::current_pcb(); + Ok(pcb.pid) + } } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 25324589..4a392853 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -415,6 +415,8 @@ pub const SYS_REBOOT: usize = 169; pub const SYS_GETPPID: usize = 110; pub const SYS_GETPGID: usize = 121; +pub const SYS_GETTID: usize = 186; + pub const SYS_MKNOD: usize = 133; #[allow(dead_code)] @@ -1134,6 +1136,7 @@ impl Syscall { kwarn!("SYS_MADVISE has not yet been implemented"); Ok(0) } + SYS_GETTID => Self::gettid().map(|tid| tid.into()), _ => panic!("Unsupported syscall ID: {}", syscall_num), }; diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index d3b4f8b6..2c90dc89 100644 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -77,7 +77,7 @@ QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 " QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} " -QEMU_ARGUMENT+="-s -S ${QEMU_MACHINE} -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}" +QEMU_ARGUMENT+="-s ${QEMU_MACHINE} -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}" QEMU_ARGUMENT+=" ${QEMU_SHM_OBJECT} " QEMU_ARGUMENT+=" ${QEMU_ACCELARATE} "