123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- 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,
- libs::spinlock::SpinLock,
- mm::{
- allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
- page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
- syscall::ProtFlags,
- ucontext::{AddressSpace, VMA},
- VirtAddr, VmFlags,
- },
- process::{Pid, ProcessManager},
- syscall::{
- user_access::{UserBufferReader, UserBufferWriter},
- Syscall,
- },
- };
- use super::{
- pipe::{LockedPipeInode, PipeFsPrivateData},
- shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey},
- signal_types::{
- SaHandlerType, SigInfo, SigType, Sigaction, SigactionType, UserSigaction, USER_SIG_DFL,
- USER_SIG_ERR, USER_SIG_IGN,
- },
- };
- 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(pid: Pid, sig: c_int) -> Result<usize, SystemError> {
- let sig = Signal::from(sig);
- if sig == Signal::INVALID {
- // 传入的signal数值不合法
- warn!("Not a valid signal number");
- return Err(SystemError::EINVAL);
- }
- // 初始化signal info
- let mut info = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(pid));
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
- let retval = sig
- .send_signal_info(Some(&mut info), pid)
- .map(|x| x as usize);
- 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().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 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()
- .insert_vma(vma.clone());
- phys = phys.next();
- virt = virt.next();
- }
- // 更新vma的映射状态
- vma.lock().set_mapped(true);
- vaddr.data()
- }
- };
- // 更新最后一次连接时间
- kernel_shm.update_atim();
- 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().region().start() != vaddr {
- return Err(SystemError::EINVAL);
- }
- // 获取映射的物理地址
- let paddr = address_write_guard
- .user_mapper
- .utable
- .translate(vaddr)
- .ok_or(SystemError::EINVAL)?
- .0;
- // 如果物理页的shm_id为None,代表不是共享页
- let page_manager_guard = page_manager_lock_irqsave();
- let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?;
- let shm_id = page.read().shm_id().ok_or(SystemError::EINVAL)?;
- drop(page_manager_guard);
- // 获取对应共享页管理信息
- let mut shm_manager_guard = shm_manager_lock();
- let kernel_shm = shm_manager_guard
- .get_mut(&shm_id)
- .ok_or(SystemError::EINVAL)?;
- // 更新最后一次断开连接时间
- kernel_shm.update_dtim();
- drop(shm_manager_guard);
- // 取消映射
- 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),
- }
- }
- }
|