From 5db1f9ad54b167a3c7dc4b330ececd156bd9eda7 Mon Sep 17 00:00:00 2001 From: Vitus <144411726+Vitus213@users.noreply.github.com> Date: Fri, 30 May 2025 20:52:44 +0800 Subject: [PATCH] refactor(ipc): Refactor the syscalls in ipc (#1183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(ipc): 完成对ipc的系统调用的重构 * refactor(ipc): 优化结构 Signed-off-by: sparkzky * feat: fmt Signed-off-by: sparkzky --------- Signed-off-by: sparkzky Co-authored-by: Vitus Co-authored-by: sparkzky --- kernel/src/arch/x86_64/ipc/signal.rs | 31 +- kernel/src/driver/tty/tty_job_control.rs | 7 +- kernel/src/driver/tty/tty_ldisc/ntty.rs | 4 +- kernel/src/ipc/kill.rs | 44 ++ kernel/src/ipc/mod.rs | 1 + kernel/src/ipc/shm.rs | 19 +- kernel/src/ipc/syscall.rs | 662 ------------------- kernel/src/ipc/syscall/mod.rs | 13 + kernel/src/ipc/syscall/sys_kill.rs | 90 +++ kernel/src/ipc/syscall/sys_pipe.rs | 44 ++ kernel/src/ipc/syscall/sys_pipe2.rs | 102 +++ kernel/src/ipc/syscall/sys_restart.rs | 49 ++ kernel/src/ipc/syscall/sys_rt_sigprocmask.rs | 135 ++++ kernel/src/ipc/syscall/sys_shmat.rs | 179 +++++ kernel/src/ipc/syscall/sys_shmctl.rs | 92 +++ kernel/src/ipc/syscall/sys_shmdt.rs | 67 ++ kernel/src/ipc/syscall/sys_shmget.rs | 110 +++ kernel/src/ipc/syscall/sys_sigaction.rs | 191 ++++++ kernel/src/ipc/syscall/sys_sigpending.rs | 76 +++ kernel/src/process/exit.rs | 2 +- kernel/src/process/mod.rs | 4 +- kernel/src/syscall/mod.rs | 75 +-- 22 files changed, 1241 insertions(+), 756 deletions(-) create mode 100644 kernel/src/ipc/kill.rs delete mode 100644 kernel/src/ipc/syscall.rs create mode 100644 kernel/src/ipc/syscall/mod.rs create mode 100644 kernel/src/ipc/syscall/sys_kill.rs create mode 100644 kernel/src/ipc/syscall/sys_pipe.rs create mode 100644 kernel/src/ipc/syscall/sys_pipe2.rs create mode 100644 kernel/src/ipc/syscall/sys_restart.rs create mode 100644 kernel/src/ipc/syscall/sys_rt_sigprocmask.rs create mode 100644 kernel/src/ipc/syscall/sys_shmat.rs create mode 100644 kernel/src/ipc/syscall/sys_shmctl.rs create mode 100644 kernel/src/ipc/syscall/sys_shmdt.rs create mode 100644 kernel/src/ipc/syscall/sys_shmget.rs create mode 100644 kernel/src/ipc/syscall/sys_sigaction.rs create mode 100644 kernel/src/ipc/syscall/sys_sigpending.rs diff --git a/kernel/src/arch/x86_64/ipc/signal.rs b/kernel/src/arch/x86_64/ipc/signal.rs index 619df758..2fe4428c 100644 --- a/kernel/src/arch/x86_64/ipc/signal.rs +++ b/kernel/src/arch/x86_64/ipc/signal.rs @@ -20,7 +20,7 @@ use crate::{ mm::MemoryManagementArch, process::ProcessManager, sched::{schedule, SchedMode}, - syscall::{user_access::UserBufferWriter, Syscall}, + syscall::user_access::UserBufferWriter, }; /// 信号处理的栈的栈指针的最小对齐数量 @@ -556,8 +556,11 @@ impl SignalArch for X86_64SignalArch { // 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击) if UserBufferWriter::new(frame, size_of::(), true).is_err() { error!("rsp doesn't from user level"); - let _r = Syscall::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV) - .map_err(|e| e.to_posix_errno()); + let _r = crate::ipc::kill::kill_process( + ProcessManager::current_pcb().pid(), + Signal::SIGSEGV, + ) + .map_err(|e| e.to_posix_errno()); return trap_frame.rax; } let mut sigmask: SigSet = unsafe { (*frame).context.oldmask }; @@ -565,8 +568,11 @@ impl SignalArch for X86_64SignalArch { // 从用户栈恢复sigcontext if !unsafe { &mut (*frame).context }.restore_sigcontext(trap_frame) { error!("unable to restore sigcontext"); - let _r = Syscall::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV) - .map_err(|e| e.to_posix_errno()); + let _r = crate::ipc::kill::kill_process( + ProcessManager::current_pcb().pid(), + Signal::SIGSEGV, + ) + .map_err(|e| e.to_posix_errno()); // 如果这里返回 err 值的话会丢失上一个系统调用的返回值 } // 由于系统调用的返回值会被系统调用模块被存放在rax寄存器,因此,为了还原原来的那个系统调用的返回值,我们需要在这里返回恢复后的rax的值 @@ -658,7 +664,7 @@ fn setup_frame( ProcessManager::current_pcb().pid(), sig as i32 ); - let r = Syscall::kill_process( + let r = crate::ipc::kill::kill_process( ProcessManager::current_pcb().pid(), Signal::SIGSEGV, ); @@ -698,7 +704,8 @@ fn setup_frame( if r.is_err() { // 如果地址区域位于内核空间,则直接报错 // todo: 生成一个sigsegv - let r = Syscall::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV); + let r = + crate::ipc::kill::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV); if r.is_err() { error!("In setup frame: generate SIGSEGV signal failed"); } @@ -709,7 +716,10 @@ fn setup_frame( // 将siginfo拷贝到用户栈 info.copy_siginfo_to_user(unsafe { &mut ((*frame).info) as *mut SigInfo }) .map_err(|e| -> SystemError { - let r = Syscall::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV); + let r = crate::ipc::kill::kill_process( + ProcessManager::current_pcb().pid(), + Signal::SIGSEGV, + ); if r.is_err() { error!("In copy_siginfo_to_user: generate SIGSEGV signal failed"); } @@ -723,7 +733,10 @@ fn setup_frame( .context .setup_sigcontext(oldset, trap_frame) .map_err(|e: SystemError| -> SystemError { - let r = Syscall::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV); + let r = crate::ipc::kill::kill_process( + ProcessManager::current_pcb().pid(), + Signal::SIGSEGV, + ); if r.is_err() { error!("In setup_sigcontext: generate SIGSEGV signal failed"); } diff --git a/kernel/src/driver/tty/tty_job_control.rs b/kernel/src/driver/tty/tty_job_control.rs index 03980650..9cff704f 100644 --- a/kernel/src/driver/tty/tty_job_control.rs +++ b/kernel/src/driver/tty/tty_job_control.rs @@ -5,10 +5,7 @@ use crate::{ arch::ipc::signal::{SigSet, Signal}, mm::VirtAddr, process::{process_group::Pgid, Pid, ProcessFlags, ProcessManager}, - syscall::{ - user_access::{UserBufferReader, UserBufferWriter}, - Syscall, - }, + syscall::user_access::{UserBufferReader, UserBufferWriter}, }; use super::tty_core::{TtyCore, TtyIoctlCmd}; @@ -59,7 +56,7 @@ impl TtyJobCtrlManager { } else if ProcessManager::is_current_pgrp_orphaned() { return Err(SystemError::EIO); } else { - Syscall::kill_process_group(pgid, sig)?; + crate::ipc::kill::kill_process_group(pgid, sig)?; ProcessManager::current_pcb() .flags() .insert(ProcessFlags::HAS_PENDING_SIGNAL); diff --git a/kernel/src/driver/tty/tty_ldisc/ntty.rs b/kernel/src/driver/tty/tty_ldisc/ntty.rs index 6c30f1f4..81353bcc 100644 --- a/kernel/src/driver/tty/tty_ldisc/ntty.rs +++ b/kernel/src/driver/tty/tty_ldisc/ntty.rs @@ -22,7 +22,7 @@ use crate::{ }, mm::VirtAddr, process::{ProcessFlags, ProcessManager}, - syscall::{user_access::UserBufferWriter, Syscall}, + syscall::user_access::UserBufferWriter, }; use super::TtyLineDiscipline; @@ -789,7 +789,7 @@ impl NTtyData { let ctrl_info = tty.core().contorl_info_irqsave(); let pg = ctrl_info.pgid; if let Some(pg) = pg { - let _ = Syscall::kill_process_group(pg, signal); + let _ = crate::ipc::kill::kill_process_group(pg, signal); } if !termios.local_mode.contains(LocalMode::NOFLSH) { diff --git a/kernel/src/ipc/kill.rs b/kernel/src/ipc/kill.rs new file mode 100644 index 00000000..cc0065ce --- /dev/null +++ b/kernel/src/ipc/kill.rs @@ -0,0 +1,44 @@ +use crate::arch::ipc::signal::{SigCode, Signal}; +use crate::ipc::signal_types::{SigInfo, SigType}; +use crate::process::{process_group::Pgid, Pid, ProcessManager}; +use core::sync::atomic::compiler_fence; +use system_error::SystemError; + +/// ### 杀死一个进程 +pub fn kill_process(pid: Pid, sig: Signal) -> Result { + // 初始化signal info + let mut info = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(pid)); + compiler_fence(core::sync::atomic::Ordering::SeqCst); + + let ret = sig + .send_signal_info(Some(&mut info), pid) + .map(|x| x as usize); + + compiler_fence(core::sync::atomic::Ordering::SeqCst); + ret +} + +/// ### 杀死一个进程组 +pub fn kill_process_group(pgid: Pgid, sig: Signal) -> Result { + let pg = ProcessManager::find_process_group(pgid).ok_or(SystemError::ESRCH)?; + let inner = pg.process_group_inner.lock(); + for pcb in inner.processes.values() { + kill_process(pcb.pid(), sig)?; // Call the new common function + } + Ok(0) +} + +/// ### 杀死所有进程 +/// - 该函数会杀死所有进程,除了当前进程和init进程 +pub fn kill_all(sig: Signal) -> Result { + let current_pid = ProcessManager::current_pcb().pid(); + let all_processes = ProcessManager::get_all_processes(); + + for pid_val in all_processes { + if pid_val == current_pid || pid_val.data() == 1 { + continue; + } + kill_process(pid_val, sig)?; // Call the new common function + } + Ok(0) +} diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 3ff869cd..8b1d5b32 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,4 +1,5 @@ pub mod generic_signal; +pub mod kill; pub mod pipe; pub mod shm; pub mod signal; diff --git a/kernel/src/ipc/shm.rs b/kernel/src/ipc/shm.rs index e2c0187f..b04ae324 100644 --- a/kernel/src/ipc/shm.rs +++ b/kernel/src/ipc/shm.rs @@ -14,13 +14,13 @@ use crate::{ syscall::user_access::{UserBufferReader, UserBufferWriter}, time::PosixTimeSpec, }; +use core::fmt; use core::sync::atomic::{compiler_fence, Ordering}; use hashbrown::HashMap; use ida::IdAllocator; use log::info; use num::ToPrimitive; use system_error::SystemError; - pub static mut SHM_MANAGER: Option> = None; /// 用于创建新的私有IPC对象 @@ -104,6 +104,23 @@ impl From for ShmCtlCmd { } } +impl fmt::Display for ShmCtlCmd { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ShmCtlCmd::IpcRmid => write!(f, "IPC_RMID"), + ShmCtlCmd::IpcSet => write!(f, "IPC_SET"), + ShmCtlCmd::IpcStat => write!(f, "IPC_STAT"), + ShmCtlCmd::IpcInfo => write!(f, "IPC_INFO"), + ShmCtlCmd::ShmLock => write!(f, "SHM_LOCK"), + ShmCtlCmd::ShmUnlock => write!(f, "SHM_UNLOCK"), + ShmCtlCmd::ShmStat => write!(f, "SHM_STAT"), + ShmCtlCmd::ShmInfo => write!(f, "SHM_INFO"), + ShmCtlCmd::ShmtStatAny => write!(f, "SHM_STAT_ANY"), + ShmCtlCmd::Default => write!(f, "DEFAULT (Invalid Cmd)"), + } + } +} + impl PartialEq for ShmCtlCmd { fn eq(&self, other: &ShmCtlCmd) -> bool { *self as usize == *other as usize diff --git a/kernel/src/ipc/syscall.rs b/kernel/src/ipc/syscall.rs deleted file mode 100644 index 21db609a..00000000 --- a/kernel/src/ipc/syscall.rs +++ /dev/null @@ -1,662 +0,0 @@ -use core::{ - ffi::{c_int, c_void}, - sync::atomic::compiler_fence, -}; - -use log::{error, warn}; -use system_error::SystemError; - -use crate::{ - arch::{ - ipc::signal::{SigCode, SigFlags, SigSet, Signal}, - MMArch, - }, - filesystem::vfs::{ - file::{File, FileMode}, - FilePrivateData, - }, - ipc::shm::{shm_manager_lock, IPC_PRIVATE}, - libs::{align::page_align_up, spinlock::SpinLock}, - mm::{ - allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame}, - page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll}, - syscall::ProtFlags, - ucontext::{AddressSpace, VMA}, - VirtAddr, VmFlags, - }, - process::{process_group::Pgid, Pid, ProcessManager}, - syscall::{ - user_access::{UserBufferReader, UserBufferWriter}, - Syscall, - }, -}; - -use super::{ - pipe::{LockedPipeInode, PipeFsPrivateData}, - shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey}, - signal::{set_sigprocmask, SigHow}, - signal_types::{ - SaHandlerType, SigInfo, SigType, Sigaction, SigactionType, UserSigaction, USER_SIG_DFL, - USER_SIG_ERR, USER_SIG_IGN, - }, -}; - -/// ### pid转换器,将输入的id转换成对应的pid或pgid -/// - 如果id < -1,则为pgid -/// - 如果id == -1,则为所有进程 -/// - 如果id == 0,则为当前进程组 -/// - 如果id > 0,则为pid -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum PidConverter { - All, - Pid(Pid), - Pgid(Pgid), -} - -impl PidConverter { - /// ### 为 `wait` 和 `kill` 调用使用 - pub fn from_id(id: i32) -> Self { - if id < -1 { - PidConverter::Pgid(Pgid::from(-id as usize)) - } else if id == -1 { - PidConverter::All - } else if id == 0 { - let pgid = ProcessManager::current_pcb().pgid(); - PidConverter::Pgid(pgid) - } else { - PidConverter::Pid(Pid::from(id as usize)) - } - } -} - -impl Syscall { - /// # 创建带参数的匿名管道 - /// - /// ## 参数 - /// - /// - `fd`: 用于返回文件描述符的数组 - /// - `flags`:设置管道的参数 - pub fn pipe2(fd: *mut i32, flags: FileMode) -> Result { - if !flags - .difference(FileMode::O_CLOEXEC | FileMode::O_NONBLOCK | FileMode::O_DIRECT) - .is_empty() - { - return Err(SystemError::EINVAL); - } - - let mut user_buffer = UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?; - let fd = user_buffer.buffer::(0)?; - let pipe_ptr = LockedPipeInode::new(); - - let mut read_file = File::new( - pipe_ptr.clone(), - FileMode::O_RDONLY | (flags & FileMode::O_NONBLOCK), - )?; - read_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new( - FileMode::O_RDONLY, - ))); - - let mut write_file = File::new( - pipe_ptr.clone(), - FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)), - )?; - write_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new( - FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)), - ))); - - if flags.contains(FileMode::O_CLOEXEC) { - read_file.set_close_on_exec(true); - write_file.set_close_on_exec(true); - } - let fd_table_ptr = ProcessManager::current_pcb().fd_table(); - let mut fd_table_guard = fd_table_ptr.write(); - let read_fd = fd_table_guard.alloc_fd(read_file, None)?; - let write_fd = fd_table_guard.alloc_fd(write_file, None)?; - - drop(fd_table_guard); - - fd[0] = read_fd; - fd[1] = write_fd; - Ok(0) - } - - /// ### 杀死一个进程 - pub fn kill_process(pid: Pid, sig: Signal) -> Result { - // 初始化signal info - let mut info = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(pid)); - compiler_fence(core::sync::atomic::Ordering::SeqCst); - - let ret = sig - .send_signal_info(Some(&mut info), pid) - .map(|x| x as usize); - - compiler_fence(core::sync::atomic::Ordering::SeqCst); - - return ret; - } - - /// ### 杀死一个进程组 - pub fn kill_process_group(pgid: Pgid, sig: Signal) -> Result { - let pg = ProcessManager::find_process_group(pgid).ok_or(SystemError::ESRCH)?; - let inner = pg.process_group_inner.lock(); - for pcb in inner.processes.values() { - Self::kill_process(pcb.pid(), sig)?; - } - Ok(0) - } - - /// ### 杀死所有进程 - /// - 该函数会杀死所有进程,除了当前进程和init进程 - pub fn kill_all(sig: Signal) -> Result { - let current_pid = ProcessManager::current_pcb().pid(); - let all_processes = ProcessManager::get_all_processes(); - - for pid in all_processes { - if pid == current_pid || pid.data() == 1 { - continue; - } - Self::kill_process(pid, sig)?; - } - Ok(0) - } - - /// # kill系统调用函数 - /// - /// ## 参数 - /// - `id`: id,等于0表示当前进程组,等于-1表示所有进程,小于0表示pgid = -id,大于0表示pid = id, - /// - `sig`: 信号值 - pub fn kill(id: i32, sig: c_int) -> Result { - let converter = PidConverter::from_id(id); - let sig = Signal::from(sig); - if sig == Signal::INVALID { - // 传入的signal数值不合法 - warn!("Not a valid signal number"); - return Err(SystemError::EINVAL); - } - - // compiler_fence(core::sync::atomic::Ordering::SeqCst); - - let retval = match converter { - PidConverter::Pid(pid) => Self::kill_process(pid, sig), - PidConverter::Pgid(pgid) => Self::kill_process_group(pgid, sig), - PidConverter::All => Self::kill_all(sig), - }; - - // compiler_fence(core::sync::atomic::Ordering::SeqCst); - - return retval; - } - - /// 通用信号注册函数 - /// - /// ## 参数 - /// - /// - `sig` 信号的值 - /// - `act` 用户空间传入的 Sigaction 指针 - /// - `old_act` 用户空间传入的用来保存旧 Sigaction 的指针 - /// - `from_user` 用来标识这个函数调用是否来自用户空间 - /// - /// @return int 错误码 - #[no_mangle] - pub fn sigaction( - sig: c_int, - new_act: usize, - old_act: usize, - from_user: bool, - ) -> Result { - // 请注意:用户态传进来的user_sigaction结构体类型,请注意,这个结构体与内核实际的不一样 - let act: *mut UserSigaction = new_act as *mut UserSigaction; - let old_act = old_act as *mut UserSigaction; - let mut new_ka: Sigaction = Default::default(); - let mut old_sigaction: Sigaction = Default::default(); - // 如果传入的,新的sigaction不为空 - if !act.is_null() { - // 如果参数的范围不在用户空间,则返回错误 - let r = UserBufferWriter::new(act, core::mem::size_of::(), from_user); - if r.is_err() { - return Err(SystemError::EFAULT); - } - let mask: SigSet = unsafe { (*act).mask }; - let input_sighandler = unsafe { (*act).handler as u64 }; - match input_sighandler { - USER_SIG_DFL => { - new_ka = Sigaction::DEFAULT_SIGACTION; - *new_ka.flags_mut() = unsafe { (*act).flags }; - new_ka.set_restorer(None); - } - - USER_SIG_IGN => { - new_ka = Sigaction::DEFAULT_SIGACTION_IGNORE; - *new_ka.flags_mut() = unsafe { (*act).flags }; - - new_ka.set_restorer(None); - } - _ => { - // 从用户空间获得sigaction结构体 - // TODO mask是default还是用户空间传入 - new_ka = Sigaction::new( - SigactionType::SaHandler(SaHandlerType::Customized(unsafe { - VirtAddr::new((*act).handler as usize) - })), - unsafe { (*act).flags }, - SigSet::default(), - unsafe { Some(VirtAddr::new((*act).restorer as usize)) }, - ); - } - } - - // TODO 如果为空,赋默认值? - // debug!("new_ka={:?}", new_ka); - // 如果用户手动给了sa_restorer,那么就置位SA_FLAG_RESTORER,否则报错。(用户必须手动指定restorer) - if new_ka.restorer().is_some() { - new_ka.flags_mut().insert(SigFlags::SA_RESTORER); - } else if new_ka.action().is_customized() { - error!( - "pid:{:?}: in sys_sigaction: User must manually sprcify a sa_restorer for signal {}.", - ProcessManager::current_pcb().pid(), - sig - ); - return Err(SystemError::EINVAL); - } - *new_ka.mask_mut() = mask; - } - - let sig = Signal::from(sig); - // 如果给出的信号值不合法 - if sig == Signal::INVALID { - return Err(SystemError::EINVAL); - } - - let retval = super::signal::do_sigaction( - sig, - if act.is_null() { - None - } else { - Some(&mut new_ka) - }, - if old_act.is_null() { - None - } else { - Some(&mut old_sigaction) - }, - ); - - // - if (retval == Ok(())) && (!old_act.is_null()) { - let r = - UserBufferWriter::new(old_act, core::mem::size_of::(), from_user); - if r.is_err() { - return Err(SystemError::EFAULT); - } - - let sigaction_handler = match old_sigaction.action() { - SigactionType::SaHandler(handler) => { - if let SaHandlerType::Customized(hand) = handler { - hand - } else if handler.is_sig_ignore() { - VirtAddr::new(USER_SIG_IGN as usize) - } else if handler.is_sig_error() { - VirtAddr::new(USER_SIG_ERR as usize) - } else { - VirtAddr::new(USER_SIG_DFL as usize) - } - } - SigactionType::SaSigaction(_) => { - error!("unsupported type: SaSigaction"); - VirtAddr::new(USER_SIG_DFL as usize) - } - }; - - unsafe { - (*old_act).handler = sigaction_handler.data() as *mut c_void; - (*old_act).flags = old_sigaction.flags(); - (*old_act).mask = old_sigaction.mask(); - if old_sigaction.restorer().is_some() { - (*old_act).restorer = old_sigaction.restorer().unwrap().data() as *mut c_void; - } - } - } - return retval.map(|_| 0); - } - - /// # SYS_SHMGET系统调用函数,用于获取共享内存 - /// - /// ## 参数 - /// - /// - `key`: 共享内存键值 - /// - `size`: 共享内存大小(bytes) - /// - `shmflg`: 共享内存标志 - /// - /// ## 返回值 - /// - /// 成功:共享内存id - /// 失败:错误码 - pub fn shmget(key: ShmKey, size: usize, shmflg: ShmFlags) -> Result { - // 暂不支持巨页 - if shmflg.contains(ShmFlags::SHM_HUGETLB) { - error!("shmget: not support huge page"); - return Err(SystemError::ENOSYS); - } - - let mut shm_manager_guard = shm_manager_lock(); - match key { - // 创建共享内存段 - IPC_PRIVATE => shm_manager_guard.add(key, size, shmflg), - _ => { - // 查找key对应的共享内存段是否存在 - let id = shm_manager_guard.contains_key(&key); - if let Some(id) = id { - // 不能重复创建 - if shmflg.contains(ShmFlags::IPC_CREAT | ShmFlags::IPC_EXCL) { - return Err(SystemError::EEXIST); - } - - // key值存在,说明有对应共享内存,返回该共享内存id - return Ok(id.data()); - } else { - // key不存在且shm_flags不包含IPC_CREAT创建IPC对象标志,则返回错误码 - if !shmflg.contains(ShmFlags::IPC_CREAT) { - return Err(SystemError::ENOENT); - } - - // 存在创建IPC对象标志 - return shm_manager_guard.add(key, size, shmflg); - } - } - } - } - - /// # SYS_SHMAT系统调用函数,用于连接共享内存段 - /// - /// ## 参数 - /// - /// - `id`: 共享内存id - /// - `vaddr`: 连接共享内存的进程虚拟内存区域起始地址 - /// - `shmflg`: 共享内存标志 - /// - /// ## 返回值 - /// - /// 成功:映射到共享内存的虚拟内存区域起始地址 - /// 失败:错误码 - pub fn shmat(id: ShmId, vaddr: VirtAddr, shmflg: ShmFlags) -> Result { - let mut shm_manager_guard = shm_manager_lock(); - let current_address_space = AddressSpace::current()?; - let mut address_write_guard = current_address_space.write(); - - let kernel_shm = shm_manager_guard.get_mut(&id).ok_or(SystemError::EINVAL)?; - let size = page_align_up(kernel_shm.size()); - let mut phys = PhysPageFrame::new(kernel_shm.start_paddr()); - let count = PageFrameCount::from_bytes(size).unwrap(); - let r = match vaddr.data() { - // 找到空闲区域并映射到共享内存 - 0 => { - // 找到空闲区域 - let region = address_write_guard - .mappings - .find_free(vaddr, size) - .ok_or(SystemError::EINVAL)?; - let vm_flags = VmFlags::from(shmflg); - let destination = VirtPageFrame::new(region.start()); - let page_flags: EntryFlags = - EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true); - let flusher: PageFlushAll = PageFlushAll::new(); - - // 将共享内存映射到对应虚拟区域 - let vma = VMA::physmap( - phys, - destination, - count, - vm_flags, - page_flags, - &mut address_write_guard.user_mapper.utable, - flusher, - )?; - - // 将VMA加入到当前进程的VMA列表中 - address_write_guard.mappings.insert_vma(vma); - - region.start().data() - } - // 指定虚拟地址 - _ => { - // 获取对应vma - let vma = address_write_guard - .mappings - .contains(vaddr) - .ok_or(SystemError::EINVAL)?; - if vma.lock_irqsave().region().start() != vaddr { - return Err(SystemError::EINVAL); - } - - // 验证用户虚拟内存区域是否有效 - let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?; - - // 必须在取消映射前获取到EntryFlags - let page_flags = address_write_guard - .user_mapper - .utable - .translate(vaddr) - .ok_or(SystemError::EINVAL)? - .1; - - // 取消原映射 - let flusher: PageFlushAll = PageFlushAll::new(); - vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); - - // 将该虚拟内存区域映射到共享内存区域 - let mut page_manager_guard = page_manager_lock_irqsave(); - let mut virt = VirtPageFrame::new(vaddr); - for _ in 0..count.data() { - let r = unsafe { - address_write_guard.user_mapper.utable.map_phys( - virt.virt_address(), - phys.phys_address(), - page_flags, - ) - } - .expect("Failed to map zero, may be OOM error"); - r.flush(); - - // 将vma加入到对应Page的anon_vma - page_manager_guard - .get_unwrap(&phys.phys_address()) - .write_irqsave() - .insert_vma(vma.clone()); - - phys = phys.next(); - virt = virt.next(); - } - - // 更新vma的映射状态 - vma.lock_irqsave().set_mapped(true); - - vaddr.data() - } - }; - - // 更新最后一次连接时间 - kernel_shm.update_atim(); - - // 映射计数增加 - kernel_shm.increase_count(); - - Ok(r) - } - - /// # SYS_SHMDT系统调用函数,用于取消对共享内存的连接 - /// - /// ## 参数 - /// - /// - `vaddr`: 需要取消映射的虚拟内存区域起始地址 - /// - /// ## 返回值 - /// - /// 成功:0 - /// 失败:错误码 - pub fn shmdt(vaddr: VirtAddr) -> Result { - let current_address_space = AddressSpace::current()?; - let mut address_write_guard = current_address_space.write(); - - // 获取vma - let vma = address_write_guard - .mappings - .contains(vaddr) - .ok_or(SystemError::EINVAL)?; - - // 判断vaddr是否为起始地址 - if vma.lock_irqsave().region().start() != vaddr { - return Err(SystemError::EINVAL); - } - - // 取消映射 - let flusher: PageFlushAll = PageFlushAll::new(); - vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); - - return Ok(0); - } - - /// # SYS_SHMCTL系统调用函数,用于管理共享内存段 - /// - /// ## 参数 - /// - /// - `id`: 共享内存id - /// - `cmd`: 操作码 - /// - `user_buf`: 用户缓冲区 - /// - `from_user`: buf_vaddr是否来自用户地址空间 - /// - /// ## 返回值 - /// - /// 成功:0 - /// 失败:错误码 - pub fn shmctl( - id: ShmId, - cmd: ShmCtlCmd, - user_buf: *const u8, - from_user: bool, - ) -> Result { - let mut shm_manager_guard = shm_manager_lock(); - - match cmd { - // 查看共享内存元信息 - ShmCtlCmd::IpcInfo => shm_manager_guard.ipc_info(user_buf, from_user), - // 查看共享内存使用信息 - ShmCtlCmd::ShmInfo => shm_manager_guard.shm_info(user_buf, from_user), - // 查看id对应的共享内存信息 - ShmCtlCmd::ShmStat | ShmCtlCmd::ShmtStatAny | ShmCtlCmd::IpcStat => { - shm_manager_guard.shm_stat(id, cmd, user_buf, from_user) - } - // 设置KernIpcPerm - ShmCtlCmd::IpcSet => shm_manager_guard.ipc_set(id, user_buf, from_user), - // 将共享内存段设置为可回收状态 - ShmCtlCmd::IpcRmid => shm_manager_guard.ipc_rmid(id), - // 锁住共享内存段,不允许内存置换 - ShmCtlCmd::ShmLock => shm_manager_guard.shm_lock(id), - // 解锁共享内存段,允许内存置换 - ShmCtlCmd::ShmUnlock => shm_manager_guard.shm_unlock(id), - // 无效操作码 - ShmCtlCmd::Default => Err(SystemError::EINVAL), - } - } - - /// # SYS_SIGPROCMASK系统调用函数,用于设置或查询当前进程的信号屏蔽字 - /// - /// ## 参数 - /// - /// - `how`: 指示如何修改信号屏蔽字 - /// - `nset`: 新的信号屏蔽字 - /// - `oset`: 旧的信号屏蔽字的指针,由于可以是NULL,所以用Option包装 - /// - `sigsetsize`: 信号集的大小 - /// - /// ## 返回值 - /// - /// 成功:0 - /// 失败:错误码 - /// - /// ## 说明 - /// 根据 https://man7.org/linux/man-pages/man2/sigprocmask.2.html ,传进来的oldset和newset都是指针类型,这里选择传入usize然后转换为u64的指针类型 - pub fn rt_sigprocmask( - how: i32, - newset: usize, - oldset: usize, - sigsetsize: usize, - ) -> Result { - // 对应oset传进来一个NULL的情况 - let oset = if oldset == 0 { None } else { Some(oldset) }; - let nset = if newset == 0 { None } else { Some(newset) }; - - if sigsetsize != size_of::() { - return Err(SystemError::EFAULT); - } - - let sighow = SigHow::try_from(how)?; - - let mut new_set = SigSet::default(); - if let Some(nset) = nset { - let reader = UserBufferReader::new( - VirtAddr::new(nset).as_ptr::(), - core::mem::size_of::(), - true, - )?; - - let nset = reader.read_one_from_user::(0)?; - new_set = SigSet::from_bits_truncate(*nset); - // debug!("Get Newset: {}", &new_set.bits()); - let to_remove: SigSet = - >::into(Signal::SIGKILL) | Signal::SIGSTOP.into(); - new_set.remove(to_remove); - } - - let oldset_to_return = set_sigprocmask(sighow, new_set)?; - if let Some(oldset) = oset { - // debug!("Get Oldset to return: {}", &oldset_to_return.bits()); - let mut writer = UserBufferWriter::new( - VirtAddr::new(oldset).as_ptr::(), - core::mem::size_of::(), - true, - )?; - writer.copy_one_to_user::(&oldset_to_return.bits(), 0)?; - } - - Ok(0) - } - - pub fn restart_syscall() -> Result { - let restart_block = ProcessManager::current_pcb().restart_block().take(); - if let Some(mut restart_block) = restart_block { - return restart_block.restart_fn.call(&mut restart_block.data); - } else { - // 不应该走到这里,因此kill掉当前进程及同组的进程 - let pid = Pid::new(0); - let sig = Signal::SIGKILL; - let mut info = SigInfo::new(sig, 0, SigCode::Kernel, SigType::Kill(pid)); - - sig.send_signal_info(Some(&mut info), pid) - .expect("Failed to kill "); - return Ok(0); - } - } - - #[inline(never)] - pub fn rt_sigpending(user_sigset_ptr: usize, sigsetsize: usize) -> Result { - if sigsetsize != size_of::() { - return Err(SystemError::EINVAL); - } - - let mut user_buffer_writer = - UserBufferWriter::new(user_sigset_ptr as *mut SigSet, size_of::(), true)?; - - let pcb = ProcessManager::current_pcb(); - let siginfo_guard = pcb.sig_info_irqsave(); - let pending_set = siginfo_guard.sig_pending().signal(); - let shared_pending_set = siginfo_guard.sig_shared_pending().signal(); - let blocked_set = *siginfo_guard.sig_blocked(); - drop(siginfo_guard); - - let mut result = pending_set.union(shared_pending_set); - result = result.difference(blocked_set); - - user_buffer_writer.copy_one_to_user(&result, 0)?; - - Ok(0) - } -} diff --git a/kernel/src/ipc/syscall/mod.rs b/kernel/src/ipc/syscall/mod.rs new file mode 100644 index 00000000..75a79042 --- /dev/null +++ b/kernel/src/ipc/syscall/mod.rs @@ -0,0 +1,13 @@ +pub mod sys_kill; +pub mod sys_pipe2; +mod sys_restart; +mod sys_rt_sigprocmask; +mod sys_shmat; +mod sys_shmctl; +mod sys_shmdt; +mod sys_shmget; +mod sys_sigaction; +mod sys_sigpending; + +#[cfg(target_arch = "x86_64")] +pub mod sys_pipe; diff --git a/kernel/src/ipc/syscall/sys_kill.rs b/kernel/src/ipc/syscall/sys_kill.rs new file mode 100644 index 00000000..4de97e6c --- /dev/null +++ b/kernel/src/ipc/syscall/sys_kill.rs @@ -0,0 +1,90 @@ +use alloc::string::ToString; +use alloc::vec::Vec; +use core::ffi::c_int; + +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use crate::{ + arch::{ipc::signal::Signal, syscall::nr::SYS_KILL}, + process::{process_group::Pgid, Pid, ProcessManager}, +}; +use log::warn; +use system_error::SystemError; + +use crate::ipc::kill::{kill_all, kill_process, kill_process_group}; + +/// ### pid转换器,将输入的id转换成对应的pid或pgid +/// - 如果id < -1,则为pgid +/// - 如果id == -1,则为所有进程 +/// - 如果id == 0,则为当前进程组 +/// - 如果id > 0,则为pid +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PidConverter { + All, + Pid(Pid), + Pgid(Pgid), +} + +impl PidConverter { + /// ### 为 `wait` 和 `kill` 调用使用 + pub fn from_id(id: i32) -> Self { + if id < -1 { + PidConverter::Pgid(Pgid::from(-id as usize)) + } else if id == -1 { + PidConverter::All + } else if id == 0 { + let pgid = ProcessManager::current_pcb().pgid(); + PidConverter::Pgid(pgid) + } else { + PidConverter::Pid(Pid::from(id as usize)) + } + } +} + +pub struct SysKillHandle; + +impl SysKillHandle { + #[inline(always)] + fn pid(args: &[usize]) -> i32 { + // 第一个参数是id + args[0] as i32 + } + #[inline(always)] + fn sig(args: &[usize]) -> c_int { + // 第二个参数是信号值 + args[1] as c_int + } +} + +impl Syscall for SysKillHandle { + fn num_args(&self) -> usize { + 2 + } + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let id = Self::pid(args); + let sig_c_int = Self::sig(args); + + let converter = PidConverter::from_id(id); + let sig = Signal::from(sig_c_int); + if sig == Signal::INVALID { + warn!("Not a valid signal number"); + return Err(SystemError::EINVAL); + } + + match converter { + PidConverter::Pid(pid) => kill_process(pid, sig), + PidConverter::Pgid(pgid) => kill_process_group(pgid, sig), + PidConverter::All => kill_all(sig), + } + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("pid", Self::pid(args).to_string()), + FormattedSyscallParam::new("sig", Self::sig(args).to_string()), + ] + } +} + +// 注册系统调用 +syscall_table_macros::declare_syscall!(SYS_KILL, SysKillHandle); diff --git a/kernel/src/ipc/syscall/sys_pipe.rs b/kernel/src/ipc/syscall/sys_pipe.rs new file mode 100644 index 00000000..b7dd862b --- /dev/null +++ b/kernel/src/ipc/syscall/sys_pipe.rs @@ -0,0 +1,44 @@ +use super::sys_pipe2::do_kernel_pipe2; +use crate::arch::syscall::nr::SYS_PIPE; +use crate::{ + filesystem::vfs::file::FileMode, + syscall::table::{FormattedSyscallParam, Syscall}, +}; +use alloc::vec::Vec; +use core::ffi::c_int; +use system_error::SystemError; + +pub struct SysPipeHandle; + +impl SysPipeHandle { + #[inline(always)] + fn pipefd(args: &[usize]) -> *mut i32 { + // 第一个参数是fd指针 + args[0] as *mut c_int + } +} + +impl Syscall for SysPipeHandle { + fn num_args(&self) -> usize { + 1 // pipefd + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let pipefd = Self::pipefd(args); + if pipefd.is_null() { + return Err(SystemError::EFAULT); + } else { + do_kernel_pipe2(pipefd, FileMode::empty()) + } + } + + fn entry_format(&self, args: &[usize]) -> Vec { + let fd_ptr = Self::pipefd(args); + vec![FormattedSyscallParam::new( + "fd_ptr", + format!("{}", fd_ptr as usize), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_PIPE, SysPipeHandle); diff --git a/kernel/src/ipc/syscall/sys_pipe2.rs b/kernel/src/ipc/syscall/sys_pipe2.rs new file mode 100644 index 00000000..2d918234 --- /dev/null +++ b/kernel/src/ipc/syscall/sys_pipe2.rs @@ -0,0 +1,102 @@ +use crate::{ + arch::syscall::nr::SYS_PIPE2, + filesystem::vfs::{ + file::{File, FileMode}, + FilePrivateData, + }, + ipc::pipe::{LockedPipeInode, PipeFsPrivateData}, + libs::spinlock::SpinLock, + process::ProcessManager, + syscall::{ + table::{FormattedSyscallParam, Syscall}, + user_access::UserBufferWriter, + }, +}; +use alloc::vec::Vec; +use core::ffi::c_int; +use system_error::SystemError; + +pub struct SysPipe2Handle; + +// Extracted core logic for pipe2 +// pub(super) makes it visible to other modules in kernel/src/ipc/syscall/ +pub(super) fn do_kernel_pipe2(fd: *mut i32, flags: FileMode) -> Result { + if !flags + .difference(FileMode::O_CLOEXEC | FileMode::O_NONBLOCK | FileMode::O_DIRECT) + .is_empty() + { + return Err(SystemError::EINVAL); + } + + let mut user_buffer = UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?; + let fd = user_buffer.buffer::(0)?; + let pipe_ptr = LockedPipeInode::new(); + + let mut read_file = File::new( + pipe_ptr.clone(), + FileMode::O_RDONLY | (flags & FileMode::O_NONBLOCK), + )?; + read_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new( + FileMode::O_RDONLY, + ))); + + let mut write_file = File::new( + pipe_ptr.clone(), + FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)), + )?; + write_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new( + FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)), + ))); + + if flags.contains(FileMode::O_CLOEXEC) { + read_file.set_close_on_exec(true); + write_file.set_close_on_exec(true); + } + let fd_table_ptr = ProcessManager::current_pcb().fd_table(); + let mut fd_table_guard = fd_table_ptr.write(); + let read_fd = fd_table_guard.alloc_fd(read_file, None)?; + let write_fd = fd_table_guard.alloc_fd(write_file, None)?; + + drop(fd_table_guard); + + fd[0] = read_fd; + fd[1] = write_fd; + Ok(0) +} + +impl SysPipe2Handle { + #[inline(always)] + fn pipefd(args: &[usize]) -> *mut i32 { + args[0] as *mut c_int + } + #[inline(always)] + fn flags(args: &[usize]) -> FileMode { + FileMode::from_bits_truncate(args[1] as u32) + } +} + +impl Syscall for SysPipe2Handle { + fn num_args(&self) -> usize { + 2 // fd_ptr, flags + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let fd_ptr = Self::pipefd(args); + if fd_ptr.is_null() { + return Err(SystemError::EFAULT); + } else { + let flags = FileMode::from_bits_truncate(args[1] as u32); + do_kernel_pipe2(fd_ptr, flags) + } + } + + fn entry_format(&self, args: &[usize]) -> Vec { + let fd_ptr = Self::pipefd(args); + vec![ + FormattedSyscallParam::new("fd_ptr", format!("{}", fd_ptr as usize)), // Format pointer as hex + FormattedSyscallParam::new("flags", format!("{}", Self::flags(args).bits())), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_PIPE2, SysPipe2Handle); diff --git a/kernel/src/ipc/syscall/sys_restart.rs b/kernel/src/ipc/syscall/sys_restart.rs new file mode 100644 index 00000000..c6dc46f1 --- /dev/null +++ b/kernel/src/ipc/syscall/sys_restart.rs @@ -0,0 +1,49 @@ +use super::super::signal_types::{SigInfo, SigType}; +use crate::{ + alloc::vec::Vec, + arch::ipc::signal::{SigCode, Signal}, + arch::syscall::nr::SYS_RESTART_SYSCALL, + process::{Pid, ProcessManager}, + syscall::table::{FormattedSyscallParam, Syscall}, +}; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; + +pub struct SysRestartHandle; + +/// # SYS_RESTART_SYSCALL 系统调用函数,用于重启被信号中断的系统调用 +/// +/// ## 返回值 +/// +/// 根据被重启的系统调用决定 +pub(super) fn do_kernel_restart_syscall() -> Result { + let restart_block = ProcessManager::current_pcb().restart_block().take(); + if let Some(mut restart_block) = restart_block { + return restart_block.restart_fn.call(&mut restart_block.data); + } else { + // 不应该走到这里,因此kill掉当前进程及同组的进程 + let pid = Pid::new(0); + let sig = Signal::SIGKILL; + let mut info = SigInfo::new(sig, 0, SigCode::Kernel, SigType::Kill(pid)); + + sig.send_signal_info(Some(&mut info), pid) + .expect("Failed to kill "); + return Ok(0); + } +} + +impl Syscall for SysRestartHandle { + fn num_args(&self) -> usize { + 0 // restart_syscall 通常没有参数 + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + Vec::new() // 没有参数,返回空Vec + } + + fn handle(&self, _args: &[usize], _from_user: bool) -> Result { + do_kernel_restart_syscall() + } +} + +declare_syscall!(SYS_RESTART_SYSCALL, SysRestartHandle); diff --git a/kernel/src/ipc/syscall/sys_rt_sigprocmask.rs b/kernel/src/ipc/syscall/sys_rt_sigprocmask.rs new file mode 100644 index 00000000..bf8ca46a --- /dev/null +++ b/kernel/src/ipc/syscall/sys_rt_sigprocmask.rs @@ -0,0 +1,135 @@ +use crate::alloc::vec::Vec; +use crate::{ + arch::ipc::signal::{SigSet, Signal}, + arch::syscall::nr::SYS_RT_SIGPROCMASK, + ipc::signal::{set_sigprocmask, SigHow}, + mm::VirtAddr, + syscall::{ + table::{FormattedSyscallParam, Syscall}, + user_access::{UserBufferReader, UserBufferWriter}, + }, +}; +use core::mem::size_of; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; // 添加 Vec + +pub struct SysRtSigprocmaskHandle; + +/// # SYS_SIGPROCMASK系统调用函数,用于设置或查询当前进程的信号屏蔽字 +/// +/// ## 参数 +/// +/// - `how`: 指示如何修改信号屏蔽字 +/// - `nset`: 新的信号屏蔽字 +/// - `oset`: 旧的信号屏蔽字的指针,由于可以是NULL,所以用Option包装 +/// - `sigsetsize`: 信号集的大小 +/// +/// ## 返回值 +/// +/// 成功:0 +/// 失败:错误码 +/// +/// ## 说明 +/// 根据 https://man7.org/linux/man-pages/man2/sigprocmask.2.html ,传进来的oldset和newset都是指针类型,这里选择传入usize然后转换为u64的指针类型 +pub(super) fn do_kernel_rt_sigprocmask( + how: i32, + newset: usize, + oldset: usize, + sigsetsize: usize, +) -> Result { + // 对应oset传进来一个NULL的情况 + let oset = if oldset == 0 { None } else { Some(oldset) }; + let nset = if newset == 0 { None } else { Some(newset) }; + + if sigsetsize != size_of::() { + return Err(SystemError::EFAULT); + } + + let sighow = SigHow::try_from(how)?; + + let mut new_set = SigSet::default(); + if let Some(nset) = nset { + let reader = UserBufferReader::new( + VirtAddr::new(nset).as_ptr::(), + core::mem::size_of::(), + true, + )?; + + let nset = reader.read_one_from_user::(0)?; + new_set = SigSet::from_bits_truncate(*nset); + // debug!("Get Newset: {}", &new_set.bits()); + let to_remove: SigSet = + >::into(Signal::SIGKILL) | Signal::SIGSTOP.into(); + new_set.remove(to_remove); + } + + let oldset_to_return = set_sigprocmask(sighow, new_set)?; + if let Some(oldset) = oset { + // debug!("Get Oldset to return: {}", &oldset_to_return.bits()); + let mut writer = UserBufferWriter::new( + VirtAddr::new(oldset).as_ptr::(), + core::mem::size_of::(), + true, + )?; + writer.copy_one_to_user::(&oldset_to_return.bits(), 0)?; + } + + Ok(0) +} + +impl SysRtSigprocmaskHandle { + #[inline(always)] + fn how(args: &[usize]) -> i32 { + // 第一个参数是 how + args[0] as i32 + } + + #[inline(always)] + fn nset(args: &[usize]) -> usize { + // 第二个参数是新信号集的指针 + args[1] + } + + #[inline(always)] + fn oset(args: &[usize]) -> usize { + // 第三个参数是旧信号集的指针 + args[2] + } + + #[inline(always)] + fn sigsetsize(args: &[usize]) -> usize { + // 第四个参数是 sigset_t 的大小 + args[3] + } +} + +impl Syscall for SysRtSigprocmaskHandle { + fn num_args(&self) -> usize { + 4 + } + + fn entry_format(&self, args: &[usize]) -> Vec { + let how = Self::how(args); + let nset_ptr = Self::nset(args); + let oset_ptr = Self::oset(args); + let sigsetsize = Self::sigsetsize(args); + + vec![ + FormattedSyscallParam::new("how", format!("{:#x}", how)), + FormattedSyscallParam::new("nset", format!("{:#x}", nset_ptr)), + FormattedSyscallParam::new("oset", format!("{:#x}", oset_ptr)), + FormattedSyscallParam::new("sigsetsize", format!("{}", sigsetsize)), + ] + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let how = Self::how(args); + let nset = Self::nset(args); + let oset = Self::oset(args); + let sigsetsize = Self::sigsetsize(args); + + do_kernel_rt_sigprocmask(how, nset, oset, sigsetsize) + } +} + +declare_syscall!(SYS_RT_SIGPROCMASK, SysRtSigprocmaskHandle); diff --git a/kernel/src/ipc/syscall/sys_shmat.rs b/kernel/src/ipc/syscall/sys_shmat.rs new file mode 100644 index 00000000..526c385e --- /dev/null +++ b/kernel/src/ipc/syscall/sys_shmat.rs @@ -0,0 +1,179 @@ +use crate::alloc::vec::Vec; +use crate::syscall::table::FormattedSyscallParam; +use crate::{ + arch::syscall::nr::SYS_SHMAT, + arch::MMArch, + ipc::shm::{shm_manager_lock, ShmFlags, ShmId}, + libs::align::page_align_up, + mm::{ + allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame}, + page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll}, + syscall::ProtFlags, + ucontext::{AddressSpace, VMA}, + VirtAddr, VmFlags, + }, + syscall::{table::Syscall, user_access::UserBufferReader}, +}; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; + +pub struct SysShmatHandle; + +/// # SYS_SHMAT系统调用函数,用于连接共享内存段 +/// +/// ## 参数 +/// +/// - `id`: 共享内存id +/// - `vaddr`: 连接共享内存的进程虚拟内存区域起始地址 +/// - `shmflg`: 共享内存标志 +/// +/// ## 返回值 +/// +/// 成功:映射到共享内存的虚拟内存区域起始地址 +/// 失败:错误码 +pub(super) fn do_kernel_shmat( + id: ShmId, + vaddr: VirtAddr, + shmflg: ShmFlags, +) -> Result { + let mut shm_manager_guard = shm_manager_lock(); + let current_address_space = AddressSpace::current()?; + let mut address_write_guard = current_address_space.write(); + + let kernel_shm = shm_manager_guard.get_mut(&id).ok_or(SystemError::EINVAL)?; + let size = page_align_up(kernel_shm.size()); + let mut phys = PhysPageFrame::new(kernel_shm.start_paddr()); + let count = PageFrameCount::from_bytes(size).unwrap(); + let r = match vaddr.data() { + // 找到空闲区域并映射到共享内存 + 0 => { + // 找到空闲区域 + let region = address_write_guard + .mappings + .find_free(vaddr, size) + .ok_or(SystemError::EINVAL)?; + let vm_flags = VmFlags::from(shmflg); + let destination = VirtPageFrame::new(region.start()); + let page_flags: EntryFlags = + EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true); + let flusher: PageFlushAll = PageFlushAll::new(); + + // 将共享内存映射到对应虚拟区域 + let vma = VMA::physmap( + phys, + destination, + count, + vm_flags, + page_flags, + &mut address_write_guard.user_mapper.utable, + flusher, + )?; + + // 将VMA加入到当前进程的VMA列表中 + address_write_guard.mappings.insert_vma(vma); + + region.start().data() + } + // 指定虚拟地址 + _ => { + // 获取对应vma + let vma = address_write_guard + .mappings + .contains(vaddr) + .ok_or(SystemError::EINVAL)?; + if vma.lock_irqsave().region().start() != vaddr { + return Err(SystemError::EINVAL); + } + + // 验证用户虚拟内存区域是否有效 + let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?; + + // 必须在取消映射前获取到EntryFlags + let page_flags = address_write_guard + .user_mapper + .utable + .translate(vaddr) + .ok_or(SystemError::EINVAL)? + .1; + + // 取消原映射 + let flusher: PageFlushAll = PageFlushAll::new(); + vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); + + // 将该虚拟内存区域映射到共享内存区域 + let mut page_manager_guard = page_manager_lock_irqsave(); + let mut virt = VirtPageFrame::new(vaddr); + for _ in 0..count.data() { + let r = unsafe { + address_write_guard.user_mapper.utable.map_phys( + virt.virt_address(), + phys.phys_address(), + page_flags, + ) + } + .expect("Failed to map zero, may be OOM error"); + r.flush(); + + // 将vma加入到对应Page的anon_vma + page_manager_guard + .get_unwrap(&phys.phys_address()) + .write_irqsave() + .insert_vma(vma.clone()); + + phys = phys.next(); + virt = virt.next(); + } + + // 更新vma的映射状态 + vma.lock_irqsave().set_mapped(true); + + vaddr.data() + } + }; + + // 更新最后一次连接时间 + kernel_shm.update_atim(); + + // 映射计数增加 + kernel_shm.increase_count(); + + Ok(r) +} + +impl SysShmatHandle { + #[inline(always)] + fn id(args: &[usize]) -> ShmId { + ShmId::new(args[0]) // 更正 ShmIT 为 ShmId + } + + #[inline(always)] + fn vaddr(args: &[usize]) -> VirtAddr { + VirtAddr::new(args[1]) + } + #[inline(always)] + fn shmflg(args: &[usize]) -> ShmFlags { + ShmFlags::from_bits_truncate(args[2] as u32) + } +} + +impl Syscall for SysShmatHandle { + fn num_args(&self) -> usize { + 3 + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("id", format!("{}", Self::id(args).data())), + FormattedSyscallParam::new("vaddr", format!("{}", Self::vaddr(args).data())), + FormattedSyscallParam::new("shmflg", format!("{}", Self::shmflg(args).bits())), + ] + } + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let id = Self::id(args); + let vaddr = Self::vaddr(args); + let shmflg = Self::shmflg(args); + do_kernel_shmat(id, vaddr, shmflg) + } +} + +declare_syscall!(SYS_SHMAT, SysShmatHandle); diff --git a/kernel/src/ipc/syscall/sys_shmctl.rs b/kernel/src/ipc/syscall/sys_shmctl.rs new file mode 100644 index 00000000..5b42d1b1 --- /dev/null +++ b/kernel/src/ipc/syscall/sys_shmctl.rs @@ -0,0 +1,92 @@ +use crate::alloc::vec::Vec; +use crate::{ + arch::syscall::nr::SYS_SHMCTL, + ipc::shm::{shm_manager_lock, ShmCtlCmd, ShmId}, + syscall::table::{FormattedSyscallParam, Syscall}, +}; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; + +pub struct SysShmctlHandle; + +/// # SYS_SHMCTL系统调用函数,用于管理共享内存段 +/// +/// ## 参数 +/// +/// - `id`: 共享内存id +/// - `cmd`: 操作码 +/// - `user_buf`: 用户缓冲区 +/// - `from_user`: buf_vaddr是否来自用户地址空间 +/// +/// ## 返回值 +/// +/// 成功:0 +/// 失败:错误码 +pub(super) fn do_kernel_shmctl( + id: ShmId, + cmd: ShmCtlCmd, + user_buf: *const u8, + from_user: bool, +) -> Result { + let mut shm_manager_guard = shm_manager_lock(); + + match cmd { + // 查看共享内存元信息 + ShmCtlCmd::IpcInfo => shm_manager_guard.ipc_info(user_buf, from_user), + // 查看共享内存使用信息 + ShmCtlCmd::ShmInfo => shm_manager_guard.shm_info(user_buf, from_user), + // 查看id对应的共享内存信息 + ShmCtlCmd::ShmStat | ShmCtlCmd::ShmtStatAny | ShmCtlCmd::IpcStat => { + shm_manager_guard.shm_stat(id, cmd, user_buf, from_user) + } + // 设置KernIpcPerm + ShmCtlCmd::IpcSet => shm_manager_guard.ipc_set(id, user_buf, from_user), + // 将共享内存段设置为可回收状态 + ShmCtlCmd::IpcRmid => shm_manager_guard.ipc_rmid(id), + // 锁住共享内存段,不允许内存置换 + ShmCtlCmd::ShmLock => shm_manager_guard.shm_lock(id), + // 解锁共享内存段,允许内存置换 + ShmCtlCmd::ShmUnlock => shm_manager_guard.shm_unlock(id), + // 无效操作码 + ShmCtlCmd::Default => Err(SystemError::EINVAL), + } +} + +impl SysShmctlHandle { + #[inline(always)] + fn id(args: &[usize]) -> ShmId { + ShmId::new(args[0]) // Assuming ShmId::new takes usize or can infer from args[0] + } + + #[inline(always)] + fn cmd(args: &[usize]) -> ShmCtlCmd { + ShmCtlCmd::from(args[1]) + } + + #[inline(always)] + fn user_buf(args: &[usize]) -> *const u8 { + args[2] as *const u8 // Assuming args[2] is a pointer to user buffer + } +} + +impl Syscall for SysShmctlHandle { + fn num_args(&self) -> usize { + 3 + } + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("shmid", format!("{}", Self::id(args).data())), + FormattedSyscallParam::new("cmd", format!("{}", Self::cmd(args))), + FormattedSyscallParam::new("buf", format!("{:#x}", Self::user_buf(args) as usize)), + ] + } + + fn handle(&self, args: &[usize], from_user: bool) -> Result { + let id = Self::id(args); + let cmd = Self::cmd(args); + let user_buf = Self::user_buf(args); + do_kernel_shmctl(id, cmd, user_buf, from_user) + } +} + +declare_syscall!(SYS_SHMCTL, SysShmctlHandle); diff --git a/kernel/src/ipc/syscall/sys_shmdt.rs b/kernel/src/ipc/syscall/sys_shmdt.rs new file mode 100644 index 00000000..f4ac4202 --- /dev/null +++ b/kernel/src/ipc/syscall/sys_shmdt.rs @@ -0,0 +1,67 @@ +use crate::mm::page::PageFlushAll; +use crate::syscall::table::FormattedSyscallParam; +use crate::{ + arch::syscall::nr::SYS_SHMDT, + arch::MMArch, + mm::{ucontext::AddressSpace, VirtAddr}, + syscall::table::Syscall, +}; +use alloc::vec::Vec; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; + +pub struct SysShmdtHandle; + +impl SysShmdtHandle { + #[inline(always)] + fn vaddr(args: &[usize]) -> VirtAddr { + VirtAddr::new(args[0]) + } +} + +impl Syscall for SysShmdtHandle { + fn num_args(&self) -> usize { + 1 + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "vaddr", + format!("{}", Self::vaddr(args).data()), + )] + } + /// # SYS_SHMDT系统调用函数,用于取消对共享内存的连接 + /// + /// ## 参数 + /// + /// - `vaddr`: 需要取消映射的虚拟内存区域起始地址 + /// + /// ## 返回值 + /// + /// 成功:0 + /// 失败:错误码 + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let vaddr = Self::vaddr(args); + let current_address_space = AddressSpace::current()?; + let mut address_write_guard = current_address_space.write(); + + // 获取vma + let vma = address_write_guard + .mappings + .contains(vaddr) + .ok_or(SystemError::EINVAL)?; + + // 判断vaddr是否为起始地址 + if vma.lock_irqsave().region().start() != vaddr { + return Err(SystemError::EINVAL); + } + + // 取消映射 + let flusher: PageFlushAll = PageFlushAll::new(); + vma.unmap(&mut address_write_guard.user_mapper.utable, flusher); + + return Ok(0); + } +} + +declare_syscall!(SYS_SHMDT, SysShmdtHandle); diff --git a/kernel/src/ipc/syscall/sys_shmget.rs b/kernel/src/ipc/syscall/sys_shmget.rs new file mode 100644 index 00000000..1d0e9903 --- /dev/null +++ b/kernel/src/ipc/syscall/sys_shmget.rs @@ -0,0 +1,110 @@ +use crate::alloc::vec::Vec; +use crate::syscall::table::FormattedSyscallParam; +use crate::{ + arch::syscall::nr::SYS_SHMGET, + ipc::shm::{shm_manager_lock, ShmFlags, ShmKey, IPC_PRIVATE}, + syscall::table::Syscall, +}; +use log::error; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; + +pub struct SysShmgetHandle; + +/// # SYS_SHMGET系统调用函数,用于获取共享内存 +/// +/// ## 参数 +/// +/// - `key`: 共享内存键值 +/// - `size`: 共享内存大小(bytes) +/// - `shmflg`: 共享内存标志 +/// +/// ## 返回值 +/// +/// 成功:共享内存id +/// 失败:错误码 +pub(super) fn do_kernel_shmget( + key: ShmKey, + size: usize, + shmflg: ShmFlags, +) -> Result { + // 暂不支持巨页 + if shmflg.contains(ShmFlags::SHM_HUGETLB) { + error!("shmget: not support huge page"); + return Err(SystemError::ENOSYS); + } + + let mut shm_manager_guard = shm_manager_lock(); + match key { + // 创建共享内存段 + IPC_PRIVATE => shm_manager_guard.add(key, size, shmflg), + _ => { + // 查找key对应的共享内存段是否存在 + let id = shm_manager_guard.contains_key(&key); + if let Some(id) = id { + // 不能重复创建 + if shmflg.contains(ShmFlags::IPC_CREAT | ShmFlags::IPC_EXCL) { + return Err(SystemError::EEXIST); + } + + // key值存在,说明有对应共享内存,返回该共享内存id + return Ok(id.data()); + } else { + // key不存在且shm_flags不包含IPC_CREAT创建IPC对象标志,则返回错误码 + if !shmflg.contains(ShmFlags::IPC_CREAT) { + return Err(SystemError::ENOENT); + } + + // 存在创建IPC对象标志 + return shm_manager_guard.add(key, size, shmflg); + } + } + } +} + +impl SysShmgetHandle { + #[inline(always)] + fn key(args: &[usize]) -> ShmKey { + // 第一个参数是共享内存的key + // In the old code: ShmKey::new(args[0]) + // ShmKey is likely a type alias for i32 or similar, args[0] is usize + ShmKey::new(args[0]) // Assuming ShmKey::new takes i32 + } + + #[inline(always)] + fn size(args: &[usize]) -> usize { + // 第二个参数是共享内存的大小 + args[1] + } + + #[inline(always)] + fn shmflg(args: &[usize]) -> ShmFlags { + // 第三个参数是共享内存的标志 + // In the old code: ShmFlags::from_bits_truncate(args[2] as u32) + ShmFlags::from_bits_truncate(args[2] as u32) + } +} + +impl Syscall for SysShmgetHandle { + fn num_args(&self) -> usize { + 3 // key, size, shmflg + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let key = Self::key(args); + let size = Self::size(args); + let shmflg = Self::shmflg(args); + do_kernel_shmget(key, size, shmflg) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("key", format!("{}", Self::key(args).data())), + // 使用 format! 宏将 usize 类型的 size 转换为 String + FormattedSyscallParam::new("size", format!("{}", Self::size(args))), + FormattedSyscallParam::new("shmflg", format!("{:#x}", Self::shmflg(args).bits())), + ] + } +} + +declare_syscall!(SYS_SHMGET, SysShmgetHandle); diff --git a/kernel/src/ipc/syscall/sys_sigaction.rs b/kernel/src/ipc/syscall/sys_sigaction.rs new file mode 100644 index 00000000..9365dfdc --- /dev/null +++ b/kernel/src/ipc/syscall/sys_sigaction.rs @@ -0,0 +1,191 @@ +use super::super::signal_types::{ + SaHandlerType, Sigaction, SigactionType, UserSigaction, USER_SIG_DFL, USER_SIG_ERR, + USER_SIG_IGN, +}; +use crate::arch::syscall::nr::SYS_RT_SIGACTION; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use crate::{ + arch::ipc::signal::{SigFlags, SigSet, Signal}, + mm::VirtAddr, + process::ProcessManager, + syscall::user_access::UserBufferWriter, +}; +use alloc::vec::Vec; +use core::ffi::{c_int, c_void}; +use log::error; +use system_error::SystemError; + +pub struct SysSigactionHandle; + +/// 通用信号注册函数 +/// +/// ## 参数 +/// +/// - `sig` 信号的值 +/// - `act` 用户空间传入的 Sigaction 指针 +/// - `old_act` 用户空间传入的用来保存旧 Sigaction 的指针 +/// - `from_user` 用来标识这个函数调用是否来自用户空间 +/// +/// @return int 错误码 +#[no_mangle] +pub(super) fn do_kernel_sigaction( + sig: c_int, + new_act: usize, + old_act: usize, + from_user: bool, +) -> Result { + // 请注意:用户态传进来的user_sigaction结构体类型,请注意,这个结构体与内核实际的不一样 + let act: *mut UserSigaction = new_act as *mut UserSigaction; + let old_act = old_act as *mut UserSigaction; + let mut new_ka: Sigaction = Default::default(); + let mut old_sigaction: Sigaction = Default::default(); + // 如果传入的,新的sigaction不为空 + if !act.is_null() { + // 如果参数的范围不在用户空间,则返回错误 + let r = UserBufferWriter::new(act, core::mem::size_of::(), from_user); + if r.is_err() { + return Err(SystemError::EFAULT); + } + let mask: SigSet = unsafe { (*act).mask }; + let input_sighandler = unsafe { (*act).handler as u64 }; + match input_sighandler { + USER_SIG_DFL => { + new_ka = Sigaction::DEFAULT_SIGACTION; + *new_ka.flags_mut() = unsafe { (*act).flags }; + new_ka.set_restorer(None); + } + + USER_SIG_IGN => { + new_ka = Sigaction::DEFAULT_SIGACTION_IGNORE; + *new_ka.flags_mut() = unsafe { (*act).flags }; + + new_ka.set_restorer(None); + } + _ => { + // 从用户空间获得sigaction结构体 + // TODO mask是default还是用户空间传入 + new_ka = Sigaction::new( + SigactionType::SaHandler(SaHandlerType::Customized(unsafe { + VirtAddr::new((*act).handler as usize) + })), + unsafe { (*act).flags }, + SigSet::default(), + unsafe { Some(VirtAddr::new((*act).restorer as usize)) }, + ); + } + } + + // TODO 如果为空,赋默认值? + // debug!("new_ka={:?}", new_ka); + // 如果用户手动给了sa_restorer,那么就置位SA_FLAG_RESTORER,否则报错。(用户必须手动指定restorer) + if new_ka.restorer().is_some() { + new_ka.flags_mut().insert(SigFlags::SA_RESTORER); + } else if new_ka.action().is_customized() { + error!( + "pid:{:?}: in sys_sigaction: User must manually sprcify a sa_restorer for signal {}.", + ProcessManager::current_pcb().pid(), + sig + ); + return Err(SystemError::EINVAL); + } + *new_ka.mask_mut() = mask; + } + + let sig = Signal::from(sig); + // 如果给出的信号值不合法 + if sig == Signal::INVALID { + return Err(SystemError::EINVAL); + } + + let retval = super::super::signal::do_sigaction( + sig, + if act.is_null() { + None + } else { + Some(&mut new_ka) + }, + if old_act.is_null() { + None + } else { + Some(&mut old_sigaction) + }, + ); + + // + if (retval == Ok(())) && (!old_act.is_null()) { + let r = UserBufferWriter::new(old_act, core::mem::size_of::(), from_user); + if r.is_err() { + return Err(SystemError::EFAULT); + } + + let sigaction_handler = match old_sigaction.action() { + SigactionType::SaHandler(handler) => { + if let SaHandlerType::Customized(hand) = handler { + hand + } else if handler.is_sig_ignore() { + VirtAddr::new(USER_SIG_IGN as usize) + } else if handler.is_sig_error() { + VirtAddr::new(USER_SIG_ERR as usize) + } else { + VirtAddr::new(USER_SIG_DFL as usize) + } + } + SigactionType::SaSigaction(_) => { + error!("unsupported type: SaSigaction"); + VirtAddr::new(USER_SIG_DFL as usize) + } + }; + + unsafe { + (*old_act).handler = sigaction_handler.data() as *mut c_void; + (*old_act).flags = old_sigaction.flags(); + (*old_act).mask = old_sigaction.mask(); + if old_sigaction.restorer().is_some() { + (*old_act).restorer = old_sigaction.restorer().unwrap().data() as *mut c_void; + } + } + } + return retval.map(|_| 0); +} + +impl SysSigactionHandle { + #[inline(always)] + fn sig(args: &[usize]) -> c_int { + // 第一个参数是信号值 + args[0] as c_int + } + #[inline(always)] + fn act(args: &[usize]) -> usize { + // 第二个参数是用户空间传入的 Sigaction 指针 + args[1] + } + #[inline(always)] + fn old_act(args: &[usize]) -> usize { + // 第三个参数是用户空间传入的用来保存旧 Sigaction 的指针 + args[2] + } +} + +impl Syscall for SysSigactionHandle { + fn num_args(&self) -> usize { + 3 + } + + #[no_mangle] + fn handle(&self, args: &[usize], from_user: bool) -> Result { + let sig = Self::sig(args); + let act = Self::act(args); + let old_act = Self::old_act(args); + + do_kernel_sigaction(sig, act, old_act, from_user) + } + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("sig", format!("{}", Self::sig(args))), + FormattedSyscallParam::new("act", format!("{:#x}", Self::act(args))), + FormattedSyscallParam::new("old_act", format!("{:#x}", Self::old_act(args))), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_RT_SIGACTION, SysSigactionHandle); diff --git a/kernel/src/ipc/syscall/sys_sigpending.rs b/kernel/src/ipc/syscall/sys_sigpending.rs new file mode 100644 index 00000000..153cf8f6 --- /dev/null +++ b/kernel/src/ipc/syscall/sys_sigpending.rs @@ -0,0 +1,76 @@ +use crate::{ + alloc::vec::Vec, + arch::ipc::signal::SigSet, + arch::syscall::nr::SYS_RT_SIGPENDING, + process::ProcessManager, + syscall::{ + table::{FormattedSyscallParam, Syscall}, + user_access::UserBufferWriter, + }, +}; +use core::mem::size_of; +use syscall_table_macros::declare_syscall; +use system_error::SystemError; + +pub struct SysSigpendingHandle; + +#[inline(never)] +pub(super) fn do_kernel_rt_sigpending( + user_sigset_ptr: usize, + sigsetsize: usize, +) -> Result { + if sigsetsize != size_of::() { + return Err(SystemError::EINVAL); + } + + let mut user_buffer_writer = + UserBufferWriter::new(user_sigset_ptr as *mut SigSet, size_of::(), true)?; + + let pcb = ProcessManager::current_pcb(); + let siginfo_guard = pcb.sig_info_irqsave(); + let pending_set = siginfo_guard.sig_pending().signal(); + let shared_pending_set = siginfo_guard.sig_shared_pending().signal(); + let blocked_set = *siginfo_guard.sig_blocked(); + drop(siginfo_guard); + + let mut result = pending_set.union(shared_pending_set); + result = result.difference(blocked_set); + + user_buffer_writer.copy_one_to_user(&result, 0)?; + + Ok(0) +} + +impl Syscall for SysSigpendingHandle { + fn num_args(&self) -> usize { + 2 // sigpending(sigset_t *set) + } + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("user_sigset_ptr", format!("{}", args[0])), + FormattedSyscallParam::new("sigsetsize", format!("{}", args[1])), + ] + } + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let user_sigset = SysSigpendingHandle::user_sigset_ptr(args); + let size = SysSigpendingHandle::sigsetsize(args); + + do_kernel_rt_sigpending(user_sigset, size) + } +} + +impl SysSigpendingHandle { + #[inline(always)] + fn user_sigset_ptr(args: &[usize]) -> usize { + // 第一个参数是用户空间信号集的指针 + args[0] + } + + #[inline(always)] + fn sigsetsize(args: &[usize]) -> usize { + // 第二个参数是 sigset_t 的大小 + args[1] + } +} + +declare_syscall!(SYS_RT_SIGPENDING, SysSigpendingHandle); diff --git a/kernel/src/process/exit.rs b/kernel/src/process/exit.rs index cee1ce1f..4549e54b 100644 --- a/kernel/src/process/exit.rs +++ b/kernel/src/process/exit.rs @@ -4,7 +4,7 @@ use system_error::SystemError; use crate::{ arch::ipc::signal::{SigChildCode, Signal}, - ipc::syscall::PidConverter, + ipc::syscall::sys_kill::PidConverter, sched::{schedule, SchedMode}, syscall::user_access::UserBufferWriter, time::{sleep::nanosleep, Duration}, diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 2e4b6de2..a6c3ef0d 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -67,7 +67,7 @@ use crate::{ cpu::{AtomicProcessorId, ProcessorId}, kick_cpu, }, - syscall::{user_access::clear_user, Syscall}, + syscall::user_access::clear_user, }; use timer::AlarmTimer; @@ -386,7 +386,7 @@ impl ProcessManager { return; } let parent_pcb = r.unwrap(); - let r = Syscall::kill_process(parent_pcb.pid(), Signal::SIGCHLD); + let r = crate::ipc::kill::kill_process(parent_pcb.pid(), Signal::SIGCHLD); if r.is_err() { warn!( "failed to send kill signal to {:?}'s parent pcb {:?}", diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index bb798877..50e68404 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -6,7 +6,6 @@ use core::{ use crate::{ arch::syscall::nr::*, filesystem::vfs::syscall::PosixStatfs, - ipc::shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey}, libs::{futex::constant::FutexFlag, rand::GRandFlags}, mm::{page::PAGE_4K_SIZE, syscall::MremapFlags}, net::syscall::MsgHdr, @@ -29,7 +28,6 @@ use crate::{ arch::{interrupt::TrapFrame, MMArch}, filesystem::vfs::{ fcntl::{AtFlags, FcntlCommand}, - file::FileMode, syscall::{ModeType, UtimensFlags}, MAX_PATHLEN, }, @@ -314,27 +312,6 @@ impl Syscall { } SYS_CLOCK => Self::clock(), - #[cfg(target_arch = "x86_64")] - SYS_PIPE => { - let pipefd: *mut i32 = args[0] as *mut c_int; - if pipefd.is_null() { - Err(SystemError::EFAULT) - } else { - Self::pipe2(pipefd, FileMode::empty()) - } - } - - SYS_PIPE2 => { - let pipefd: *mut i32 = args[0] as *mut c_int; - let arg1 = args[1]; - if pipefd.is_null() { - Err(SystemError::EFAULT) - } else { - let flags = FileMode::from_bits_truncate(arg1 as u32); - Self::pipe2(pipefd, flags) - } - } - SYS_UNLINKAT => { let dirfd = args[0] as i32; let path = args[1] as *const u8; @@ -383,20 +360,6 @@ impl Syscall { let path = args[0] as *const u8; Self::unlink(path) } - SYS_KILL => { - let pid = args[0] as i32; - let sig = args[1] as c_int; - // debug!("KILL SYSCALL RECEIVED"); - Self::kill(pid, sig) - } - - SYS_RT_SIGACTION => { - let sig = args[0] as c_int; - let act = args[1]; - let old_act = args[2]; - Self::sigaction(sig, act, old_act, frame.is_from_user()) - } - SYS_GETPID => Self::getpid().map(|pid| pid.into()), SYS_SCHED => { @@ -794,14 +757,6 @@ impl Syscall { Self::setpgid(pid, pgid) } - SYS_RT_SIGPROCMASK => { - let how = args[0] as i32; - let nset = args[1]; - let oset = args[2]; - let sigsetsize = args[3]; - Self::rt_sigprocmask(how, nset, oset, sigsetsize) - } - SYS_TKILL => { warn!("SYS_TKILL has not yet been implemented"); Ok(0) @@ -1053,33 +1008,6 @@ impl Syscall { let second = args[0] as u32; Self::alarm(second) } - - SYS_SHMGET => { - let key = ShmKey::new(args[0]); - let size = args[1]; - let shmflg = ShmFlags::from_bits_truncate(args[2] as u32); - - Self::shmget(key, size, shmflg) - } - SYS_SHMAT => { - let id = ShmId::new(args[0]); - let vaddr = VirtAddr::new(args[1]); - let shmflg = ShmFlags::from_bits_truncate(args[2] as u32); - - Self::shmat(id, vaddr, shmflg) - } - SYS_SHMDT => { - let vaddr = VirtAddr::new(args[0]); - Self::shmdt(vaddr) - } - SYS_SHMCTL => { - let id = ShmId::new(args[0]); - let cmd = ShmCtlCmd::from(args[1]); - let user_buf = args[2] as *const u8; - let from_user = frame.is_from_user(); - - Self::shmctl(id, cmd, user_buf, from_user) - } SYS_MSYNC => { let start = page_align_up(args[0]); let len = page_align_up(args[1]); @@ -1131,8 +1059,7 @@ impl Syscall { } #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] SYS_SETRLIMIT => Ok(0), - SYS_RESTART_SYSCALL => Self::restart_syscall(), - SYS_RT_SIGPENDING => Self::rt_sigpending(args[0], args[1]), + SYS_RT_SIGTIMEDWAIT => { log::warn!("SYS_RT_SIGTIMEDWAIT has not yet been implemented"); Ok(0)