Browse Source

实现SystemV共享内存 (#690)

* 实现SystemV共享内存

* 测试shm

* 添加测试程序

* 完善细节

* 修正shm的时间数据错误的问题

* fix: devfs的metadata权限为0x777的错误

---------

Co-authored-by: longjin <[email protected]>
Jomo 11 months ago
parent
commit
6fc066ac11
49 changed files with 1567 additions and 202 deletions
  1. 2 1
      kernel/src/arch/x86_64/mm/mod.rs
  2. 4 4
      kernel/src/driver/disk/ahci/ahci_inode.rs
  3. 4 4
      kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs
  4. 4 4
      kernel/src/driver/keyboard/ps2_keyboard.rs
  5. 2 2
      kernel/src/driver/net/dma.rs
  6. 2 2
      kernel/src/driver/rtc/class.rs
  7. 3 3
      kernel/src/driver/rtc/mod.rs
  8. 2 2
      kernel/src/driver/virtio/virtio_impl.rs
  9. 7 7
      kernel/src/filesystem/devfs/mod.rs
  10. 4 4
      kernel/src/filesystem/devfs/null_dev.rs
  11. 4 4
      kernel/src/filesystem/devfs/zero_dev.rs
  12. 5 5
      kernel/src/filesystem/devpts/mod.rs
  13. 7 7
      kernel/src/filesystem/fat/fs.rs
  14. 7 7
      kernel/src/filesystem/kernfs/mod.rs
  15. 3 3
      kernel/src/filesystem/procfs/log.rs
  16. 7 7
      kernel/src/filesystem/procfs/mod.rs
  17. 10 10
      kernel/src/filesystem/ramfs/mod.rs
  18. 10 10
      kernel/src/filesystem/vfs/mod.rs
  19. 15 15
      kernel/src/filesystem/vfs/syscall.rs
  20. 1 0
      kernel/src/ipc/mod.rs
  21. 4 4
      kernel/src/ipc/pipe.rs
  22. 658 0
      kernel/src/ipc/shm.rs
  23. 276 3
      kernel/src/ipc/syscall.rs
  24. 2 2
      kernel/src/libs/futex/futex.rs
  25. 2 2
      kernel/src/libs/futex/syscall.rs
  26. 2 2
      kernel/src/libs/printk.rs
  27. 18 3
      kernel/src/mm/allocator/page_frame.rs
  28. 3 0
      kernel/src/mm/init.rs
  29. 44 3
      kernel/src/mm/page.rs
  30. 23 0
      kernel/src/mm/syscall.rs
  31. 24 14
      kernel/src/mm/ucontext.rs
  32. 2 2
      kernel/src/net/event_poll/mod.rs
  33. 3 3
      kernel/src/net/event_poll/syscall.rs
  34. 3 3
      kernel/src/process/resource.rs
  35. 37 9
      kernel/src/syscall/mod.rs
  36. 23 12
      kernel/src/time/mod.rs
  37. 6 6
      kernel/src/time/sleep.rs
  38. 10 7
      kernel/src/time/syscall.rs
  39. 2 2
      kernel/src/time/timekeep.rs
  40. 12 12
      kernel/src/time/timekeeping.rs
  41. 4 4
      kernel/src/virt/kvm/kvm_dev.rs
  42. 4 4
      kernel/src/virt/kvm/vcpu_dev.rs
  43. 4 4
      kernel/src/virt/kvm/vm_dev.rs
  44. 3 0
      user/apps/test_shm/.gitignore
  45. 25 0
      user/apps/test_shm/Makefile
  46. 40 0
      user/apps/test_shm/receiver.c
  47. 46 0
      user/apps/test_shm/sender.c
  48. 161 0
      user/apps/test_shm/test_info.c
  49. 23 0
      user/dadk/config/test_shm-0.1.0.dadk

+ 2 - 1
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 {

+ 4 - 4
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,

+ 4 - 4
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<Arc<Ps2MouseDevice>> = 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,

+ 4 - 4
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,

+ 2 - 2
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<u8>, 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;

+ 2 - 2
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<RtcGeneralDevice>) {
     }
 
     let time = r.unwrap();
-    let timespec64: TimeSpec = time.into();
+    let timespec64: PosixTimeSpec = time.into();
     let r = do_settimeofday64(timespec64);
     dev.set_hc2sys_result(r);
 

+ 3 - 3
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<RtcTime> for TimeSpec {
+impl From<RtcTime> for PosixTimeSpec {
     fn from(val: RtcTime) -> Self {
         let instant = Instant::mktime64(
             val.year_real() as u32,
@@ -155,7 +155,7 @@ impl From<RtcTime> for TimeSpec {
          * 存储最接近的值会减慢同步 API 的速度。因此,这里我们存储截断的值
          * 并在后面加上 0.5s 的最佳猜测。
          */
-        TimeSpec::new(instant.secs(), (NSEC_PER_SEC >> 1).into())
+        PosixTimeSpec::new(instant.secs(), (NSEC_PER_SEC >> 1).into())
     }
 }
 

+ 2 - 2
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;

+ 7 - 7
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,

+ 4 - 4
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,

+ 4 - 4
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,

+ 5 - 5
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,

+ 7 - 7
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,

+ 7 - 7
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(),

+ 3 - 3
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<usize> 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,

+ 7 - 7
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,

+ 10 - 10
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,

+ 10 - 10
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,

+ 15 - 15
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,
             },

+ 1 - 0
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;

+ 4 - 4
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,

+ 658 - 0
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<SpinLock<ShmManager>> = 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<usize> 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<ShmId, KernelShm>,
+    /// ShmKey映射ShmId表
+    key2id: HashMap<ShmKey, ShmId>,
+}
+
+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<usize, SystemError> {
+        // 判断共享内存大小是否过小或溢出
+        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<usize, SystemError> {
+        let mut user_buffer_writer = UserBufferWriter::new(
+            user_buf as *mut u8,
+            core::mem::size_of::<PosixShmMetaInfo>(),
+            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<usize, SystemError> {
+        // 已使用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::<PosixShmInfo>(),
+            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<usize, SystemError> {
+        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::<PosixShmIdDs>(),
+            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<usize, SystemError> {
+        let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
+
+        let user_buffer_reader =
+            UserBufferReader::new(user_buf, core::mem::size_of::<PosixShmIdDs>(), 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<usize, SystemError> {
+        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<usize, SystemError> {
+        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<usize, SystemError> {
+        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<usize> = 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::<Vec<_>>(),
+            );
+
+            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,
+        }
+    }
+}

+ 276 - 3
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<usize, SystemError> {
+        // 暂不支持巨页
+        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<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: PageFlags<MMArch> =
+                    PageFlags::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)?;
+
+                // 必须在取消映射前获取到PageFlags
+                let page_flags = address_write_guard
+                    .user_mapper
+                    .utable
+                    .translate(vaddr)
+                    .ok_or(SystemError::EINVAL)?
+                    .1;
+
+                // 取消原映射
+                let flusher: PageFlushAll<MMArch> = PageFlushAll::new();
+                vma.unmap(&mut address_write_guard.user_mapper.utable, flusher);
+
+                // 将该虚拟内存区域映射到共享内存区域
+                let mut page_manager_guard = page_manager_lock_irqsave();
+                let mut virt = VirtPageFrame::new(vaddr);
+                for _ in 0..count.data() {
+                    let r = unsafe {
+                        address_write_guard.user_mapper.utable.map_phys(
+                            virt.virt_address(),
+                            phys.phys_address(),
+                            page_flags,
+                        )
+                    }
+                    .expect("Failed to map zero, may be OOM error");
+                    r.flush();
+
+                    // 将vma加入到对应Page的anon_vma
+                    page_manager_guard
+                        .get_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<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.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),
+        }
+    }
 }

+ 2 - 2
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<TimeSpec>,
+        abs_time: Option<PosixTimeSpec>,
         bitset: u32,
     ) -> Result<usize, SystemError> {
         if bitset == 0 {

+ 2 - 2
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<TimeSpec>,
+        timeout: Option<PosixTimeSpec>,
         uaddr2: VirtAddr,
         val2: u32,
         val3: u32,

+ 2 - 2
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());

+ 18 - 3
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();
     }
 }

+ 3 - 0
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(

+ 44 - 3
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<ShmId>,
     /// 映射到当前page的VMA
     anon_vma: HashSet<Arc<LockedVMA>>,
 }
 
 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<ShmId> {
+        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<Arc<LockedVMA>> {
+        &self.anon_vma
     }
 }
 
@@ -682,7 +718,12 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         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);
     }
 

+ 23 - 0
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<ProtFlags> for VmFlags {
     }
 }
 
