refactor(ipc): Refactor the syscalls in ipc (#1183)

* feat(ipc): 完成对ipc的系统调用的重构

* refactor(ipc): 优化结构

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* feat: fmt

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

---------

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
Co-authored-by: Vitus <zhzvitus@gmail.com>
Co-authored-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
This commit is contained in:
Vitus 2025-05-30 20:52:44 +08:00 committed by GitHub
parent 6ac8e1f0cd
commit 5db1f9ad54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1241 additions and 756 deletions

View File

@ -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::<SigFrame>(), 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");
}

View File

@ -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);

View File

@ -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) {

44
kernel/src/ipc/kill.rs Normal file
View File

@ -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<usize, SystemError> {
// 初始化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<usize, SystemError> {
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<usize, SystemError> {
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)
}

View File

@ -1,4 +1,5 @@
pub mod generic_signal;
pub mod kill;
pub mod pipe;
pub mod shm;
pub mod signal;

View File

@ -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<SpinLock<ShmManager>> = None;
/// 用于创建新的私有IPC对象
@ -104,6 +104,23 @@ impl From<usize> 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

View File

@ -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<usize, SystemError> {
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::<i32>(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<usize, SystemError> {
// 初始化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<usize, SystemError> {
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<usize, SystemError> {
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<usize, SystemError> {
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<usize, SystemError> {
// 请注意用户态传进来的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::<Sigaction>(), 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::<UserSigaction>(), 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<usize, SystemError> {
// 暂不支持巨页
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<usize, SystemError> {
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<MMArch> =
EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true);
let flusher: PageFlushAll<MMArch> = 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<MMArch> = 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<usize, SystemError> {
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<MMArch> = 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<usize, SystemError> {
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<usize, SystemError> {
// 对应oset传进来一个NULL的情况
let oset = if oldset == 0 { None } else { Some(oldset) };
let nset = if newset == 0 { None } else { Some(newset) };
if sigsetsize != size_of::<SigSet>() {
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::<u64>(),
core::mem::size_of::<u64>(),
true,
)?;
let nset = reader.read_one_from_user::<u64>(0)?;
new_set = SigSet::from_bits_truncate(*nset);
// debug!("Get Newset: {}", &new_set.bits());
let to_remove: SigSet =
<Signal as Into<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::<u64>(),
core::mem::size_of::<u64>(),
true,
)?;
writer.copy_one_to_user::<u64>(&oldset_to_return.bits(), 0)?;
}
Ok(0)
}
pub fn restart_syscall() -> Result<usize, SystemError> {
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<usize, SystemError> {
if sigsetsize != size_of::<SigSet>() {
return Err(SystemError::EINVAL);
}
let mut user_buffer_writer =
UserBufferWriter::new(user_sigset_ptr as *mut SigSet, size_of::<SigSet>(), 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)
}
}

View File

@ -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;

View File

@ -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<usize, SystemError> {
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<FormattedSyscallParam> {
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);

View File

@ -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<usize, SystemError> {
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<FormattedSyscallParam> {
let fd_ptr = Self::pipefd(args);
vec![FormattedSyscallParam::new(
"fd_ptr",
format!("{}", fd_ptr as usize),
)]
}
}
syscall_table_macros::declare_syscall!(SYS_PIPE, SysPipeHandle);

View File

@ -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<usize, SystemError> {
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::<i32>(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<usize, SystemError> {
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<FormattedSyscallParam> {
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);

View File

@ -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<usize, SystemError> {
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<FormattedSyscallParam> {
Vec::new() // 没有参数返回空Vec
}
fn handle(&self, _args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
do_kernel_restart_syscall()
}
}
declare_syscall!(SYS_RESTART_SYSCALL, SysRestartHandle);

View File

@ -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<usize, SystemError> {
// 对应oset传进来一个NULL的情况
let oset = if oldset == 0 { None } else { Some(oldset) };
let nset = if newset == 0 { None } else { Some(newset) };
if sigsetsize != size_of::<SigSet>() {
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::<u64>(),
core::mem::size_of::<u64>(),
true,
)?;
let nset = reader.read_one_from_user::<u64>(0)?;
new_set = SigSet::from_bits_truncate(*nset);
// debug!("Get Newset: {}", &new_set.bits());
let to_remove: SigSet =
<Signal as Into<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::<u64>(),
core::mem::size_of::<u64>(),
true,
)?;
writer.copy_one_to_user::<u64>(&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<FormattedSyscallParam> {
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<usize, SystemError> {
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);

View File

@ -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<usize, SystemError> {
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<MMArch> =
EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true);
let flusher: PageFlushAll<MMArch> = 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<MMArch> = 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<FormattedSyscallParam> {
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<usize, SystemError> {
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);

View File

@ -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<usize, SystemError> {
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<FormattedSyscallParam> {
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<usize, SystemError> {
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);

View File

@ -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<FormattedSyscallParam> {
vec![FormattedSyscallParam::new(
"vaddr",
format!("{}", Self::vaddr(args).data()),
)]
}
/// # SYS_SHMDT系统调用函数用于取消对共享内存的连接
///
/// ## 参数
///
/// - `vaddr`: 需要取消映射的虚拟内存区域起始地址
///
/// ## 返回值
///
/// 成功0
/// 失败:错误码
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
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<MMArch> = PageFlushAll::new();
vma.unmap(&mut address_write_guard.user_mapper.utable, flusher);
return Ok(0);
}
}
declare_syscall!(SYS_SHMDT, SysShmdtHandle);

View File

@ -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<usize, SystemError> {
// 暂不支持巨页
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<usize, SystemError> {
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<FormattedSyscallParam> {
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);

View File

@ -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<usize, SystemError> {
// 请注意用户态传进来的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::<Sigaction>(), 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::<UserSigaction>(), 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<usize, SystemError> {
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<FormattedSyscallParam> {
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);

View File

@ -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<usize, SystemError> {
if sigsetsize != size_of::<SigSet>() {
return Err(SystemError::EINVAL);
}
let mut user_buffer_writer =
UserBufferWriter::new(user_sigset_ptr as *mut SigSet, size_of::<SigSet>(), 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<FormattedSyscallParam> {
vec![
FormattedSyscallParam::new("user_sigset_ptr", format!("{}", args[0])),
FormattedSyscallParam::new("sigsetsize", format!("{}", args[1])),
]
}
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
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);

View File

@ -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},

View File

@ -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 {:?}",

View File

@ -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)