From 6fc066ac11d2f9a3ac629d57487a6144fda1ac63 Mon Sep 17 00:00:00 2001 From: Jomo <2512364506@qq.com> Date: Sun, 7 Apr 2024 14:04:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0SystemV=E5=85=B1=E4=BA=AB?= =?UTF-8?q?=E5=86=85=E5=AD=98=20(#690)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 实现SystemV共享内存 * 测试shm * 添加测试程序 * 完善细节 * 修正shm的时间数据错误的问题 * fix: devfs的metadata权限为0x777的错误 --------- Co-authored-by: longjin --- kernel/src/arch/x86_64/mm/mod.rs | 3 +- kernel/src/driver/disk/ahci/ahci_inode.rs | 8 +- .../driver/input/ps2_mouse/ps_mouse_device.rs | 8 +- kernel/src/driver/keyboard/ps2_keyboard.rs | 8 +- kernel/src/driver/net/dma.rs | 4 +- kernel/src/driver/rtc/class.rs | 4 +- kernel/src/driver/rtc/mod.rs | 6 +- kernel/src/driver/virtio/virtio_impl.rs | 4 +- kernel/src/filesystem/devfs/mod.rs | 14 +- kernel/src/filesystem/devfs/null_dev.rs | 8 +- kernel/src/filesystem/devfs/zero_dev.rs | 8 +- kernel/src/filesystem/devpts/mod.rs | 10 +- kernel/src/filesystem/fat/fs.rs | 14 +- kernel/src/filesystem/kernfs/mod.rs | 14 +- kernel/src/filesystem/procfs/log.rs | 6 +- kernel/src/filesystem/procfs/mod.rs | 14 +- kernel/src/filesystem/ramfs/mod.rs | 20 +- kernel/src/filesystem/vfs/mod.rs | 20 +- kernel/src/filesystem/vfs/syscall.rs | 30 +- kernel/src/ipc/mod.rs | 1 + kernel/src/ipc/pipe.rs | 8 +- kernel/src/ipc/shm.rs | 658 ++++++++++++++++++ kernel/src/ipc/syscall.rs | 279 +++++++- kernel/src/libs/futex/futex.rs | 4 +- kernel/src/libs/futex/syscall.rs | 4 +- kernel/src/libs/printk.rs | 4 +- kernel/src/mm/allocator/page_frame.rs | 21 +- kernel/src/mm/init.rs | 3 + kernel/src/mm/page.rs | 47 +- kernel/src/mm/syscall.rs | 23 + kernel/src/mm/ucontext.rs | 38 +- kernel/src/net/event_poll/mod.rs | 4 +- kernel/src/net/event_poll/syscall.rs | 6 +- kernel/src/process/resource.rs | 6 +- kernel/src/syscall/mod.rs | 46 +- kernel/src/time/mod.rs | 35 +- kernel/src/time/sleep.rs | 12 +- kernel/src/time/syscall.rs | 17 +- kernel/src/time/timekeep.rs | 4 +- kernel/src/time/timekeeping.rs | 24 +- kernel/src/virt/kvm/kvm_dev.rs | 8 +- kernel/src/virt/kvm/vcpu_dev.rs | 8 +- kernel/src/virt/kvm/vm_dev.rs | 8 +- user/apps/test_shm/.gitignore | 3 + user/apps/test_shm/Makefile | 25 + user/apps/test_shm/receiver.c | 40 ++ user/apps/test_shm/sender.c | 46 ++ user/apps/test_shm/test_info.c | 161 +++++ user/dadk/config/test_shm-0.1.0.dadk | 23 + 49 files changed, 1567 insertions(+), 202 deletions(-) create mode 100644 kernel/src/ipc/shm.rs create mode 100644 user/apps/test_shm/.gitignore create mode 100644 user/apps/test_shm/Makefile create mode 100644 user/apps/test_shm/receiver.c create mode 100644 user/apps/test_shm/sender.c create mode 100644 user/apps/test_shm/test_info.c create mode 100644 user/dadk/config/test_shm-0.1.0.dadk diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 51341f083..b95195969 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -602,7 +602,8 @@ pub fn test_buddy() { pub struct LockedFrameAllocator; impl FrameAllocator for LockedFrameAllocator { - unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { + unsafe fn allocate(&mut self, mut count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { + count = count.next_power_of_two(); if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { return allocator.allocate(count); } else { diff --git a/kernel/src/driver/disk/ahci/ahci_inode.rs b/kernel/src/driver/disk/ahci/ahci_inode.rs index b51cb66f5..4805dc9ab 100644 --- a/kernel/src/driver/disk/ahci/ahci_inode.rs +++ b/kernel/src/driver/disk/ahci/ahci_inode.rs @@ -7,7 +7,7 @@ use crate::filesystem::vfs::{ core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, }; use crate::libs::spinlock::SpinLockGuard; -use crate::{libs::spinlock::SpinLock, time::TimeSpec}; +use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec}; use alloc::{ string::String, sync::{Arc, Weak}, @@ -47,9 +47,9 @@ impl LockedAhciInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::BlockDevice, // 文件夹,block设备,char设备 mode: ModeType::from_bits_truncate(0o666), nlinks: 1, diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs index c19380334..ae16bcde4 100644 --- a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs @@ -38,7 +38,7 @@ use crate::{ rwlock::{RwLockReadGuard, RwLockWriteGuard}, spinlock::{SpinLock, SpinLockGuard}, }, - time::TimeSpec, + time::PosixTimeSpec, }; static mut PS2_MOUSE_DEVICE: Option> = None; @@ -199,9 +199,9 @@ impl Ps2MouseDevice { size: 4096, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 mode: ModeType::from_bits_truncate(0o644), nlinks: 1, diff --git a/kernel/src/driver/keyboard/ps2_keyboard.rs b/kernel/src/driver/keyboard/ps2_keyboard.rs index 952d99fb0..f7e53cd87 100644 --- a/kernel/src/driver/keyboard/ps2_keyboard.rs +++ b/kernel/src/driver/keyboard/ps2_keyboard.rs @@ -32,7 +32,7 @@ use crate::{ rwlock::RwLock, spinlock::{SpinLock, SpinLockGuard}, }, - time::TimeSpec, + time::PosixTimeSpec, }; use system_error::SystemError; @@ -83,9 +83,9 @@ impl LockedPS2KeyBoardInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 mode: ModeType::from_bits_truncate(0o666), nlinks: 1, diff --git a/kernel/src/driver/net/dma.rs b/kernel/src/driver/net/dma.rs index 657e3da8c..11fcf6229 100644 --- a/kernel/src/driver/net/dma.rs +++ b/kernel/src/driver/net/dma.rs @@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags; use crate::arch::MMArch; use crate::mm::kernel_mapper::KernelMapper; -use crate::mm::page::{page_manager_lock_irasave, PageFlags}; +use crate::mm::page::{page_manager_lock_irqsave, PageFlags}; use crate::mm::{ allocator::page_frame::{ allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame, @@ -60,7 +60,7 @@ pub unsafe fn dma_dealloc(paddr: usize, vaddr: NonNull, pages: usize) -> i32 deallocate_page_frames( PhysPageFrame::new(PhysAddr::new(paddr)), page_count, - &mut page_manager_lock_irasave(), + &mut page_manager_lock_irqsave(), ); } return 0; diff --git a/kernel/src/driver/rtc/class.rs b/kernel/src/driver/rtc/class.rs index 357fa4e0d..12184e561 100644 --- a/kernel/src/driver/rtc/class.rs +++ b/kernel/src/driver/rtc/class.rs @@ -13,7 +13,7 @@ use crate::{ subsys::SubSysPrivate, }, init::initcall::INITCALL_SUBSYS, - time::{timekeeping::do_settimeofday64, TimeSpec}, + time::{timekeeping::do_settimeofday64, PosixTimeSpec}, }; use super::{interface::rtc_read_time, register_default_rtc, sysfs::RtcGeneralDevice}; @@ -96,7 +96,7 @@ fn rtc_hctosys(dev: &Arc) { } let time = r.unwrap(); - let timespec64: TimeSpec = time.into(); + let timespec64: PosixTimeSpec = time.into(); let r = do_settimeofday64(timespec64); dev.set_hc2sys_result(r); diff --git a/kernel/src/driver/rtc/mod.rs b/kernel/src/driver/rtc/mod.rs index 9abddaf3b..7031c0ba3 100644 --- a/kernel/src/driver/rtc/mod.rs +++ b/kernel/src/driver/rtc/mod.rs @@ -5,7 +5,7 @@ use system_error::SystemError; use crate::{ libs::rwlock::RwLock, - time::{Instant, TimeSpec, NSEC_PER_SEC}, + time::{Instant, PosixTimeSpec, NSEC_PER_SEC}, }; use self::sysfs::RtcGeneralDevice; @@ -137,7 +137,7 @@ impl RtcTime { } } -impl From for TimeSpec { +impl From for PosixTimeSpec { fn from(val: RtcTime) -> Self { let instant = Instant::mktime64( val.year_real() as u32, @@ -155,7 +155,7 @@ impl From for TimeSpec { * 存储最接近的值会减慢同步 API 的速度。因此,这里我们存储截断的值 * 并在后面加上 0.5s 的最佳猜测。 */ - TimeSpec::new(instant.secs(), (NSEC_PER_SEC >> 1).into()) + PosixTimeSpec::new(instant.secs(), (NSEC_PER_SEC >> 1).into()) } } diff --git a/kernel/src/driver/virtio/virtio_impl.rs b/kernel/src/driver/virtio/virtio_impl.rs index dab879af9..92e2edd86 100644 --- a/kernel/src/driver/virtio/virtio_impl.rs +++ b/kernel/src/driver/virtio/virtio_impl.rs @@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags; use crate::arch::MMArch; use crate::mm::kernel_mapper::KernelMapper; -use crate::mm::page::{page_manager_lock_irasave, PageFlags}; +use crate::mm::page::{page_manager_lock_irqsave, PageFlags}; use crate::mm::{ allocator::page_frame::{ allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame, @@ -71,7 +71,7 @@ unsafe impl Hal for HalImpl { deallocate_page_frames( PhysPageFrame::new(PhysAddr::new(paddr)), page_count, - &mut page_manager_lock_irasave(), + &mut page_manager_lock_irqsave(), ); } return 0; diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index 302e94614..3b19ed975 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -15,7 +15,7 @@ use crate::{ once::Once, spinlock::{SpinLock, SpinLockGuard}, }, - time::TimeSpec, + time::PosixTimeSpec, }; use alloc::{ collections::BTreeMap, @@ -273,9 +273,9 @@ impl DevFSInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: dev_type_, // 文件夹 mode, nlinks: 1, @@ -363,9 +363,9 @@ impl LockedDevFSInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type, mode, nlinks: 1, diff --git a/kernel/src/filesystem/devfs/null_dev.rs b/kernel/src/filesystem/devfs/null_dev.rs index 07197868a..2fad76928 100644 --- a/kernel/src/filesystem/devfs/null_dev.rs +++ b/kernel/src/filesystem/devfs/null_dev.rs @@ -5,7 +5,7 @@ use crate::filesystem::vfs::{ core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, }; use crate::libs::spinlock::SpinLockGuard; -use crate::{libs::spinlock::SpinLock, time::TimeSpec}; +use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec}; use alloc::{ string::String, sync::{Arc, Weak}, @@ -42,9 +42,9 @@ impl LockedNullInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 mode: ModeType::from_bits_truncate(0o666), nlinks: 1, diff --git a/kernel/src/filesystem/devfs/zero_dev.rs b/kernel/src/filesystem/devfs/zero_dev.rs index 869beb2d4..c2787ac0f 100644 --- a/kernel/src/filesystem/devfs/zero_dev.rs +++ b/kernel/src/filesystem/devfs/zero_dev.rs @@ -5,7 +5,7 @@ use crate::filesystem::vfs::{ core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, }; use crate::libs::spinlock::SpinLockGuard; -use crate::{libs::spinlock::SpinLock, time::TimeSpec}; +use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec}; use alloc::{ string::String, sync::{Arc, Weak}, @@ -42,9 +42,9 @@ impl LockedZeroInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 mode: ModeType::from_bits_truncate(0o666), nlinks: 1, diff --git a/kernel/src/filesystem/devpts/mod.rs b/kernel/src/filesystem/devpts/mod.rs index 01654c843..ad832dd75 100644 --- a/kernel/src/filesystem/devpts/mod.rs +++ b/kernel/src/filesystem/devpts/mod.rs @@ -24,7 +24,7 @@ use crate::{ filesystem::vfs::{syscall::ModeType, FileType, ROOT_INODE}, init::initcall::INITCALL_FS, libs::spinlock::{SpinLock, SpinLockGuard}, - time::TimeSpec, + time::PosixTimeSpec, }; use super::vfs::{ @@ -105,11 +105,11 @@ impl LockedDevPtsFSInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::Dir, - mode: ModeType::from_bits_truncate(0x777), + mode: ModeType::from_bits_truncate(0o777), nlinks: 1, uid: 0, gid: 0, diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 58d92339b..38f558bae 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -26,7 +26,7 @@ use crate::{ spinlock::{SpinLock, SpinLockGuard}, vec_cursor::VecCursor, }, - time::TimeSpec, + time::PosixTimeSpec, }; use super::entry::FATFile; @@ -195,9 +195,9 @@ impl LockedFATInode { } else { fs.bpb.total_sectors_16 as usize }, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type, mode: ModeType::from_bits_truncate(0o777), nlinks: 1, @@ -327,9 +327,9 @@ impl FATFileSystem { } else { bpb.total_sectors_16 as usize }, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::Dir, mode: ModeType::from_bits_truncate(0o777), nlinks: 1, diff --git a/kernel/src/filesystem/kernfs/mod.rs b/kernel/src/filesystem/kernfs/mod.rs index a97dbea7b..1edfe1cc6 100644 --- a/kernel/src/filesystem/kernfs/mod.rs +++ b/kernel/src/filesystem/kernfs/mod.rs @@ -15,7 +15,7 @@ use crate::{ rwlock::RwLock, spinlock::{SpinLock, SpinLockGuard}, }, - time::TimeSpec, + time::PosixTimeSpec, }; use self::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData}; @@ -90,9 +90,9 @@ impl KernFS { gid: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::new(0, 0), - mtime: TimeSpec::new(0, 0), - ctime: TimeSpec::new(0, 0), + atime: PosixTimeSpec::new(0, 0), + mtime: PosixTimeSpec::new(0, 0), + ctime: PosixTimeSpec::new(0, 0), dev_id: 0, inode_id: generate_inode_id(), file_type: FileType::Dir, @@ -526,9 +526,9 @@ impl KernFSInode { gid: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::new(0, 0), - mtime: TimeSpec::new(0, 0), - ctime: TimeSpec::new(0, 0), + atime: PosixTimeSpec::new(0, 0), + mtime: PosixTimeSpec::new(0, 0), + ctime: PosixTimeSpec::new(0, 0), dev_id: 0, inode_id: generate_inode_id(), file_type: file_type.into(), diff --git a/kernel/src/filesystem/procfs/log.rs b/kernel/src/filesystem/procfs/log.rs index 06fd26557..01771effe 100644 --- a/kernel/src/filesystem/procfs/log.rs +++ b/kernel/src/filesystem/procfs/log.rs @@ -2,7 +2,7 @@ use core::fmt::{Display, Formatter, Result}; use alloc::string::String; -use crate::time::TimeSpec; +use crate::time::PosixTimeSpec; // /// 日志类型 // #[derive(Default, Clone, Debug)] @@ -58,7 +58,7 @@ impl From for LogLevel { #[derive(Default, Clone, Debug)] pub struct LogMessage { /// 时间戳 - timestamp: TimeSpec, + timestamp: PosixTimeSpec, /// 日志级别 level: LogLevel, // /// 日志类型 @@ -68,7 +68,7 @@ pub struct LogMessage { } impl LogMessage { - pub fn new(timestamp: TimeSpec, level: LogLevel, message: String) -> Self { + pub fn new(timestamp: PosixTimeSpec, level: LogLevel, message: String) -> Self { LogMessage { timestamp, level, diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 9db13a1a3..ef69cce1a 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -25,7 +25,7 @@ use crate::{ }, mm::allocator::page_frame::FrameAllocator, process::{Pid, ProcessManager}, - time::TimeSpec, + time::PosixTimeSpec, }; use super::vfs::{ @@ -314,9 +314,9 @@ impl ProcFS { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::Dir, mode: ModeType::from_bits_truncate(0o555), nlinks: 1, @@ -600,9 +600,9 @@ impl IndexNode for LockedProcFSInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type, mode, nlinks: 1, diff --git a/kernel/src/filesystem/ramfs/mod.rs b/kernel/src/filesystem/ramfs/mod.rs index 523b6d2cd..f2505753a 100644 --- a/kernel/src/filesystem/ramfs/mod.rs +++ b/kernel/src/filesystem/ramfs/mod.rs @@ -9,7 +9,7 @@ use crate::{ ipc::pipe::LockedPipeInode, libs::casting::DowncastArc, libs::spinlock::{SpinLock, SpinLockGuard}, - time::TimeSpec, + time::PosixTimeSpec, }; use alloc::{ @@ -110,9 +110,9 @@ impl RamFS { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::Dir, mode: ModeType::from_bits_truncate(0o777), nlinks: 1, @@ -310,9 +310,9 @@ impl IndexNode for LockedRamFSInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type, mode, nlinks: 1, @@ -545,9 +545,9 @@ impl IndexNode for LockedRamFSInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::Pipe, mode, nlinks: 1, diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index a4e6e5404..6a6a805ad 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -20,7 +20,7 @@ use crate::{ casting::DowncastArc, spinlock::{SpinLock, SpinLockGuard}, }, - time::TimeSpec, + time::PosixTimeSpec, }; use self::{core::generate_inode_id, file::FileMode, syscall::ModeType}; @@ -549,13 +549,13 @@ pub struct Metadata { pub blocks: usize, /// inode最后一次被访问的时间 - pub atime: TimeSpec, + pub atime: PosixTimeSpec, /// inode最后一次修改的时间 - pub mtime: TimeSpec, + pub mtime: PosixTimeSpec, /// inode的创建时间 - pub ctime: TimeSpec, + pub ctime: PosixTimeSpec, /// 文件类型 pub file_type: FileType, @@ -584,9 +584,9 @@ impl Default for Metadata { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::File, mode: ModeType::empty(), nlinks: 1, @@ -701,9 +701,9 @@ impl Metadata { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type, mode, nlinks: 1, diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 0226eda72..292f747e9 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -17,7 +17,7 @@ use crate::{ user_access::{self, check_and_clone_cstr, UserBufferWriter}, Syscall, }, - time::TimeSpec, + time::PosixTimeSpec, }; use super::SuperBlock; @@ -110,11 +110,11 @@ pub struct PosixKstat { /// 分配的512B块数 blocks: u64, /// 最后访问时间 - atime: TimeSpec, + atime: PosixTimeSpec, /// 最后修改时间 - mtime: TimeSpec, + mtime: PosixTimeSpec, /// 最后状态变化时间 - ctime: TimeSpec, + ctime: PosixTimeSpec, /// 用于填充结构体大小的空白数据 pub _pad: [i8; 24], } @@ -129,15 +129,15 @@ impl PosixKstat { gid: 0, rdev: 0, size: 0, - atime: TimeSpec { + atime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, - mtime: TimeSpec { + mtime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, - ctime: TimeSpec { + ctime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, @@ -180,13 +180,13 @@ pub struct PosixStatx { /* 0x40 */ /// 最后访问时间 - stx_atime: TimeSpec, + stx_atime: PosixTimeSpec, /// 文件创建时间 - stx_btime: TimeSpec, + stx_btime: PosixTimeSpec, /// 最后状态变化时间 - stx_ctime: TimeSpec, + stx_ctime: PosixTimeSpec, /// 最后修改时间 - stx_mtime: TimeSpec, + stx_mtime: PosixTimeSpec, /* 0x80 */ /// 主设备ID @@ -217,19 +217,19 @@ impl PosixStatx { stx_size: 0, stx_blocks: 0, stx_attributes_mask: StxAttributes::STATX_ATTR_APPEND, - stx_atime: TimeSpec { + stx_atime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, - stx_btime: TimeSpec { + stx_btime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, - stx_ctime: TimeSpec { + stx_ctime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, - stx_mtime: TimeSpec { + stx_mtime: PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }, diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 1112d41f3..8f794a659 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,4 +1,5 @@ pub mod pipe; +pub mod shm; pub mod signal; pub mod signal_types; pub mod syscall; diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index f96555bf9..aa36a8af3 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -12,7 +12,7 @@ use crate::{ net::event_poll::{EPollEventType, EPollItem, EventPoll}, process::ProcessState, sched::{schedule, SchedMode}, - time::TimeSpec, + time::PosixTimeSpec, }; use alloc::{ @@ -121,9 +121,9 @@ impl LockedPipeInode { size: PIPE_BUFF_SIZE as i64, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::Pipe, mode: ModeType::from_bits_truncate(0o666), nlinks: 1, diff --git a/kernel/src/ipc/shm.rs b/kernel/src/ipc/shm.rs new file mode 100644 index 000000000..6e4b7224d --- /dev/null +++ b/kernel/src/ipc/shm.rs @@ -0,0 +1,658 @@ +use crate::{ + arch::mm::LockedFrameAllocator, + filesystem::vfs::syscall::ModeType, + libs::{ + align::page_align_up, + spinlock::{SpinLock, SpinLockGuard}, + }, + mm::{ + allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame}, + page::{page_manager_lock_irqsave, Page}, + PhysAddr, + }, + process::{Pid, ProcessManager}, + syscall::user_access::{UserBufferReader, UserBufferWriter}, + time::PosixTimeSpec, +}; +use alloc::vec::Vec; +use core::sync::atomic::{compiler_fence, Ordering}; +use hashbrown::{HashMap, HashSet}; +use ida::IdAllocator; +use num::ToPrimitive; +use system_error::SystemError; + +pub static mut SHM_MANAGER: Option> = None; + +/// 用于创建新的私有IPC对象 +pub const IPC_PRIVATE: ShmKey = ShmKey::new(0); + +/// 初始化SHM_MANAGER +pub fn shm_manager_init() { + kinfo!("shm_manager_init"); + let shm_manager = SpinLock::new(ShmManager::new()); + + compiler_fence(Ordering::SeqCst); + unsafe { SHM_MANAGER = Some(shm_manager) }; + compiler_fence(Ordering::SeqCst); + + kinfo!("shm_manager_init done"); +} + +pub fn shm_manager_lock() -> SpinLockGuard<'static, ShmManager> { + unsafe { SHM_MANAGER.as_ref().unwrap().lock() } +} + +int_like!(ShmId, usize); +int_like!(ShmKey, usize); + +bitflags! { + pub struct ShmFlags:u32{ + const SHM_RDONLY = 0o10000; + const SHM_RND = 0o20000; + const SHM_REMAP = 0o40000; + const SHM_EXEC = 0o100000; + const SHM_HUGETLB = 0o4000; + + const IPC_CREAT = 0o1000; + const IPC_EXCL = 0o2000; + + const SHM_DEST = 0o1000; + const SHM_LOCKED = 0o2000; + } +} + +/// 管理共享内存段信息的操作码 +#[derive(Eq, Clone, Copy)] +pub enum ShmCtlCmd { + /// 删除共享内存段 + IpcRmid = 0, + /// 设置KernIpcPerm选项 + IpcSet = 1, + /// 获取ShmIdDs + IpcStat = 2, + /// 查看ShmMetaData + IpcInfo = 3, + + /// 不允许共享内存段被置换出物理内存 + ShmLock = 11, + /// 允许共享内存段被置换出物理内存 + ShmUnlock = 12, + /// 查看ShmMetaData + ShmStat = 13, + /// 查看ShmInfo + ShmInfo = 14, + /// 查看ShmMetaData + ShmtStatAny = 15, + + Default, +} + +impl From for ShmCtlCmd { + fn from(cmd: usize) -> ShmCtlCmd { + match cmd { + 0 => Self::IpcRmid, + 1 => Self::IpcSet, + 2 => Self::IpcStat, + 3 => Self::IpcInfo, + 11 => Self::ShmLock, + 12 => Self::ShmUnlock, + 13 => Self::ShmStat, + 14 => Self::ShmInfo, + 15 => Self::ShmtStatAny, + _ => Self::Default, + } + } +} + +impl PartialEq for ShmCtlCmd { + fn eq(&self, other: &ShmCtlCmd) -> bool { + *self as usize == *other as usize + } +} + +/// 共享内存管理器 +#[derive(Debug)] +pub struct ShmManager { + /// ShmId分配器 + id_allocator: IdAllocator, + /// ShmId映射共享内存信息表 + id2shm: HashMap, + /// ShmKey映射ShmId表 + key2id: HashMap, +} + +impl ShmManager { + pub fn new() -> Self { + ShmManager { + id_allocator: IdAllocator::new(0, usize::MAX - 1), + id2shm: HashMap::new(), + key2id: HashMap::new(), + } + } + + /// # 添加共享内存段 + /// + /// ## 参数 + /// + /// - `key`: 共享内存键值 + /// - `size`: 共享内存大小 + /// - `shmflg`: 共享内存标志 + /// + /// ## 返回值 + /// + /// 成功:共享内存id + /// 失败:对应错误码 + pub fn add( + &mut self, + key: ShmKey, + size: usize, + shmflg: ShmFlags, + ) -> Result { + // 判断共享内存大小是否过小或溢出 + if !(PosixShmMetaInfo::SHMMIN..=PosixShmMetaInfo::SHMMAX).contains(&size) { + return Err(SystemError::EINVAL); + } + + let id = self.id_allocator.alloc().expect("No more id to allocate."); + let shm_id = ShmId::new(id); + + // 分配共享内存页面 + let page_count = PageFrameCount::from_bytes(page_align_up(size)).unwrap(); + let phys_page = + unsafe { LockedFrameAllocator.allocate(page_count) }.ok_or(SystemError::EINVAL)?; + // 创建共享内存page,并添加到PAGE_MANAGER中 + let mut page_manager_guard = page_manager_lock_irqsave(); + let mut cur_phys = PhysPageFrame::new(phys_page.0); + for _ in 0..page_count.data() { + let mut page = Page::new(true); + page.set_shm_id(shm_id); + let paddr = cur_phys.phys_address(); + page_manager_guard.insert(paddr, page); + cur_phys = cur_phys.next(); + } + + // 创建共享内存信息结构体 + let paddr = phys_page.0; + let kern_ipc_perm = KernIpcPerm { + id: shm_id, + key, + uid: 0, + gid: 0, + _cuid: 0, + _cgid: 0, + mode: shmflg & ShmFlags::from_bits_truncate(ModeType::S_IRWXUGO.bits()), + _seq: 0, + }; + let shm_kernel = KernelShm::new(kern_ipc_perm, paddr, size); + + // 将key、id及其对应KernelShm添加到表中 + self.id2shm.insert(shm_id, shm_kernel); + self.key2id.insert(key, shm_id); + + return Ok(shm_id.data()); + } + + pub fn contains_key(&self, key: &ShmKey) -> Option<&ShmId> { + self.key2id.get(key) + } + + pub fn get_mut(&mut self, id: &ShmId) -> Option<&mut KernelShm> { + self.id2shm.get_mut(id) + } + + pub fn free_key(&mut self, key: &ShmKey) { + self.key2id.remove(key); + } + + pub fn free_id(&mut self, id: &ShmId) { + self.id2shm.remove(id); + self.id_allocator.free(id.0); + } + + pub fn ipc_info(&self, user_buf: *const u8, from_user: bool) -> Result { + let mut user_buffer_writer = UserBufferWriter::new( + user_buf as *mut u8, + core::mem::size_of::(), + from_user, + )?; + + let shm_meta_info = PosixShmMetaInfo::new(); + user_buffer_writer.copy_one_to_user(&shm_meta_info, 0)?; + + return Ok(0); + } + + pub fn shm_info(&self, user_buf: *const u8, from_user: bool) -> Result { + // 已使用id数量 + let used_ids = self.id2shm.len().to_i32().unwrap(); + // 共享内存总和 + let shm_tot = self.id2shm.iter().fold(0, |acc, (_, kernel_shm)| { + acc + PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)) + .unwrap() + .data() + }); + let shm_info = PosixShmInfo::new(used_ids, shm_tot, 0, 0, 0, 0); + + let mut user_buffer_writer = UserBufferWriter::new( + user_buf as *mut u8, + core::mem::size_of::(), + from_user, + )?; + user_buffer_writer.copy_one_to_user(&shm_info, 0)?; + + return Ok(0); + } + + pub fn shm_stat( + &self, + id: ShmId, + cmd: ShmCtlCmd, + user_buf: *const u8, + from_user: bool, + ) -> Result { + let kernel_shm = self.id2shm.get(&id).ok_or(SystemError::EINVAL)?; + let key = kernel_shm.kern_ipc_perm.key.data().to_i32().unwrap(); + let mode = kernel_shm.kern_ipc_perm.mode.bits(); + + let shm_perm = PosixIpcPerm::new(key, 0, 0, 0, 0, mode); + let shm_segsz = kernel_shm.shm_size; + let shm_atime = kernel_shm.shm_atim.total_nanos(); + let shm_dtime = kernel_shm.shm_dtim.total_nanos(); + let shm_ctime = kernel_shm.shm_ctim.total_nanos(); + let shm_cpid = kernel_shm.shm_cprid.data().to_u32().unwrap(); + let shm_lpid = kernel_shm.shm_lprid.data().to_u32().unwrap(); + let shm_map_count = kernel_shm.map_count(); + let shm_id_ds = PosixShmIdDs { + shm_perm, + shm_segsz, + shm_atime, + shm_dtime, + shm_ctime, + shm_cpid, + shm_lpid, + shm_map_count, + _unused1: 0, + _unused2: 0, + }; + + let mut user_buffer_writer = UserBufferWriter::new( + user_buf as *mut u8, + core::mem::size_of::(), + from_user, + )?; + user_buffer_writer.copy_one_to_user(&shm_id_ds, 0)?; + + let r: usize = if cmd == ShmCtlCmd::IpcStat { + 0 + } else { + id.data() + }; + + return Ok(r); + } + + pub fn ipc_set( + &mut self, + id: ShmId, + user_buf: *const u8, + from_user: bool, + ) -> Result { + let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; + + let user_buffer_reader = + UserBufferReader::new(user_buf, core::mem::size_of::(), from_user)?; + let mut shm_id_ds = PosixShmIdDs::default(); + user_buffer_reader.copy_one_from_user(&mut shm_id_ds, 0)?; + + kernel_shm.copy_from(shm_id_ds); + + return Ok(0); + } + + pub fn ipc_rmid(&mut self, id: ShmId) -> Result { + let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; + kernel_shm.set_mode(ShmFlags::SHM_DEST, true); + + let mut cur_phys = PhysPageFrame::new(kernel_shm.shm_start_paddr); + let count = PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)).unwrap(); + let key = kernel_shm.kern_ipc_perm.key; + let id = kernel_shm.kern_ipc_perm.id; + let map_count = kernel_shm.map_count(); + + let mut page_manager_guard = page_manager_lock_irqsave(); + if map_count > 0 { + // 设置共享内存物理页当映射计数等于0时可被回收 + for _ in 0..count.data() { + let page = page_manager_guard.get_mut(&cur_phys.phys_address()); + page.set_dealloc_when_zero(true); + + cur_phys = cur_phys.next(); + } + + // 释放key,不让后续进程连接 + self.free_key(&key); + } else { + // 释放共享内存物理页 + for _ in 0..count.data() { + let paddr = cur_phys.phys_address(); + unsafe { + LockedFrameAllocator.free(paddr, PageFrameCount::new(1)); + } + // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去 + page_manager_guard.remove_page(&paddr); + cur_phys = cur_phys.next(); + } + + // 释放key和id + self.free_id(&id); + self.free_key(&key) + } + + return Ok(0); + } + + pub fn shm_lock(&mut self, id: ShmId) -> Result { + let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; + kernel_shm.set_mode(ShmFlags::SHM_LOCKED, true); + + return Ok(0); + } + + pub fn shm_unlock(&mut self, id: ShmId) -> Result { + let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?; + kernel_shm.set_mode(ShmFlags::SHM_LOCKED, false); + + return Ok(0); + } +} +/// 共享内存信息 +#[derive(Debug)] +pub struct KernelShm { + /// 权限信息 + kern_ipc_perm: KernIpcPerm, + /// 共享内存起始物理地址 + shm_start_paddr: PhysAddr, + /// 共享内存大小(bytes),注意是用户指定的大小(未经过页面对齐) + shm_size: usize, + /// 最后一次连接的时间 + shm_atim: PosixTimeSpec, + /// 最后一次断开连接的时间 + shm_dtim: PosixTimeSpec, + /// 最后一次更改信息的时间 + shm_ctim: PosixTimeSpec, + /// 创建者进程id + shm_cprid: Pid, + /// 最后操作者进程id + shm_lprid: Pid, +} + +impl KernelShm { + pub fn new(kern_ipc_perm: KernIpcPerm, shm_start_paddr: PhysAddr, shm_size: usize) -> Self { + let shm_cprid = ProcessManager::current_pid(); + KernelShm { + kern_ipc_perm, + shm_start_paddr, + shm_size, + shm_atim: PosixTimeSpec::new(0, 0), + shm_dtim: PosixTimeSpec::new(0, 0), + shm_ctim: PosixTimeSpec::now(), + shm_cprid, + shm_lprid: shm_cprid, + } + } + + pub fn start_paddr(&self) -> PhysAddr { + self.shm_start_paddr + } + + pub fn size(&self) -> usize { + self.shm_size + } + + /// 更新最后连接时间 + pub fn update_atim(&mut self) { + // 更新最后一次连接时间 + self.shm_atim = PosixTimeSpec::now(); + + // 更新最后操作当前共享内存的进程ID + self.shm_lprid = ProcessManager::current_pid(); + } + + /// 更新最后断开连接时间 + pub fn update_dtim(&mut self) { + // 更新最后一次断开连接时间 + self.shm_dtim = PosixTimeSpec::now(); + + // 更新最后操作当前共享内存的进程ID + self.shm_lprid = ProcessManager::current_pid(); + } + + /// 更新最后一次修改信息的时间 + pub fn update_ctim(&mut self) { + // 更新最后一次修改信息的时间 + self.shm_ctim = PosixTimeSpec::now(); + } + + /// 共享内存段的映射计数(有多少个不同的VMA映射) + pub fn map_count(&self) -> usize { + let page_manager_guard = page_manager_lock_irqsave(); + let mut id_set: HashSet = HashSet::new(); + let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr); + let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap(); + + for _ in 0..page_count.data() { + let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap(); + id_set.extend( + page.anon_vma() + .iter() + .map(|vma| vma.id()) + .collect::>(), + ); + + cur_phys = cur_phys.next(); + } + + // 由于LockedVMA的id是独一无二的,因此有多少个不同的id,就代表着有多少个不同的VMA映射到共享内存段 + return id_set.len(); + } + + pub fn copy_from(&mut self, shm_id_ds: PosixShmIdDs) { + self.kern_ipc_perm.uid = shm_id_ds.uid() as usize; + self.kern_ipc_perm.gid = shm_id_ds.gid() as usize; + self.kern_ipc_perm.mode = ShmFlags::from_bits_truncate(shm_id_ds.mode()); + self.update_ctim(); + } + + pub fn set_mode(&mut self, shmflg: ShmFlags, set: bool) { + if set { + self.kern_ipc_perm.mode.insert(shmflg); + } else { + self.kern_ipc_perm.mode.remove(shmflg); + } + + self.update_ctim(); + } +} + +/// 共享内存权限信息 +#[derive(Debug)] +pub struct KernIpcPerm { + /// 共享内存id + id: ShmId, + /// 共享内存键值,由创建共享内存用户指定 + key: ShmKey, + /// 共享内存拥有者用户id + uid: usize, + /// 共享内存拥有者所在组id + gid: usize, + /// 共享内存创建者用户id + _cuid: usize, + /// 共享内存创建者所在组id + _cgid: usize, + /// 共享内存区权限模式 + mode: ShmFlags, + _seq: usize, +} + +/// 共享内存元信息,符合POSIX标准 +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct PosixShmMetaInfo { + /// 最大共享内存段的大小(bytes) + shmmax: usize, + /// 最小共享内存段的大小(bytes) + shmmin: usize, + /// 最大共享内存标识符数量 + shmmni: usize, + /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同 + shmseg: usize, + /// 所有共享内存段总共可以使用的最大内存量(pages) + shmall: usize, + _unused1: usize, + _unused2: usize, + _unused3: usize, + _unused4: usize, +} + +impl PosixShmMetaInfo { + /// 最小共享内存段的大小(bytes) + pub const SHMMIN: usize = 1; + /// 最大共享内存标识符数量 + pub const SHMMNI: usize = 4096; + /// 最大共享内存段的大小(bytes) + pub const SHMMAX: usize = usize::MAX - (1 << 24); + /// 所有共享内存段总共可以使用的最大内存量(pages) + pub const SHMALL: usize = usize::MAX - (1 << 24); + /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同 + pub const SHMSEG: usize = 4096; + + pub fn new() -> Self { + PosixShmMetaInfo { + shmmax: Self::SHMMAX, + shmmin: Self::SHMMIN, + shmmni: Self::SHMMNI, + shmseg: Self::SHMSEG, + shmall: Self::SHMALL, + _unused1: 0, + _unused2: 0, + _unused3: 0, + _unused4: 0, + } + } +} + +/// 共享内存信息,符合POSIX标准 +#[repr(C)] +#[derive(Clone, Copy)] +pub struct PosixShmInfo { + /// 已使用id数 + used_ids: i32, + /// 共享内存总量(pages) + shm_tot: usize, + /// 保留在内存中的共享内存大小 + shm_rss: usize, + /// 被置换出的共享内存大小 + shm_swp: usize, + /// 尝试置换次数 + swap_attempts: usize, + /// 成功置换次数 + swap_successes: usize, +} + +impl PosixShmInfo { + pub fn new( + used_ids: i32, + shm_tot: usize, + shm_rss: usize, + shm_swp: usize, + swap_attempts: usize, + swap_successes: usize, + ) -> Self { + PosixShmInfo { + used_ids, + shm_tot, + shm_rss, + shm_swp, + swap_attempts, + swap_successes, + } + } +} + +/// 共享内存段属性信息,符合POSIX标准 +#[repr(C)] +#[derive(Debug, Clone, Copy, Default)] +pub struct PosixShmIdDs { + /// 共享内存段权限 + shm_perm: PosixIpcPerm, + /// 共享内存大小(bytes) + shm_segsz: usize, + /// 最后一次连接的时间 + shm_atime: i64, + /// 最后一次断开连接的时间 + shm_dtime: i64, + /// 最后一次更改信息的时间 + shm_ctime: i64, + /// 创建者进程id + shm_cpid: u32, + /// 最后操作者进程id + shm_lpid: u32, + /// 链接数 + shm_map_count: usize, + _unused1: usize, + _unused2: usize, +} + +impl PosixShmIdDs { + pub fn uid(&self) -> u32 { + self.shm_perm.uid + } + + pub fn gid(&self) -> u32 { + self.shm_perm.gid + } + + pub fn mode(&self) -> u32 { + self.shm_perm.mode + } +} + +/// 共享内存段权限,符合POSIX标准 +#[repr(C)] +#[derive(Debug, Clone, Copy, Default)] +pub struct PosixIpcPerm { + /// IPC对象键值 + key: i32, + /// 当前用户id + uid: u32, + /// 当前用户组id + gid: u32, + /// 创建者用户id + cuid: u32, + /// 创建者组id + cgid: u32, + /// 权限 + mode: u32, + /// 序列号 + seq: i32, + _pad1: i32, + _unused1: usize, + _unused2: usize, +} + +impl PosixIpcPerm { + pub fn new(key: i32, uid: u32, gid: u32, cuid: u32, cgid: u32, mode: u32) -> Self { + PosixIpcPerm { + key, + uid, + gid, + cuid, + cgid, + mode, + seq: 0, + _pad1: 0, + _unused1: 0, + _unused2: 0, + } + } +} diff --git a/kernel/src/ipc/syscall.rs b/kernel/src/ipc/syscall.rs index cf723fc96..b196ec1ab 100644 --- a/kernel/src/ipc/syscall.rs +++ b/kernel/src/ipc/syscall.rs @@ -6,20 +6,35 @@ use core::{ use system_error::SystemError; use crate::{ - arch::ipc::signal::{SigCode, SigFlags, SigSet, Signal}, + arch::{ + ipc::signal::{SigCode, SigFlags, SigSet, Signal}, + MMArch, + }, filesystem::vfs::{ file::{File, FileMode}, FilePrivateData, }, + ipc::shm::{shm_manager_lock, IPC_PRIVATE}, kerror, kwarn, + libs::align::page_align_up, libs::spinlock::SpinLock, - mm::VirtAddr, + mm::{ + allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame}, + page::{page_manager_lock_irqsave, PageFlags, PageFlushAll}, + syscall::ProtFlags, + ucontext::{AddressSpace, VMA}, + VirtAddr, VmFlags, + }, process::{Pid, ProcessManager}, - syscall::{user_access::UserBufferWriter, Syscall}, + 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, @@ -230,4 +245,262 @@ impl Syscall { } 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) { + kerror!("shmget: not support huge page"); + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + 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: PageFlags = + PageFlags::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().region().start() != vaddr { + return Err(SystemError::EINVAL); + } + + // 验证用户虚拟内存区域是否有效 + let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?; + + // 必须在取消映射前获取到PageFlags + 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_mut(&phys.phys_address()) + .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 { + 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.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 = 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), + } + } } diff --git a/kernel/src/libs/futex/futex.rs b/kernel/src/libs/futex/futex.rs index 4e428cfdb..c1897f968 100644 --- a/kernel/src/libs/futex/futex.rs +++ b/kernel/src/libs/futex/futex.rs @@ -22,7 +22,7 @@ use crate::{ syscall::user_access::{UserBufferReader, UserBufferWriter}, time::{ timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, - TimeSpec, + PosixTimeSpec, }, }; @@ -220,7 +220,7 @@ impl Futex { uaddr: VirtAddr, flags: FutexFlag, val: u32, - abs_time: Option, + abs_time: Option, bitset: u32, ) -> Result { if bitset == 0 { diff --git a/kernel/src/libs/futex/syscall.rs b/kernel/src/libs/futex/syscall.rs index 8ac5739b3c..2f8ae0963 100644 --- a/kernel/src/libs/futex/syscall.rs +++ b/kernel/src/libs/futex/syscall.rs @@ -3,7 +3,7 @@ use system_error::SystemError; use crate::{ mm::{verify_area, VirtAddr}, syscall::Syscall, - time::TimeSpec, + time::PosixTimeSpec, }; use super::{ @@ -16,7 +16,7 @@ impl Syscall { uaddr: VirtAddr, operation: FutexFlag, val: u32, - timeout: Option, + timeout: Option, uaddr2: VirtAddr, val2: u32, val3: u32, diff --git a/kernel/src/libs/printk.rs b/kernel/src/libs/printk.rs index ca0a4bccd..6726d0992 100644 --- a/kernel/src/libs/printk.rs +++ b/kernel/src/libs/printk.rs @@ -16,7 +16,7 @@ use crate::{ kmsg::KMSG, log::{LogLevel, LogMessage}, }, - time::TimeSpec, + time::PosixTimeSpec, }; #[macro_export] @@ -120,7 +120,7 @@ pub struct Logger; impl Logger { pub fn log(&self, log_level: usize, message: fmt::Arguments) { if unsafe { KMSG.is_some() } { - let timestamp: TimeSpec = TimeSpec::now(); + let timestamp: PosixTimeSpec = PosixTimeSpec::now_cpu_time(); let log_level = LogLevel::from(log_level); let log_message = LogMessage::new(timestamp, log_level, message.to_string()); diff --git a/kernel/src/mm/allocator/page_frame.rs b/kernel/src/mm/allocator/page_frame.rs index 9a7fd2916..1e20ee310 100644 --- a/kernel/src/mm/allocator/page_frame.rs +++ b/kernel/src/mm/allocator/page_frame.rs @@ -5,6 +5,7 @@ use core::{ use crate::{ arch::{mm::LockedFrameAllocator, MMArch}, + ipc::shm::shm_manager_lock, libs::spinlock::SpinLockGuard, mm::{MemoryManagementArch, PhysAddr, VirtAddr}, }; @@ -196,6 +197,11 @@ impl PageFrameCount { return Some(Self(bytes / MMArch::PAGE_SIZE)); } } + + #[inline(always)] + pub fn next_power_of_two(&self) -> Self { + Self::new(self.0.next_power_of_two()) + } } impl Add for PageFrameCount { @@ -352,17 +358,26 @@ pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, P pub unsafe fn deallocate_page_frames( frame: PhysPageFrame, count: PageFrameCount, - page_manager: &mut SpinLockGuard<'_, crate::mm::page::PageManager>, + page_manager_guard: &mut SpinLockGuard<'_, crate::mm::page::PageManager>, ) { unsafe { LockedFrameAllocator.free(frame.phys_address(), count); } - // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去 let mut frame = frame; for _ in 0..count.data() { let paddr = frame.phys_address(); - page_manager.remove_page(&paddr); + let page = page_manager_guard.get(&paddr); + + if let Some(page) = page { + // 如果page是共享页,将其共享页信息从SHM_MANAGER中删去 + if page.shared() { + shm_manager_lock().free_id(&page.shm_id().unwrap()); + } + } + + // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去 + page_manager_guard.remove_page(&paddr); frame = frame.next(); } } diff --git a/kernel/src/mm/init.rs b/kernel/src/mm/init.rs index faaaaebe7..d70fbf622 100644 --- a/kernel/src/mm/init.rs +++ b/kernel/src/mm/init.rs @@ -4,6 +4,7 @@ use crate::{ arch::MMArch, driver::serial::serial8250::send_to_default_serial8250_port, filesystem::procfs::kmsg::kmsg_init, + ipc::shm::shm_manager_init, libs::printk::PrintkWriter, mm::{mmio_buddy::mmio_init, page::page_manager_init}, }; @@ -49,6 +50,8 @@ pub unsafe fn mm_init() { kmsg_init(); // enable PAGE_MANAGER page_manager_init(); + // enable SHM_MANAGER + shm_manager_init(); MM_INIT .compare_exchange( diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index edf3b9ce9..a6af66fc0 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -12,6 +12,7 @@ use hashbrown::{HashMap, HashSet}; use crate::{ arch::{interrupt::ipi::send_ipi, MMArch}, exception::ipi::{IpiKind, IpiTarget}, + ipc::shm::ShmId, kerror, kwarn, libs::spinlock::{SpinLock, SpinLockGuard}, }; @@ -41,7 +42,7 @@ pub fn page_manager_init() { kinfo!("page_manager_init done"); } -pub fn page_manager_lock_irasave() -> SpinLockGuard<'static, PageManager> { +pub fn page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager> { unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() } } @@ -57,6 +58,14 @@ impl PageManager { } } + pub fn contains(&self, paddr: &PhysAddr) -> bool { + self.phys2page.contains_key(paddr) + } + + pub fn get(&self, paddr: &PhysAddr) -> Option<&Page> { + self.phys2page.get(paddr) + } + pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page { self.phys2page.get_mut(paddr).unwrap() } @@ -76,15 +85,22 @@ pub struct Page { map_count: usize, /// 是否为共享页 shared: bool, + /// 映射计数为0时,是否可回收 + free_when_zero: bool, + /// 共享页id(如果是共享页) + shm_id: Option, /// 映射到当前page的VMA anon_vma: HashSet>, } impl Page { pub fn new(shared: bool) -> Self { + let dealloc_when_zero = !shared; Self { map_count: 0, shared, + free_when_zero: dealloc_when_zero, + shm_id: None, anon_vma: HashSet::new(), } } @@ -103,7 +119,27 @@ impl Page { /// 判断当前物理页是否能被回 pub fn can_deallocate(&self) -> bool { - self.map_count == 0 && !self.shared + self.map_count == 0 && self.free_when_zero + } + + pub fn shared(&self) -> bool { + self.shared + } + + pub fn shm_id(&self) -> Option { + self.shm_id + } + + pub fn set_shm_id(&mut self, shm_id: ShmId) { + self.shm_id = Some(shm_id); + } + + pub fn set_dealloc_when_zero(&mut self, dealloc_when_zero: bool) { + self.free_when_zero = dealloc_when_zero; + } + + pub fn anon_vma(&self) -> &HashSet> { + &self.anon_vma } } @@ -682,7 +718,12 @@ impl PageMapper { let phys: PhysAddr = self.frame_allocator.allocate_one()?; compiler_fence(Ordering::SeqCst); - page_manager_lock_irasave().insert(phys, Page::new(false)); + let mut page_manager_guard: SpinLockGuard<'static, PageManager> = + page_manager_lock_irqsave(); + if !page_manager_guard.contains(&phys) { + page_manager_guard.insert(phys, Page::new(false)) + } + return self.map_phys(virt, phys, flags); } diff --git a/kernel/src/mm/syscall.rs b/kernel/src/mm/syscall.rs index e9b9066c4..8d3aa037d 100644 --- a/kernel/src/mm/syscall.rs +++ b/kernel/src/mm/syscall.rs @@ -5,6 +5,7 @@ use system_error::SystemError; use crate::{ arch::MMArch, + ipc::shm::ShmFlags, kerror, libs::align::{check_aligned, page_align_up}, mm::MemoryManagementArch, @@ -113,6 +114,28 @@ impl From for VmFlags { } } +impl From for VmFlags { + fn from(shm_flags: ShmFlags) -> Self { + let mut vm_flags = VmFlags::VM_NONE; + + if shm_flags.contains(ShmFlags::SHM_RDONLY) { + vm_flags |= VmFlags::VM_READ; + } else { + vm_flags |= VmFlags::VM_READ | VmFlags::VM_WRITE; + } + + if shm_flags.contains(ShmFlags::SHM_EXEC) { + vm_flags |= VmFlags::VM_EXEC; + } + + if shm_flags.contains(ShmFlags::SHM_HUGETLB) { + vm_flags |= VmFlags::VM_HUGETLB; + } + + vm_flags + } +} + impl From for MapFlags { fn from(value: VmFlags) -> Self { let mut map_flags = MapFlags::MAP_NONE; diff --git a/kernel/src/mm/ucontext.rs b/kernel/src/mm/ucontext.rs index 1b000d8e2..a04867c3b 100644 --- a/kernel/src/mm/ucontext.rs +++ b/kernel/src/mm/ucontext.rs @@ -25,7 +25,7 @@ use crate::{ rwlock::{RwLock, RwLockWriteGuard}, spinlock::{SpinLock, SpinLockGuard}, }, - mm::page::page_manager_lock_irasave, + mm::page::page_manager_lock_irqsave, process::ProcessManager, syscall::user_access::{UserBufferReader, UserBufferWriter}, }; @@ -577,7 +577,9 @@ impl InnerAddressSpace { pub unsafe fn unmap_all(&mut self) { let mut flusher: PageFlushAll = PageFlushAll::new(); for vma in self.mappings.iter_vmas() { - vma.unmap(&mut self.user_mapper.utable, &mut flusher); + if vma.mapped() { + vma.unmap(&mut self.user_mapper.utable, &mut flusher); + } } } @@ -670,7 +672,7 @@ impl Drop for UserMapper { deallocate_page_frames( PhysPageFrame::new(self.utable.table().phys()), PageFrameCount::new(1), - &mut page_manager_lock_irasave(), + &mut page_manager_lock_irqsave(), ) }; } @@ -909,6 +911,10 @@ impl LockedVMA { return r; } + pub fn id(&self) -> usize { + self.id + } + pub fn lock(&self) -> SpinLockGuard { return self.vma.lock(); } @@ -950,14 +956,14 @@ impl LockedVMA { assert!(guard.mapped); // 获取物理页的anon_vma的守卫 - let mut anon_vma_guard: SpinLockGuard<'_, crate::mm::page::PageManager> = - page_manager_lock_irasave(); + let mut page_manager_guard: SpinLockGuard<'_, crate::mm::page::PageManager> = + page_manager_lock_irqsave(); for page in guard.region.pages() { let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) } .expect("Failed to unmap, beacuse of some page is not mapped"); // 从anon_vma中删除当前VMA - let page = anon_vma_guard.get_mut(&paddr); + let page = page_manager_guard.get_mut(&paddr); page.remove_vma(self); // 如果物理页的anon_vma链表长度为0并且不是共享页,则释放物理页. @@ -966,7 +972,7 @@ impl LockedVMA { deallocate_page_frames( PhysPageFrame::new(paddr), PageFrameCount::new(1), - &mut anon_vma_guard, + &mut page_manager_guard, ) }; } @@ -1030,12 +1036,12 @@ impl LockedVMA { }); // 重新设置before、after这两个VMA里面的物理页的anon_vma - let mut anon_vma_guard = page_manager_lock_irasave(); + let mut page_manager_guard = page_manager_lock_irqsave(); if let Some(before) = before.clone() { let virt_iter = before.lock().region.iter_pages(); for frame in virt_iter { let paddr = utable.translate(frame.virt_address()).unwrap().0; - let page = anon_vma_guard.get_mut(&paddr); + let page = page_manager_guard.get_mut(&paddr); page.insert_vma(before.clone()); page.remove_vma(self); } @@ -1045,7 +1051,7 @@ impl LockedVMA { let virt_iter = after.lock().region.iter_pages(); for frame in virt_iter { let paddr = utable.translate(frame.virt_address()).unwrap().0; - let page = anon_vma_guard.get_mut(&paddr); + let page = page_manager_guard.get_mut(&paddr); page.insert_vma(after.clone()); page.remove_vma(self); } @@ -1155,6 +1161,10 @@ impl VMA { self.region.set_size(new_region_size); } + pub fn set_mapped(&mut self, mapped: bool) { + self.mapped = mapped; + } + /// # 拷贝当前VMA的内容 /// /// ### 安全性 @@ -1273,11 +1283,11 @@ impl VMA { }); // 将VMA加入到anon_vma中 - let mut anon_vma_guard = page_manager_lock_irasave(); + let mut page_manager_guard = page_manager_lock_irqsave(); cur_phy = phys; for _ in 0..count.data() { let paddr = cur_phy.phys_address(); - let page = anon_vma_guard.get_mut(&paddr); + let page = page_manager_guard.get_mut(&paddr); page.insert_vma(r.clone()); cur_phy = cur_phy.next(); } @@ -1336,14 +1346,14 @@ impl VMA { // kdebug!("VMA::zeroed: flusher dropped"); // 清空这些内存并将VMA加入到anon_vma中 - let mut anon_vma_guard = page_manager_lock_irasave(); + let mut page_manager_guard = page_manager_lock_irqsave(); let virt_iter: VirtPageFrameIter = VirtPageFrameIter::new(destination, destination.add(page_count)); for frame in virt_iter { let paddr = mapper.translate(frame.virt_address()).unwrap().0; // 将VMA加入到anon_vma - let page = anon_vma_guard.get_mut(&paddr); + let page = page_manager_guard.get_mut(&paddr); page.insert_vma(r.clone()); // 清空内存 diff --git a/kernel/src/net/event_poll/mod.rs b/kernel/src/net/event_poll/mod.rs index 86c46e9f0..0691278ba 100644 --- a/kernel/src/net/event_poll/mod.rs +++ b/kernel/src/net/event_poll/mod.rs @@ -26,7 +26,7 @@ use crate::{ sched::{schedule, SchedMode}, time::{ timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, - TimeSpec, + PosixTimeSpec, }, }; @@ -394,7 +394,7 @@ impl EventPoll { epfd: i32, epoll_event: &mut [EPollEvent], max_events: i32, - timespec: Option, + timespec: Option, ) -> Result { let current_pcb = ProcessManager::current_pcb(); let fd_table = current_pcb.fd_table(); diff --git a/kernel/src/net/event_poll/syscall.rs b/kernel/src/net/event_poll/syscall.rs index 5063161cd..02d61eed3 100644 --- a/kernel/src/net/event_poll/syscall.rs +++ b/kernel/src/net/event_poll/syscall.rs @@ -9,7 +9,7 @@ use crate::{ user_access::{UserBufferReader, UserBufferWriter}, Syscall, }, - time::TimeSpec, + time::PosixTimeSpec, }; use super::{EPollCtlOption, EPollEvent, EventPoll}; @@ -42,14 +42,14 @@ impl Syscall { let mut timespec = None; if timeout == 0 { - timespec = Some(TimeSpec::new(0, 0)); + timespec = Some(PosixTimeSpec::new(0, 0)); } if timeout > 0 { let sec: i64 = timeout as i64 / 1000; let nsec: i64 = 1000000 * (timeout as i64 % 1000); - timespec = Some(TimeSpec::new(sec, nsec)) + timespec = Some(PosixTimeSpec::new(sec, nsec)) } // 从用户传入的地址中拿到epoll_events diff --git a/kernel/src/process/resource.rs b/kernel/src/process/resource.rs index b0cbfe2ba..74831c547 100644 --- a/kernel/src/process/resource.rs +++ b/kernel/src/process/resource.rs @@ -1,7 +1,7 @@ use num_traits::FromPrimitive; use system_error::SystemError; -use crate::time::TimeSpec; +use crate::time::PosixTimeSpec; use super::ProcessControlBlock; @@ -9,9 +9,9 @@ use super::ProcessControlBlock; #[repr(C)] pub struct RUsage { /// User time used - pub ru_utime: TimeSpec, + pub ru_utime: PosixTimeSpec, /// System time used - pub ru_stime: TimeSpec, + pub ru_stime: PosixTimeSpec, // 以下是linux的rusage结构体扩展 /// Maximum resident set size diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 9956c3010..16e0c4766 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -8,6 +8,7 @@ use crate::{ arch::{ipc::signal::SigSet, syscall::nr::*}, driver::base::device::device_number::DeviceNumber, filesystem::vfs::syscall::{PosixStatfs, PosixStatx}, + ipc::shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey}, libs::{futex::constant::FutexFlag, rand::GRandFlags}, mm::syscall::MremapFlags, net::syscall::MsgHdr, @@ -39,7 +40,7 @@ use crate::{ process::{fork::CloneFlags, syscall::PosixOldUtsName, Pid}, time::{ syscall::{PosixTimeZone, PosixTimeval}, - TimeSpec, + PosixTimeSpec, }, }; @@ -297,13 +298,13 @@ impl Syscall { } SYS_NANOSLEEP => { - let req = args[0] as *const TimeSpec; - let rem = args[1] as *mut TimeSpec; + let req = args[0] as *const PosixTimeSpec; + let rem = args[1] as *mut PosixTimeSpec; let virt_req = VirtAddr::new(req as usize); let virt_rem = VirtAddr::new(rem as usize); if frame.is_from_user() - && (verify_area(virt_req, core::mem::size_of::()).is_err() - || verify_area(virt_rem, core::mem::size_of::()).is_err()) + && (verify_area(virt_req, core::mem::size_of::()).is_err() + || verify_area(virt_rem, core::mem::size_of::()).is_err()) { Err(SystemError::EFAULT) } else { @@ -693,12 +694,12 @@ impl Syscall { let mut timespec = None; if utime != 0 && operation.contains(FutexFlag::FLAGS_HAS_TIMEOUT) { let reader = UserBufferReader::new( - utime as *const TimeSpec, - core::mem::size_of::(), + utime as *const PosixTimeSpec, + core::mem::size_of::(), true, )?; - timespec = Some(*reader.read_one_from_user::(0)?); + timespec = Some(*reader.read_one_from_user::(0)?); } Self::do_futex(uaddr, operation, val, timespec, uaddr2, utime as u32, val3) @@ -945,7 +946,7 @@ impl Syscall { SYS_CLOCK_GETTIME => { let clockid = args[0] as i32; - let timespec = args[1] as *mut TimeSpec; + let timespec = args[1] as *mut PosixTimeSpec; Self::clock_gettime(clockid, timespec) } @@ -1041,6 +1042,33 @@ impl Syscall { Self::uname(name) } + 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) + } + _ => panic!("Unsupported syscall ID: {}", syscall_num), }; diff --git a/kernel/src/time/mod.rs b/kernel/src/time/mod.rs index 467ea921c..7a4eb9eb9 100644 --- a/kernel/src/time/mod.rs +++ b/kernel/src/time/mod.rs @@ -6,7 +6,7 @@ use core::{ use crate::arch::CurrentTimeArch; -use self::timekeep::ktime_get_real_ns; +use self::{timekeep::ktime_get_real_ns, timekeeping::getnstimeofday}; pub mod clocksource; pub mod jiffies; @@ -46,28 +46,34 @@ pub const FSEC_PER_SEC: u64 = 1000000000000000; /// 表示时间的结构体,符合POSIX标准。 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[repr(C)] -pub struct TimeSpec { +pub struct PosixTimeSpec { pub tv_sec: i64, pub tv_nsec: i64, } -impl TimeSpec { +impl PosixTimeSpec { #[allow(dead_code)] - pub fn new(sec: i64, nsec: i64) -> TimeSpec { - return TimeSpec { + pub fn new(sec: i64, nsec: i64) -> PosixTimeSpec { + return PosixTimeSpec { tv_sec: sec, tv_nsec: nsec, }; } /// 获取当前时间 + #[inline(always)] pub fn now() -> Self { + getnstimeofday() + } + + /// 获取当前CPU时间(使用CPU时钟周期计算,会存在回绕问题) + pub fn now_cpu_time() -> Self { #[cfg(target_arch = "x86_64")] { use crate::arch::driver::tsc::TSCManager; let khz = TSCManager::cpu_khz(); if unlikely(khz == 0) { - return TimeSpec::default(); + return PosixTimeSpec::default(); } else { return Self::from(Duration::from_millis( CurrentTimeArch::get_cycles() as u64 / khz, @@ -77,12 +83,17 @@ impl TimeSpec { #[cfg(target_arch = "riscv64")] { - return TimeSpec::new(0, 0); + return PosixTimeSpec::new(0, 0); } } + + /// 换算成纳秒 + pub fn total_nanos(&self) -> i64 { + self.tv_sec * 1000000000 + self.tv_nsec + } } -impl Sub for TimeSpec { +impl Sub for PosixTimeSpec { type Output = Duration; fn sub(self, rhs: Self) -> Self::Output { let sec = self.tv_sec.checked_sub(rhs.tv_sec).unwrap_or(0); @@ -91,17 +102,17 @@ impl Sub for TimeSpec { } } -impl From for TimeSpec { +impl From for PosixTimeSpec { fn from(dur: Duration) -> Self { - TimeSpec { + PosixTimeSpec { tv_sec: dur.total_micros() as i64 / 1000000, tv_nsec: (dur.total_micros() as i64 % 1000000) * 1000, } } } -impl From for Duration { - fn from(val: TimeSpec) -> Self { +impl From for Duration { + fn from(val: PosixTimeSpec) -> Self { Duration::from_micros(val.tv_sec as u64 * 1000000 + val.tv_nsec as u64 / 1000) } } diff --git a/kernel/src/time/sleep.rs b/kernel/src/time/sleep.rs index 965f054ea..cf5a2437f 100644 --- a/kernel/src/time/sleep.rs +++ b/kernel/src/time/sleep.rs @@ -14,7 +14,7 @@ use crate::{ use super::{ timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, - TimeArch, TimeSpec, + PosixTimeSpec, TimeArch, }; /// @brief 休眠指定时间(单位:纳秒) @@ -24,7 +24,7 @@ use super::{ /// @return Ok(TimeSpec) 剩余休眠时间 /// /// @return Err(SystemError) 错误码 -pub fn nanosleep(sleep_time: TimeSpec) -> Result { +pub fn nanosleep(sleep_time: PosixTimeSpec) -> Result { if sleep_time.tv_nsec < 0 || sleep_time.tv_nsec >= 1000000000 { return Err(SystemError::EINVAL); } @@ -34,7 +34,7 @@ pub fn nanosleep(sleep_time: TimeSpec) -> Result { while CurrentTimeArch::get_cycles() < expired_tsc { spin_loop() } - return Ok(TimeSpec { + return Ok(PosixTimeSpec { tv_sec: 0, tv_nsec: 0, }); @@ -59,7 +59,7 @@ pub fn nanosleep(sleep_time: TimeSpec) -> Result { let end_time = getnstimeofday(); // 返回正确的剩余时间 let real_sleep_time = end_time - start_time; - let rm_time: TimeSpec = (sleep_time - real_sleep_time.into()).into(); + let rm_time: PosixTimeSpec = (sleep_time - real_sleep_time.into()).into(); return Ok(rm_time); } @@ -71,7 +71,7 @@ pub fn nanosleep(sleep_time: TimeSpec) -> Result { /// @return Ok(TimeSpec) 剩余休眠时间 /// /// @return Err(SystemError) 错误码 -pub fn usleep(sleep_time: TimeSpec) -> Result { +pub fn usleep(sleep_time: PosixTimeSpec) -> Result { match nanosleep(sleep_time) { Ok(value) => return Ok(value), Err(err) => return Err(err), @@ -89,7 +89,7 @@ pub fn usleep(sleep_time: TimeSpec) -> Result { /// @return Err(SystemError) 错误码 #[no_mangle] pub extern "C" fn rs_usleep(usec: useconds_t) -> i32 { - let sleep_time = TimeSpec { + let sleep_time = PosixTimeSpec { tv_sec: (usec / 1000000) as i64, tv_nsec: ((usec % 1000000) * 1000) as i64, }; diff --git a/kernel/src/time/syscall.rs b/kernel/src/time/syscall.rs index c7bea0d94..b936e6ba4 100644 --- a/kernel/src/time/syscall.rs +++ b/kernel/src/time/syscall.rs @@ -5,7 +5,7 @@ use system_error::SystemError; use crate::{ syscall::{user_access::UserBufferWriter, Syscall}, - time::{sleep::nanosleep, TimeSpec}, + time::{sleep::nanosleep, PosixTimeSpec}, }; use super::timekeeping::{do_gettimeofday, getnstimeofday}; @@ -70,13 +70,13 @@ impl Syscall { /// /// @return Err(SystemError) 错误码 pub fn nanosleep( - sleep_time: *const TimeSpec, - rm_time: *mut TimeSpec, + sleep_time: *const PosixTimeSpec, + rm_time: *mut PosixTimeSpec, ) -> Result { if sleep_time.is_null() { return Err(SystemError::EFAULT); } - let slt_spec = TimeSpec { + let slt_spec = PosixTimeSpec { tv_sec: unsafe { *sleep_time }.tv_sec, tv_nsec: unsafe { *sleep_time }.tv_nsec, }; @@ -131,7 +131,7 @@ impl Syscall { return Ok(0); } - pub fn clock_gettime(clock_id: c_int, tp: *mut TimeSpec) -> Result { + pub fn clock_gettime(clock_id: c_int, tp: *mut PosixTimeSpec) -> Result { let clock_id = PosixClockID::try_from(clock_id)?; if clock_id != PosixClockID::Realtime { kwarn!("clock_gettime: currently only support Realtime clock, but got {:?}. Defaultly return realtime!!!\n", clock_id); @@ -139,8 +139,11 @@ impl Syscall { if tp.is_null() { return Err(SystemError::EFAULT); } - let mut tp_buf = - UserBufferWriter::new::(tp, core::mem::size_of::(), true)?; + let mut tp_buf = UserBufferWriter::new::( + tp, + core::mem::size_of::(), + true, + )?; let timespec = getnstimeofday(); diff --git a/kernel/src/time/timekeep.rs b/kernel/src/time/timekeep.rs index 758064b9a..0d81d6fa2 100644 --- a/kernel/src/time/timekeep.rs +++ b/kernel/src/time/timekeep.rs @@ -4,7 +4,7 @@ use system_error::SystemError; use crate::driver::rtc::interface::rtc_read_time_default; -use super::TimeSpec; +use super::PosixTimeSpec; #[allow(non_camel_case_types)] pub type ktime_t = i64; @@ -20,7 +20,7 @@ fn ktime_to_ns(kt: ktime_t) -> i64 { /// 注意,由于当前未引入时区,因此本函数默认时区为UTC+8来计算 fn ktime_get_real() -> Result { let rtc_time = rtc_read_time_default()?; - let time_spec: TimeSpec = rtc_time.into(); + let time_spec: PosixTimeSpec = rtc_time.into(); let r = time_spec.tv_sec * 1_000_000_000 + time_spec.tv_nsec; return Ok(r); } diff --git a/kernel/src/time/timekeeping.rs b/kernel/src/time/timekeeping.rs index 3d89dcec0..136805751 100644 --- a/kernel/src/time/timekeeping.rs +++ b/kernel/src/time/timekeeping.rs @@ -10,7 +10,7 @@ use crate::{ time::{ jiffies::{clocksource_default_clock, jiffies_init}, timekeep::ktime_get_real_ns, - TimeSpec, + PosixTimeSpec, }, }; @@ -64,10 +64,10 @@ pub struct TimekeeperData { ntp_error_shift: i32, /// NTP调整时钟乘法器 mult: u32, - raw_time: TimeSpec, - wall_to_monotonic: TimeSpec, - total_sleep_time: TimeSpec, - xtime: TimeSpec, + raw_time: PosixTimeSpec, + wall_to_monotonic: PosixTimeSpec, + total_sleep_time: PosixTimeSpec, + xtime: PosixTimeSpec, } impl TimekeeperData { pub fn new() -> Self { @@ -82,19 +82,19 @@ impl TimekeeperData { ntp_error: Default::default(), ntp_error_shift: Default::default(), mult: Default::default(), - xtime: TimeSpec { + xtime: PosixTimeSpec { tv_nsec: 0, tv_sec: 0, }, - wall_to_monotonic: TimeSpec { + wall_to_monotonic: PosixTimeSpec { tv_nsec: 0, tv_sec: 0, }, - total_sleep_time: TimeSpec { + total_sleep_time: PosixTimeSpec { tv_nsec: 0, tv_sec: 0, }, - raw_time: TimeSpec { + raw_time: PosixTimeSpec { tv_nsec: 0, tv_sec: 0, }, @@ -192,11 +192,11 @@ pub fn timekeeper_init() { /// ## 返回值 /// /// * 'TimeSpec' - 时间戳 -pub fn getnstimeofday() -> TimeSpec { +pub fn getnstimeofday() -> PosixTimeSpec { // kdebug!("enter getnstimeofday"); let nsecs; - let mut xtime: TimeSpec; + let mut xtime: PosixTimeSpec; loop { match timekeeper().inner.try_read_irqsave() { None => continue, @@ -238,7 +238,7 @@ pub fn do_gettimeofday() -> PosixTimeval { }; } -pub fn do_settimeofday64(time: TimeSpec) -> Result<(), SystemError> { +pub fn do_settimeofday64(time: PosixTimeSpec) -> Result<(), SystemError> { timekeeper().inner.write_irqsave().xtime = time; // todo: 模仿linux,实现时间误差校准。 // https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312 diff --git a/kernel/src/virt/kvm/kvm_dev.rs b/kernel/src/virt/kvm/kvm_dev.rs index fc03c1a73..d5243941a 100644 --- a/kernel/src/virt/kvm/kvm_dev.rs +++ b/kernel/src/virt/kvm/kvm_dev.rs @@ -7,7 +7,7 @@ use crate::filesystem::vfs::{ }; use crate::libs::spinlock::SpinLockGuard; use crate::process::ProcessManager; -use crate::{arch::KVMArch, libs::spinlock::SpinLock, time::TimeSpec}; +use crate::{arch::KVMArch, libs::spinlock::SpinLock, time::PosixTimeSpec}; use crate::{filesystem, kdebug}; // use crate::virt::kvm::{host_stack}; use super::push_vm; @@ -59,9 +59,9 @@ impl LockedKvmInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::KvmDevice, // 文件夹,block设备,char设备 mode: filesystem::vfs::syscall::ModeType::S_IALLUGO, nlinks: 1, diff --git a/kernel/src/virt/kvm/vcpu_dev.rs b/kernel/src/virt/kvm/vcpu_dev.rs index 5c9ae2264..31d1bbe89 100644 --- a/kernel/src/virt/kvm/vcpu_dev.rs +++ b/kernel/src/virt/kvm/vcpu_dev.rs @@ -12,7 +12,7 @@ use crate::syscall::user_access::copy_from_user; use crate::virt::kvm::vcpu::Vcpu; use crate::virt::kvm::vm; use crate::{filesystem, kdebug}; -use crate::{libs::spinlock::SpinLock, time::TimeSpec}; +use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec}; use alloc::{ string::String, sync::{Arc, Weak}, @@ -70,9 +70,9 @@ impl LockedVcpuInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::KvmDevice, // 文件夹,block设备,char设备 mode: filesystem::vfs::syscall::ModeType::S_IALLUGO, nlinks: 1, diff --git a/kernel/src/virt/kvm/vm_dev.rs b/kernel/src/virt/kvm/vm_dev.rs index aecf6c487..f860da621 100644 --- a/kernel/src/virt/kvm/vm_dev.rs +++ b/kernel/src/virt/kvm/vm_dev.rs @@ -13,7 +13,7 @@ use crate::virt::kvm::host_mem::KvmUserspaceMemoryRegion; use crate::virt::kvm::update_vm; use crate::virt::kvm::vcpu_dev::LockedVcpuInode; use crate::virt::kvm::vm; -use crate::{arch::KVMArch, libs::spinlock::SpinLock, time::TimeSpec}; +use crate::{arch::KVMArch, libs::spinlock::SpinLock, time::PosixTimeSpec}; use crate::{filesystem, kdebug}; use alloc::{ string::String, @@ -68,9 +68,9 @@ impl LockedVmInode { size: 0, blk_size: 0, blocks: 0, - atime: TimeSpec::default(), - mtime: TimeSpec::default(), - ctime: TimeSpec::default(), + atime: PosixTimeSpec::default(), + mtime: PosixTimeSpec::default(), + ctime: PosixTimeSpec::default(), file_type: FileType::KvmDevice, // 文件夹,block设备,char设备 mode: filesystem::vfs::syscall::ModeType::S_IALLUGO, nlinks: 1, diff --git a/user/apps/test_shm/.gitignore b/user/apps/test_shm/.gitignore new file mode 100644 index 000000000..fdb5d08b8 --- /dev/null +++ b/user/apps/test_shm/.gitignore @@ -0,0 +1,3 @@ +info +sender +receiver \ No newline at end of file diff --git a/user/apps/test_shm/Makefile b/user/apps/test_shm/Makefile new file mode 100644 index 000000000..d04214db0 --- /dev/null +++ b/user/apps/test_shm/Makefile @@ -0,0 +1,25 @@ +ifeq ($(ARCH), x86_64) + CROSS_COMPILE=x86_64-linux-musl- +else ifeq ($(ARCH), riscv64) + CROSS_COMPILE=riscv64-linux-musl- +endif + +CC=$(CROSS_COMPILE)gcc + +NAME_PREFIX=test_shm_ + +all: sender.c receiver.c test_info.c + $(CC) -static -o $(NAME_PREFIX)sender sender.c + $(CC) -static -o $(NAME_PREFIX)receiver receiver.c + $(CC) -static -o $(NAME_PREFIX)info test_info.c + +.PHONY: install clean +install: all + mv $(NAME_PREFIX)sender $(DADK_CURRENT_BUILD_DIR)/ + mv $(NAME_PREFIX)receiver $(DADK_CURRENT_BUILD_DIR)/ + mv $(NAME_PREFIX)info $(DADK_CURRENT_BUILD_DIR)/ + +clean: + rm $(NAME_PREFIX)receiver $(NAME_PREFIX)sender $(NAME_PREFIX)info *.o + +fmt: diff --git a/user/apps/test_shm/receiver.c b/user/apps/test_shm/receiver.c new file mode 100644 index 000000000..14e8ea0eb --- /dev/null +++ b/user/apps/test_shm/receiver.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHM_SIZE 9999 + +int main() +{ + int shmid; + char *shmaddr; + key_t key = 6666; + + // 测试shmget + shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT); + if (shmid < 0) + { + perror("shmget failed"); + exit(EXIT_FAILURE); + } + + // 测试shmat + shmaddr = shmat(shmid, 0, 0); + + char read_buf[20]; + memcpy(read_buf, shmaddr, 14); + + printf("Receiver receive: %s\n", read_buf); + + memset(shmaddr, 0, SHM_SIZE); + memcpy(shmaddr, "Reveiver Hello!", 16); + + shmdt(shmaddr); + + return 0; +} \ No newline at end of file diff --git a/user/apps/test_shm/sender.c b/user/apps/test_shm/sender.c new file mode 100644 index 000000000..cc87cc940 --- /dev/null +++ b/user/apps/test_shm/sender.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHM_SIZE 9999 + +int main() +{ + int shmid; + char *shmaddr; + key_t key = 6666; + + // 测试shmget + shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT); + if (shmid < 0) + { + perror("shmget failed"); + exit(EXIT_FAILURE); + } + + // 测试shmat + shmaddr = shmat(shmid, 0, 0); + + memset(shmaddr, 0, SHM_SIZE); + memcpy(shmaddr, "Sender Hello!", 14); + + int pid = fork(); + if (pid == 0) + { + execl("/bin/test_shm_receiver", NULL, NULL); + } + + waitpid(pid, NULL, 0); + + char read_buf[20]; + memcpy(read_buf, shmaddr, 16); + printf("Sender receive: %s\n", read_buf); + + shmdt(shmaddr); + shmctl(shmid, IPC_RMID, NULL); +} diff --git a/user/apps/test_shm/test_info.c b/user/apps/test_shm/test_info.c new file mode 100644 index 000000000..d7e181deb --- /dev/null +++ b/user/apps/test_shm/test_info.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void print_shmidds(struct shmid_ds *shminfo) +{ + struct ipc_perm shm_perm = shminfo->shm_perm; + + printf("ipc_perm:\n"); + printf("ipc_perm_key: %d\n", shm_perm.__key); + printf("uid: %d\n", shm_perm.uid); + printf("gid: %d\n", shm_perm.gid); + printf("cuid: %d\n", shm_perm.cuid); + printf("cgid: %d\n", shm_perm.cgid); + printf("mode: %d\n", shm_perm.mode); + printf("seq: %d\n", shm_perm.__seq); + printf("\n"); + + printf("shmid_ds:\n"); + printf("shm_atime: %lu\n", shminfo->shm_atime); + printf("shm_dtime: %lu\n", shminfo->shm_dtime); + printf("shm_ctime: %lu\n", shminfo->shm_ctime); + printf("shm_segsz: %lu\n", shminfo->shm_segsz); + printf("shm_cpid: %d\n", shminfo->shm_cpid); + printf("shm_lpid: %d\n", shminfo->shm_lpid); + printf("shm_nattch: %lu\n", shminfo->shm_nattch); + printf("\n"); +} + +const int SHM_SIZE = 9999; + +int main() +{ + int shmid; + char *shmaddr; + key_t key = 6666; + + // 测试shmget + shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT); + if (shmid < 0) + { + perror("shmget failed"); + exit(EXIT_FAILURE); + } + + // 测试shmat + shmaddr = shmat(shmid, 0, 0); + + // IPC_STAT: + printf("\n"); + printf("IPC_STAT:\n"); + struct shmid_ds shminfo2; + if (shmctl(shmid, IPC_STAT, &shminfo2) == -1) + { + // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + print_shmidds(&shminfo2); + + // 测试shmctl + // IPC_INFO + printf("IPC_INFO:\n"); + struct shminfo shmmetainfo; + if (shmctl(shmid, IPC_INFO, &shmmetainfo) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + printf("shmmax: %lu\n", shmmetainfo.shmmax); + printf("shmmin: %lu\n", shmmetainfo.shmmin); + printf("shmmni: %lu\n", shmmetainfo.shmmni); + printf("shmseg: %lu\n", shmmetainfo.shmseg); + printf("shmall: %lu\n", shmmetainfo.shmall); + + // SHM_INFO + printf("\n"); + printf("SHM_INFO:\n"); + struct shm_info shm_info; + if (shmctl(shmid, SHM_INFO, &shm_info) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + printf("__used_ids: %lu\n", shm_info.__used_ids); + printf("shm_tot: %lu\n", shm_info.shm_tot); + printf("shm_rss: %lu\n", shm_info.shm_rss); + printf("shm_swp: %lu\n", shm_info.shm_swp); + printf("__swap_attempts: %lu\n", shm_info.__swap_attempts); + printf("__swap_successes: %lu\n", shm_info.__swap_successes); + + // SHM_STAT + printf("\n"); + printf("SHM_STAT:\n"); + struct shmid_ds shminfo0; + if (shmctl(shmid, SHM_STAT, &shminfo0) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + print_shmidds(&shminfo0); + + // SHM_STAT_ANY + printf("SHM_STAT_ANY:\n"); + struct shmid_ds shminfo1; + if (shmctl(shmid, SHM_STAT_ANY, &shminfo1) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + print_shmidds(&shminfo1); + + // IPC_SET + printf("\n"); + printf("IPC_SET:\n"); + struct shmid_ds shminfo; + shminfo.shm_atime = 1; + shminfo.shm_dtime = 2; + shminfo.shm_ctime = 3; + shminfo.shm_segsz = 4; + shminfo.shm_cpid = 5; + shminfo.shm_lpid = 6; + shminfo.shm_nattch = 7; + if (shmctl(shmid, IPC_SET, &shminfo) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + + // IPC_RMID + printf("\n"); + printf("IPC_RMID:\n"); + if (shmctl(shmid, IPC_RMID, NULL) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + + // SHM_LOCK + printf("\n"); + printf("SHM_LOCK:\n"); + if (shmctl(shmid, SHM_LOCK, NULL) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } + + // SHM_UNLOCK + printf("\n"); + printf("SHM_UNLOCK:\n"); + if (shmctl(shmid, SHM_UNLOCK, NULL) == -1) + { // 获取共享内存段信息 + perror("shmctl"); + exit(EXIT_FAILURE); + } +} \ No newline at end of file diff --git a/user/dadk/config/test_shm-0.1.0.dadk b/user/dadk/config/test_shm-0.1.0.dadk new file mode 100644 index 000000000..1f1d9c891 --- /dev/null +++ b/user/dadk/config/test_shm-0.1.0.dadk @@ -0,0 +1,23 @@ +{ + "name": "test_shm", + "version": "0.1.0", + "description": "测试共享内存", + "task_type": { + "BuildFromSource": { + "Local": { + "path": "apps/test_shm" + } + } + }, + "depends": [ ], + "build": { + "build_command": "make install -j $(nproc)" + }, + "install": { + "in_dragonos_path": "/bin" + }, + "clean": { + "clean_command": "make clean" + }, + "envs": [] +} \ No newline at end of file