+impl From<ShmFlags> 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<VmFlags> for MapFlags {
     fn from(value: VmFlags) -> Self {
         let mut map_flags = MapFlags::MAP_NONE;

+ 24 - 14
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<MMArch> = 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<VMA> {
         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());
 
             // 清空内存

+ 2 - 2
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>,
+        timespec: Option<PosixTimeSpec>,
     ) -> Result<usize, SystemError> {
         let current_pcb = ProcessManager::current_pcb();
         let fd_table = current_pcb.fd_table();

+ 3 - 3
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

+ 3 - 3
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

+ 37 - 9
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::<TimeSpec>()).is_err()
-                        || verify_area(virt_rem, core::mem::size_of::<TimeSpec>()).is_err())
+                    && (verify_area(virt_req, core::mem::size_of::<PosixTimeSpec>()).is_err()
+                        || verify_area(virt_rem, core::mem::size_of::<PosixTimeSpec>()).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::<TimeSpec>(),
+                        utime as *const PosixTimeSpec,
+                        core::mem::size_of::<PosixTimeSpec>(),
                         true,
                     )?;
 
-                    timespec = Some(*reader.read_one_from_user::<TimeSpec>(0)?);
+                    timespec = Some(*reader.read_one_from_user::<PosixTimeSpec>(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),
         };
 

+ 23 - 12
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<Duration> for TimeSpec {
+impl From<Duration> 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<TimeSpec> for Duration {
-    fn from(val: TimeSpec) -> Self {
+impl From<PosixTimeSpec> for Duration {
+    fn from(val: PosixTimeSpec) -> Self {
         Duration::from_micros(val.tv_sec as u64 * 1000000 + val.tv_nsec as u64 / 1000)
     }
 }

+ 6 - 6
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<TimeSpec, SystemError> {
+pub fn nanosleep(sleep_time: PosixTimeSpec) -> Result<PosixTimeSpec, SystemError> {
     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<TimeSpec, SystemError> {
         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<TimeSpec, SystemError> {
     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<TimeSpec, SystemError> {
 /// @return Ok(TimeSpec) 剩余休眠时间
 ///
 /// @return Err(SystemError) 错误码
-pub fn usleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
+pub fn usleep(sleep_time: PosixTimeSpec) -> Result<PosixTimeSpec, SystemError> {
     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<TimeSpec, SystemError> {
 /// @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,
     };

+ 10 - 7
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<usize, SystemError> {
         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<usize, SystemError> {
+    pub fn clock_gettime(clock_id: c_int, tp: *mut PosixTimeSpec) -> Result<usize, SystemError> {
         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::<TimeSpec>(tp, core::mem::size_of::<TimeSpec>(), true)?;
+        let mut tp_buf = UserBufferWriter::new::<PosixTimeSpec>(
+            tp,
+            core::mem::size_of::<PosixTimeSpec>(),
+            true,
+        )?;
 
         let timespec = getnstimeofday();
 

+ 2 - 2
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<ktime_t, SystemError> {
     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);
 }

+ 12 - 12
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

+ 4 - 4
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,

+ 4 - 4
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,

+ 4 - 4
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,

+ 3 - 0
user/apps/test_shm/.gitignore

@@ -0,0 +1,3 @@
+info
+sender
+receiver

+ 25 - 0
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:

+ 40 - 0
user/apps/test_shm/receiver.c

@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#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;
+}

+ 46 - 0
user/apps/test_shm/sender.c

@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#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);
+}

+ 161 - 0
user/apps/test_shm/test_info.c

@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <string.h>
+#include <sys/wait.h>
+
+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);
+    }
+}

+ 23 - 0
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": []
+}