Browse Source

Merge remote-tracking branch 'origin/master' into origin-network-rebuild

sparkzky 5 days ago
parent
commit
ce7eeee463
100 changed files with 4563 additions and 448 deletions
  1. 1 2
      kernel/crates/bitmap/src/lib.rs
  2. 28 18
      kernel/crates/bitmap/src/static_bitmap.rs
  3. 2 1
      kernel/crates/bitmap/src/traits.rs
  4. 17 17
      kernel/crates/bitmap/tests/static-bitmap.rs
  5. 4 0
      kernel/src/bpf/map/mod.rs
  6. 4 0
      kernel/src/bpf/prog/mod.rs
  7. 36 1
      kernel/src/driver/base/block/gendisk/mod.rs
  8. 42 6
      kernel/src/driver/block/virtio_blk.rs
  9. 2 2
      kernel/src/driver/char/virtio_console.rs
  10. 0 1
      kernel/src/driver/clocksource/acpi_pm.rs
  11. 2 2
      kernel/src/driver/clocksource/timer_riscv.rs
  12. 15 1
      kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs
  13. 16 1
      kernel/src/driver/keyboard/ps2_keyboard.rs
  14. 2 2
      kernel/src/driver/scsi/mod.rs
  15. 52 7
      kernel/src/driver/tty/tty_device.rs
  16. 3 3
      kernel/src/driver/tty/tty_ldisc/ntty.rs
  17. 2 2
      kernel/src/driver/tty/virtual_terminal/virtual_console.rs
  18. 15 1
      kernel/src/driver/video/fbdev/base/fbmem.rs
  19. 35 23
      kernel/src/filesystem/devfs/mod.rs
  20. 15 0
      kernel/src/filesystem/devfs/null_dev.rs
  21. 15 0
      kernel/src/filesystem/devfs/zero_dev.rs
  22. 27 18
      kernel/src/filesystem/devpts/mod.rs
  23. 6 0
      kernel/src/filesystem/epoll/fs.rs
  24. 4 0
      kernel/src/filesystem/eventfd.rs
  25. 8 11
      kernel/src/filesystem/kernfs/mod.rs
  26. 11 0
      kernel/src/filesystem/page_cache.rs
  27. 329 103
      kernel/src/filesystem/procfs/mod.rs
  28. 73 0
      kernel/src/filesystem/procfs/proc_mounts.rs
  29. 3 2
      kernel/src/filesystem/sysfs/mod.rs
  30. 4 2
      kernel/src/filesystem/vfs/file.rs
  31. 19 18
      kernel/src/filesystem/vfs/mod.rs
  32. 239 17
      kernel/src/filesystem/vfs/mount.rs
  33. 2 8
      kernel/src/filesystem/vfs/open.rs
  34. 3 0
      kernel/src/filesystem/vfs/syscall/mod.rs
  35. 42 0
      kernel/src/filesystem/vfs/syscall/sys_fsync.rs
  36. 21 9
      kernel/src/filesystem/vfs/syscall/sys_mount.rs
  37. 69 0
      kernel/src/filesystem/vfs/syscall/sys_sync.rs
  38. 11 1
      kernel/src/filesystem/vfs/vcore.rs
  39. 5 2
      kernel/src/init/initial_kthread.rs
  40. 6 2
      kernel/src/ipc/pipe.rs
  41. 100 45
      kernel/src/libs/futex/futex.rs
  42. 7 4
      kernel/src/libs/futex/syscall.rs
  43. 2 2
      kernel/src/mm/no_init.rs
  44. 4 0
      kernel/src/perf/bpf.rs
  45. 4 0
      kernel/src/perf/kprobe.rs
  46. 4 0
      kernel/src/perf/mod.rs
  47. 8 0
      kernel/src/perf/tracepoint.rs
  48. 13 0
      kernel/src/process/cred.rs
  49. 0 1
      kernel/src/process/fork.rs
  50. 1 4
      kernel/src/process/mod.rs
  51. 25 4
      kernel/src/process/namespace/mnt.rs
  52. 1 0
      kernel/src/process/namespace/mod.rs
  53. 11 3
      kernel/src/process/namespace/nsproxy.rs
  54. 4 1
      kernel/src/process/namespace/pid_namespace.rs
  55. 110 0
      kernel/src/process/namespace/unshare.rs
  56. 12 0
      kernel/src/process/namespace/user_namespace.rs
  57. 2 0
      kernel/src/process/syscall/mod.rs
  58. 93 0
      kernel/src/process/syscall/sys_groups.rs
  59. 44 0
      kernel/src/process/syscall/sys_unshare.rs
  60. 408 67
      kernel/src/syscall/user_access.rs
  61. 14 0
      kernel/src/virt/vm/kvm_dev.rs
  62. 0 3
      tools/debugging/logmonitor/src/lib.rs
  63. 1 0
      user/apps/c_unitest/.gitignore
  64. 35 0
      user/apps/c_unitest/Makefile
  65. 179 0
      user/apps/c_unitest/dmesg.c
  66. 215 0
      user/apps/c_unitest/http_server.c
  67. 202 0
      user/apps/c_unitest/test_bind.c
  68. 43 0
      user/apps/c_unitest/test_cred.c
  69. 103 0
      user/apps/c_unitest/test_cross_process_futex.c
  70. 30 0
      user/apps/c_unitest/test_dup3.c
  71. 0 0
      user/apps/c_unitest/test_epoll.c
  72. 50 0
      user/apps/c_unitest/test_eventfd.c
  73. 3 3
      user/apps/c_unitest/test_fifo_write.c
  74. 57 0
      user/apps/c_unitest/test_filemap.c
  75. 2 3
      user/apps/c_unitest/test_fork_wait.c
  76. 0 0
      user/apps/c_unitest/test_fstat.c
  77. 41 0
      user/apps/c_unitest/test_fstatfs.c
  78. 22 0
      user/apps/c_unitest/test_gettimeofday.c
  79. 534 0
      user/apps/c_unitest/test_kvm.c
  80. 70 0
      user/apps/c_unitest/test_mkfifo.c
  81. 64 0
      user/apps/c_unitest/test_newfstatat.c
  82. 83 0
      user/apps/c_unitest/test_overlayfs.c
  83. 0 0
      user/apps/c_unitest/test_poll.c
  84. 0 0
      user/apps/c_unitest/test_ppoll.c
  85. 83 0
      user/apps/c_unitest/test_processgroup.c
  86. 47 0
      user/apps/c_unitest/test_pty.c
  87. 115 0
      user/apps/c_unitest/test_ramfs.c
  88. 0 0
      user/apps/c_unitest/test_select.c
  89. 77 0
      user/apps/c_unitest/test_session.c
  90. 149 0
      user/apps/c_unitest/test_shm_info.c
  91. 38 0
      user/apps/c_unitest/test_shm_receiver.c
  92. 43 0
      user/apps/c_unitest/test_shm_sender.c
  93. 25 0
      user/apps/c_unitest/test_sigint.c
  94. 19 24
      user/apps/c_unitest/test_signal.c
  95. 0 0
      user/apps/c_unitest/test_signal_restart.c
  96. 128 0
      user/apps/c_unitest/test_sigprocmask.c
  97. 0 0
      user/apps/c_unitest/test_stack.c
  98. 36 0
      user/apps/c_unitest/test_statfs.c
  99. 1 1
      user/apps/c_unitest/test_uart.c
  100. 11 0
      user/apps/c_unitest/test_utimensat.c

+ 1 - 2
kernel/crates/bitmap/src/lib.rs

@@ -1,7 +1,5 @@
 #![no_std]
 #![no_std]
 #![feature(core_intrinsics)]
 #![feature(core_intrinsics)]
-#![allow(incomplete_features)] // for const generics
-#![feature(generic_const_exprs)]
 #![deny(clippy::all)]
 #![deny(clippy::all)]
 #![allow(internal_features)]
 #![allow(internal_features)]
 #![allow(clippy::needless_return)]
 #![allow(clippy::needless_return)]
@@ -15,4 +13,5 @@ mod static_bitmap;
 pub mod traits;
 pub mod traits;
 pub use alloc_bitmap::AllocBitmap;
 pub use alloc_bitmap::AllocBitmap;
 pub use bitmap_core::BitMapCore;
 pub use bitmap_core::BitMapCore;
+pub use static_bitmap::static_bitmap_size;
 pub use static_bitmap::StaticBitmap;
 pub use static_bitmap::StaticBitmap;

+ 28 - 18
kernel/crates/bitmap/src/static_bitmap.rs

@@ -2,44 +2,54 @@ use core::mem::size_of;
 
 
 use crate::{bitmap_core::BitMapCore, traits::BitMapOps};
 use crate::{bitmap_core::BitMapCore, traits::BitMapOps};
 
 
+pub const fn static_bitmap_size<const N: usize>() -> usize {
+    N.div_ceil(usize::BITS as usize)
+}
+
 /// 静态位图
 /// 静态位图
 ///
 ///
 /// 该位图的大小在编译时确定,不可变
 /// 该位图的大小在编译时确定,不可变
 #[derive(Debug, Clone)]
 #[derive(Debug, Clone)]
-pub struct StaticBitmap<const N: usize>
-where
-    [(); N.div_ceil(usize::BITS as usize)]:,
-{
-    pub data: [usize; N.div_ceil(usize::BITS as usize)],
+pub struct StaticBitmap<const N: usize, const M: usize> {
+    pub data: [usize; M],
     core: BitMapCore<usize>,
     core: BitMapCore<usize>,
 }
 }
 
 
-impl<const N: usize> Default for StaticBitmap<N>
-where
-    [(); N.div_ceil(usize::BITS as usize)]:,
-{
+/// 创建静态位图的宏
+///
+/// 使用方式:static_bitmap!(items_count) 创建一个能容纳 items_count 个位的静态位图
+///
+/// 示例:
+/// ```rust
+/// use bitmap::static_bitmap;
+/// use bitmap::StaticBitmap;
+///
+/// let bmp: static_bitmap!(100) = StaticBitmap::new();
+/// ```
+#[macro_export]
+macro_rules! static_bitmap {
+    ($count:expr) => {
+        $crate::StaticBitmap<{ $count }, { $crate::static_bitmap_size::<{ $count }>() }>
+    };
+}
+
+impl<const N: usize, const M: usize> Default for StaticBitmap<N, M> {
     fn default() -> Self {
     fn default() -> Self {
         Self::new()
         Self::new()
     }
     }
 }
 }
 
 
-impl<const N: usize> StaticBitmap<N>
-where
-    [(); N.div_ceil(usize::BITS as usize)]:,
-{
+impl<const N: usize, const M: usize> StaticBitmap<N, M> {
     /// 创建一个新的静态位图
     /// 创建一个新的静态位图
     pub const fn new() -> Self {
     pub const fn new() -> Self {
         Self {
         Self {
-            data: [0; N.div_ceil(usize::BITS as usize)],
+            data: [0; M],
             core: BitMapCore::new(),
             core: BitMapCore::new(),
         }
         }
     }
     }
 }
 }
 
 
-impl<const N: usize> BitMapOps<usize> for StaticBitmap<N>
-where
-    [(); N.div_ceil(usize::BITS as usize)]:,
-{
+impl<const N: usize, const M: usize> BitMapOps<usize> for StaticBitmap<N, M> {
     #[inline]
     #[inline]
     fn get(&self, index: usize) -> Option<bool> {
     fn get(&self, index: usize) -> Option<bool> {
         return self.core.get(N, &self.data, index);
         return self.core.get(N, &self.data, index);

+ 2 - 1
kernel/crates/bitmap/src/traits.rs

@@ -241,9 +241,10 @@ pub trait BitMapOps<T: BitOps> {
     ///
     ///
     /// ```
     /// ```
     /// use bitmap::StaticBitmap;
     /// use bitmap::StaticBitmap;
+    /// use bitmap::static_bitmap;
     /// use bitmap::traits::BitMapOps;
     /// use bitmap::traits::BitMapOps;
     ///
     ///
-    /// let mut bitmap = StaticBitmap::<34>::new();
+    /// let mut bitmap: static_bitmap!(34) = StaticBitmap::new();
     /// assert_eq!(bitmap.len(), 34);
     /// assert_eq!(bitmap.len(), 34);
     /// ```
     /// ```
     ///
     ///

+ 17 - 17
kernel/crates/bitmap/tests/static-bitmap.rs

@@ -1,6 +1,6 @@
 //! 静态位图的集成测试
 //! 静态位图的集成测试
 
 
-use bitmap::{traits::BitMapOps, StaticBitmap};
+use bitmap::{static_bitmap, traits::BitMapOps, StaticBitmap};
 
 
 /// 测试空的位图
 /// 测试空的位图
 ///
 ///
@@ -10,7 +10,7 @@ use bitmap::{traits::BitMapOps, StaticBitmap};
 /// 测试空的位图
 /// 测试空的位图
 #[test]
 #[test]
 fn test_empty_bitmap_32() {
 fn test_empty_bitmap_32() {
-    let mut bitmap = StaticBitmap::<32>::new();
+    let mut bitmap: static_bitmap!(32) = StaticBitmap::new();
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.first_index(), None);
     assert_eq!(bitmap.first_index(), None);
@@ -40,7 +40,7 @@ fn test_empty_bitmap_32() {
 
 
 #[test]
 #[test]
 fn test_empty_bitmap_64() {
 fn test_empty_bitmap_64() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.first_index(), None);
     assert_eq!(bitmap.first_index(), None);
@@ -71,7 +71,7 @@ fn test_empty_bitmap_64() {
 /// 测试长度为32的bmp,其中第一个元素为1
 /// 测试长度为32的bmp,其中第一个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_32_first_1() {
 fn test_static_bitmap_32_first_1() {
-    let mut bitmap = StaticBitmap::<32>::new();
+    let mut bitmap: static_bitmap!(32) = StaticBitmap::new();
     bitmap.set(0, true);
     bitmap.set(0, true);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
@@ -112,7 +112,7 @@ fn test_static_bitmap_32_first_1() {
 /// 测试长度为32的bmp,其中中间某个元素为1
 /// 测试长度为32的bmp,其中中间某个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_32_middle_1() {
 fn test_static_bitmap_32_middle_1() {
-    let mut bitmap = StaticBitmap::<32>::new();
+    let mut bitmap: static_bitmap!(32) = StaticBitmap::new();
     bitmap.set(15, true);
     bitmap.set(15, true);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
@@ -154,7 +154,7 @@ fn test_static_bitmap_32_middle_1() {
 /// 测试长度为32的bmp,其中最后一个元素为1
 /// 测试长度为32的bmp,其中最后一个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_32_last_1() {
 fn test_static_bitmap_32_last_1() {
-    let mut bitmap = StaticBitmap::<32>::new();
+    let mut bitmap: static_bitmap!(32) = StaticBitmap::new();
     bitmap.set(31, true);
     bitmap.set(31, true);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
@@ -196,7 +196,7 @@ fn test_static_bitmap_32_last_1() {
 /// 测试长度为64的bmp,其中第一个元素为1
 /// 测试长度为64的bmp,其中第一个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_64_first_1() {
 fn test_static_bitmap_64_first_1() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     bitmap.set(0, true);
     bitmap.set(0, true);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
@@ -237,7 +237,7 @@ fn test_static_bitmap_64_first_1() {
 /// 测试长度为64的bmp,其中中间某个元素为1
 /// 测试长度为64的bmp,其中中间某个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_64_middle_1() {
 fn test_static_bitmap_64_middle_1() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     bitmap.set(15, true);
     bitmap.set(15, true);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
@@ -279,7 +279,7 @@ fn test_static_bitmap_64_middle_1() {
 /// 测试长度为64的bmp,其中最后一个元素为1
 /// 测试长度为64的bmp,其中最后一个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_64_last_1() {
 fn test_static_bitmap_64_last_1() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     bitmap.set(63, true);
     bitmap.set(63, true);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.size(), 8);
     assert_eq!(bitmap.size(), 8);
@@ -321,7 +321,7 @@ fn test_static_bitmap_64_last_1() {
 /// 测试长度为64的bmp,其中第一个和最后一个元素为1
 /// 测试长度为64的bmp,其中第一个和最后一个元素为1
 #[test]
 #[test]
 fn test_static_bitmap_64_two_1_first() {
 fn test_static_bitmap_64_two_1_first() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     bitmap.set(0, true);
     bitmap.set(0, true);
     bitmap.set(63, true);
     bitmap.set(63, true);
 
 
@@ -362,7 +362,7 @@ fn test_static_bitmap_64_two_1_first() {
 /// 测试长度为64的bmp,中间两个不相邻的元素为1
 /// 测试长度为64的bmp,中间两个不相邻的元素为1
 #[test]
 #[test]
 fn test_static_bitmap_64_two_1_middle() {
 fn test_static_bitmap_64_two_1_middle() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     bitmap.set(15, true);
     bitmap.set(15, true);
     bitmap.set(63, true);
     bitmap.set(63, true);
 
 
@@ -404,7 +404,7 @@ fn test_static_bitmap_64_two_1_middle() {
 
 
 #[test]
 #[test]
 fn test_static_bitmap_128_two_1_seperate_first() {
 fn test_static_bitmap_128_two_1_seperate_first() {
-    let mut bitmap = StaticBitmap::<128>::new();
+    let mut bitmap: static_bitmap!(128) = StaticBitmap::new();
 
 
     bitmap.set(0, true);
     bitmap.set(0, true);
     bitmap.set(127, true);
     bitmap.set(127, true);
@@ -444,7 +444,7 @@ fn test_static_bitmap_128_two_1_seperate_first() {
 /// 长度128, 第63、64bit为1
 /// 长度128, 第63、64bit为1
 #[test]
 #[test]
 fn test_static_bitmap_128_two_1_nearby_middle() {
 fn test_static_bitmap_128_two_1_nearby_middle() {
-    let mut bitmap = StaticBitmap::<128>::new();
+    let mut bitmap: static_bitmap!(128) = StaticBitmap::new();
 
 
     bitmap.set(63, true);
     bitmap.set(63, true);
     bitmap.set(64, true);
     bitmap.set(64, true);
@@ -494,7 +494,7 @@ fn test_static_bitmap_128_two_1_nearby_middle() {
 
 
 #[test]
 #[test]
 fn test_static_bitmap_full_32() {
 fn test_static_bitmap_full_32() {
-    let mut bitmap = StaticBitmap::<32>::new();
+    let mut bitmap: static_bitmap!(32) = StaticBitmap::new();
     bitmap.set_all(true);
     bitmap.set_all(true);
 
 
     assert_eq!(bitmap.len(), 32);
     assert_eq!(bitmap.len(), 32);
@@ -532,7 +532,7 @@ fn test_static_bitmap_full_32() {
 
 
 #[test]
 #[test]
 fn test_static_bitmap_full_64() {
 fn test_static_bitmap_full_64() {
-    let mut bitmap = StaticBitmap::<64>::new();
+    let mut bitmap: static_bitmap!(64) = StaticBitmap::new();
     bitmap.set_all(true);
     bitmap.set_all(true);
 
 
     assert_eq!(bitmap.len(), 64);
     assert_eq!(bitmap.len(), 64);
@@ -570,7 +570,7 @@ fn test_static_bitmap_full_64() {
 
 
 #[test]
 #[test]
 fn test_static_bitmap_full_100() {
 fn test_static_bitmap_full_100() {
-    let mut bitmap = StaticBitmap::<100>::new();
+    let mut bitmap: static_bitmap!(100) = StaticBitmap::new();
     bitmap.set_all(true);
     bitmap.set_all(true);
 
 
     assert_eq!(bitmap.len(), 100);
     assert_eq!(bitmap.len(), 100);
@@ -608,7 +608,7 @@ fn test_static_bitmap_full_100() {
 
 
 #[test]
 #[test]
 fn test_static_bitmap_full_128() {
 fn test_static_bitmap_full_128() {
-    let mut bitmap = StaticBitmap::<128>::new();
+    let mut bitmap: static_bitmap!(128) = StaticBitmap::new();
     bitmap.set_all(true);
     bitmap.set_all(true);
 
 
     assert_eq!(bitmap.len(), 128);
     assert_eq!(bitmap.len(), 128);

+ 4 - 0
kernel/src/bpf/map/mod.rs

@@ -182,6 +182,10 @@ impl IndexNode for BpfMap {
     fn list(&self) -> Result<Vec<String>> {
     fn list(&self) -> Result<Vec<String>> {
         Err(SystemError::ENOSYS)
         Err(SystemError::ENOSYS)
     }
     }
+
+    fn absolute_path(&self) -> core::result::Result<String, SystemError> {
+        Ok(String::from("BpfMap"))
+    }
 }
 }
 
 
 /// Create a map and return a file descriptor that refers to
 /// Create a map and return a file descriptor that refers to

+ 4 - 0
kernel/src/bpf/prog/mod.rs

@@ -95,6 +95,10 @@ impl IndexNode for BpfProg {
     fn list(&self) -> Result<Vec<String>> {
     fn list(&self) -> Result<Vec<String>> {
         Err(SystemError::ENOSYS)
         Err(SystemError::ENOSYS)
     }
     }
+
+    fn absolute_path(&self) -> core::result::Result<String, SystemError> {
+        Ok(String::from("BPF Program"))
+    }
 }
 }
 
 
 impl Drop for BpfProg {
 impl Drop for BpfProg {

+ 36 - 1
kernel/src/driver/base/block/gendisk/mod.rs

@@ -13,7 +13,7 @@ use system_error::SystemError;
 use crate::{
 use crate::{
     driver::base::device::device_number::DeviceNumber,
     driver::base::device::device_number::DeviceNumber,
     filesystem::{
     filesystem::{
-        devfs::{DevFS, DeviceINode},
+        devfs::{DevFS, DeviceINode, LockedDevFSInode},
         vfs::{syscall::ModeType, utils::DName, IndexNode, Metadata},
         vfs::{syscall::ModeType, utils::DName, IndexNode, Metadata},
     },
     },
     libs::{rwlock::RwLock, spinlock::SpinLockGuard},
     libs::{rwlock::RwLock, spinlock::SpinLockGuard},
@@ -32,6 +32,7 @@ pub struct GenDisk {
 
 
     device_num: DeviceNumber,
     device_num: DeviceNumber,
 
 
+    parent: RwLock<Weak<LockedDevFSInode>>,
     fs: RwLock<Weak<DevFS>>,
     fs: RwLock<Weak<DevFS>>,
     metadata: Metadata,
     metadata: Metadata,
     /// 对应/dev/下的设备名
     /// 对应/dev/下的设备名
@@ -69,6 +70,7 @@ impl GenDisk {
             block_size_log2: bsizelog2,
             block_size_log2: bsizelog2,
             idx,
             idx,
             device_num,
             device_num,
+            parent: RwLock::new(Weak::default()),
             fs: RwLock::new(Weak::default()),
             fs: RwLock::new(Weak::default()),
             metadata: Metadata::new(
             metadata: Metadata::new(
                 crate::filesystem::vfs::FileType::BlockDevice,
                 crate::filesystem::vfs::FileType::BlockDevice,
@@ -212,9 +214,11 @@ impl IndexNode for GenDisk {
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
         self.fs.read().upgrade().unwrap()
         self.fs.read().upgrade().unwrap()
     }
     }
+
     fn as_any_ref(&self) -> &dyn core::any::Any {
     fn as_any_ref(&self) -> &dyn core::any::Any {
         self
         self
     }
     }
+
     fn read_at(
     fn read_at(
         &self,
         &self,
         _offset: usize,
         _offset: usize,
@@ -224,6 +228,7 @@ impl IndexNode for GenDisk {
     ) -> Result<usize, SystemError> {
     ) -> Result<usize, SystemError> {
         Err(SystemError::EPERM)
         Err(SystemError::EPERM)
     }
     }
+
     fn write_at(
     fn write_at(
         &self,
         &self,
         _offset: usize,
         _offset: usize,
@@ -233,21 +238,51 @@ impl IndexNode for GenDisk {
     ) -> Result<usize, SystemError> {
     ) -> Result<usize, SystemError> {
         Err(SystemError::EPERM)
         Err(SystemError::EPERM)
     }
     }
+
     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
         Err(SystemError::ENOSYS)
         Err(SystemError::ENOSYS)
     }
     }
+
     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
         Ok(self.metadata.clone())
         Ok(self.metadata.clone())
     }
     }
+
     fn dname(&self) -> Result<DName, SystemError> {
     fn dname(&self) -> Result<DName, SystemError> {
         Ok(self.name.clone())
         Ok(self.name.clone())
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.parent.read();
+        if let Some(parent) = parent.upgrade() {
+            return Ok(parent as Arc<dyn IndexNode>);
+        }
+        Err(SystemError::ENOENT)
+    }
+
+    fn close(
+        &self,
+        _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
+    ) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn open(
+        &self,
+        _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
+        _mode: &crate::filesystem::vfs::file::FileMode,
+    ) -> Result<(), SystemError> {
+        Ok(())
+    }
 }
 }
 
 
 impl DeviceINode for GenDisk {
 impl DeviceINode for GenDisk {
     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
         *self.fs.write() = fs;
         *self.fs.write() = fs;
     }
     }
+
+    fn set_parent(&self, parent: Weak<LockedDevFSInode>) {
+        *self.parent.write() = parent;
+    }
 }
 }
 
 
 #[derive(Default)]
 #[derive(Default)]

+ 42 - 6
kernel/src/driver/block/virtio_blk.rs

@@ -8,7 +8,7 @@ use alloc::{
     sync::{Arc, Weak},
     sync::{Arc, Weak},
     vec::Vec,
     vec::Vec,
 };
 };
-use bitmap::traits::BitMapOps;
+use bitmap::{static_bitmap, traits::BitMapOps};
 use log::error;
 use log::error;
 use system_error::SystemError;
 use system_error::SystemError;
 use unified_init::macros::unified_init;
 use unified_init::macros::unified_init;
@@ -42,10 +42,10 @@ use crate::{
     },
     },
     exception::{irqdesc::IrqReturn, IrqNumber},
     exception::{irqdesc::IrqReturn, IrqNumber},
     filesystem::{
     filesystem::{
-        devfs::{DevFS, DeviceINode},
+        devfs::{DevFS, DeviceINode, LockedDevFSInode},
         kernfs::KernFSInode,
         kernfs::KernFSInode,
         mbr::MbrDiskPartionTable,
         mbr::MbrDiskPartionTable,
-        vfs::{syscall::ModeType, IndexNode, Metadata},
+        vfs::{syscall::ModeType, utils::DName, IndexNode, Metadata},
     },
     },
     init::initcall::INITCALL_POSTCORE,
     init::initcall::INITCALL_POSTCORE,
     libs::{
     libs::{
@@ -110,7 +110,7 @@ pub struct VirtIOBlkManager {
 }
 }
 
 
 struct InnerVirtIOBlkManager {
 struct InnerVirtIOBlkManager {
-    id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
+    id_bmp: static_bitmap!(VirtIOBlkManager::MAX_DEVICES),
     devname: [Option<DevName>; VirtIOBlkManager::MAX_DEVICES],
     devname: [Option<DevName>; VirtIOBlkManager::MAX_DEVICES],
 }
 }
 
 
@@ -164,7 +164,7 @@ pub struct VirtIOBlkDevice {
     inner: SpinLock<InnerVirtIOBlkDevice>,
     inner: SpinLock<InnerVirtIOBlkDevice>,
     locked_kobj_state: LockedKObjectState,
     locked_kobj_state: LockedKObjectState,
     self_ref: Weak<Self>,
     self_ref: Weak<Self>,
-
+    parent: RwLock<Weak<LockedDevFSInode>>,
     fs: RwLock<Weak<DevFS>>,
     fs: RwLock<Weak<DevFS>>,
     metadata: Metadata,
     metadata: Metadata,
 }
 }
@@ -212,6 +212,7 @@ impl VirtIOBlkDevice {
                 kobject_common: KObjectCommonData::default(),
                 kobject_common: KObjectCommonData::default(),
                 irq,
                 irq,
             }),
             }),
+            parent: RwLock::new(Weak::default()),
             fs: RwLock::new(Weak::default()),
             fs: RwLock::new(Weak::default()),
             metadata: Metadata::new(
             metadata: Metadata::new(
                 crate::filesystem::vfs::FileType::BlockDevice,
                 crate::filesystem::vfs::FileType::BlockDevice,
@@ -229,7 +230,10 @@ impl VirtIOBlkDevice {
 
 
 impl IndexNode for VirtIOBlkDevice {
 impl IndexNode for VirtIOBlkDevice {
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
-        todo!()
+        self.fs
+            .read()
+            .upgrade()
+            .expect("VirtIOBlkDevice fs is not set")
     }
     }
     fn as_any_ref(&self) -> &dyn core::any::Any {
     fn as_any_ref(&self) -> &dyn core::any::Any {
         self
         self
@@ -258,12 +262,44 @@ impl IndexNode for VirtIOBlkDevice {
     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
         Ok(self.metadata.clone())
         Ok(self.metadata.clone())
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.parent.read();
+        if let Some(parent) = parent.upgrade() {
+            return Ok(parent as Arc<dyn IndexNode>);
+        }
+        Err(SystemError::ENOENT)
+    }
+
+    fn close(
+        &self,
+        _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
+    ) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn dname(&self) -> Result<DName, SystemError> {
+        let dname = DName::from(self.blkdev_meta.devname.clone().as_ref());
+        Ok(dname)
+    }
+
+    fn open(
+        &self,
+        _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
+        _mode: &crate::filesystem::vfs::file::FileMode,
+    ) -> Result<(), SystemError> {
+        Ok(())
+    }
 }
 }
 
 
 impl DeviceINode for VirtIOBlkDevice {
 impl DeviceINode for VirtIOBlkDevice {
     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
         *self.fs.write() = fs;
         *self.fs.write() = fs;
     }
     }
+
+    fn set_parent(&self, parent: Weak<crate::filesystem::devfs::LockedDevFSInode>) {
+        *self.parent.write() = parent;
+    }
 }
 }
 
 
 impl BlockDevice for VirtIOBlkDevice {
 impl BlockDevice for VirtIOBlkDevice {

+ 2 - 2
kernel/src/driver/char/virtio_console.rs

@@ -42,7 +42,7 @@ use alloc::string::String;
 use alloc::string::ToString;
 use alloc::string::ToString;
 use alloc::sync::{Arc, Weak};
 use alloc::sync::{Arc, Weak};
 use alloc::vec::Vec;
 use alloc::vec::Vec;
-use bitmap::traits::BitMapOps;
+use bitmap::{static_bitmap, traits::BitMapOps};
 use core::fmt::Debug;
 use core::fmt::Debug;
 use core::fmt::Formatter;
 use core::fmt::Formatter;
 use core::{
 use core::{
@@ -422,7 +422,7 @@ impl VirtIOConsoleDriver {
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct InnerVirtIOConsoleDriver {
 struct InnerVirtIOConsoleDriver {
-    id_bmp: bitmap::StaticBitmap<{ VirtIOConsoleDriver::MAX_DEVICES }>,
+    id_bmp: static_bitmap!(VirtIOConsoleDriver::MAX_DEVICES),
     devname: [Option<DevName>; VirtIOConsoleDriver::MAX_DEVICES],
     devname: [Option<DevName>; VirtIOConsoleDriver::MAX_DEVICES],
     virtio_driver_common: VirtIODriverCommonData,
     virtio_driver_common: VirtIODriverCommonData,
     driver_common: DriverCommonData,
     driver_common: DriverCommonData,

+ 0 - 1
kernel/src/driver/clocksource/acpi_pm.rs

@@ -227,7 +227,6 @@ fn find_acpi_pm_clock() -> Result<(), SystemError> {
 }
 }
 
 
 /// # 初始化ACPI PM Timer作为系统时钟源
 /// # 初始化ACPI PM Timer作为系统时钟源
-// #[unified_init(INITCALL_FS)]
 #[inline(never)]
 #[inline(never)]
 #[allow(dead_code)]
 #[allow(dead_code)]
 pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
 pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {

+ 2 - 2
kernel/src/driver/clocksource/timer_riscv.rs

@@ -1,7 +1,7 @@
 use core::sync::atomic::{compiler_fence, fence, Ordering};
 use core::sync::atomic::{compiler_fence, fence, Ordering};
 
 
 use alloc::{string::ToString, sync::Arc};
 use alloc::{string::ToString, sync::Arc};
-use bitmap::{traits::BitMapOps, StaticBitmap};
+use bitmap::{static_bitmap, traits::BitMapOps, StaticBitmap};
 use system_error::SystemError;
 use system_error::SystemError;
 
 
 use crate::{
 use crate::{
@@ -29,7 +29,7 @@ use crate::{
 
 
 pub struct RiscVSbiTimer;
 pub struct RiscVSbiTimer;
 
 
-static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize }>> =
+static SBI_TIMER_INIT_BMP: SpinLock<static_bitmap!(PerCpu::MAX_CPU_NUM as usize)> =
     SpinLock::new(StaticBitmap::new());
     SpinLock::new(StaticBitmap::new());
 
 
 static mut INTERVAL_CNT: usize = 0;
 static mut INTERVAL_CNT: usize = 0;

+ 15 - 1
kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs

@@ -28,7 +28,7 @@ use crate::{
     },
     },
     exception::InterruptArch,
     exception::InterruptArch,
     filesystem::{
     filesystem::{
-        devfs::{devfs_register, DevFS, DeviceINode},
+        devfs::{devfs_register, DevFS, DeviceINode, LockedDevFSInode},
         kernfs::KernFSInode,
         kernfs::KernFSInode,
         vfs::{
         vfs::{
             syscall::ModeType, utils::DName, vcore::generate_inode_id, FilePrivateData, FileSystem,
             syscall::ModeType, utils::DName, vcore::generate_inode_id, FilePrivateData, FileSystem,
@@ -207,6 +207,7 @@ impl Ps2MouseDevice {
                     raw_dev: DeviceNumber::default(), // 这里用来作为device number
                     raw_dev: DeviceNumber::default(), // 这里用来作为device number
                 },
                 },
                 device_inode_fs: None,
                 device_inode_fs: None,
+                parent: Weak::new(),
             }),
             }),
             kobj_state: LockedKObjectState::new(None),
             kobj_state: LockedKObjectState::new(None),
         };
         };
@@ -424,6 +425,7 @@ struct InnerPs2MouseDevice {
 
 
     /// device inode要求的字段
     /// device inode要求的字段
     device_inode_fs: Option<Weak<DevFS>>,
     device_inode_fs: Option<Weak<DevFS>>,
+    parent: Weak<LockedDevFSInode>,
     devfs_metadata: Metadata,
     devfs_metadata: Metadata,
 }
 }
 
 
@@ -587,6 +589,10 @@ impl DeviceINode for Ps2MouseDevice {
     fn set_fs(&self, fs: Weak<DevFS>) {
     fn set_fs(&self, fs: Weak<DevFS>) {
         self.inner.lock_irqsave().device_inode_fs = Some(fs);
         self.inner.lock_irqsave().device_inode_fs = Some(fs);
     }
     }
+
+    fn set_parent(&self, parent: Weak<crate::filesystem::devfs::LockedDevFSInode>) {
+        self.inner.lock_irqsave().parent = parent;
+    }
 }
 }
 
 
 impl IndexNode for Ps2MouseDevice {
 impl IndexNode for Ps2MouseDevice {
@@ -664,6 +670,14 @@ impl IndexNode for Ps2MouseDevice {
     fn dname(&self) -> Result<DName, SystemError> {
     fn dname(&self) -> Result<DName, SystemError> {
         Ok(DName::from(self.name()))
         Ok(DName::from(self.name()))
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let guard = self.inner.lock_irqsave();
+        if let Some(parent) = guard.parent.upgrade() {
+            return Ok(parent);
+        }
+        Err(SystemError::ENOENT)
+    }
 }
 }
 
 
 impl Ps2Device for Ps2MouseDevice {}
 impl Ps2Device for Ps2MouseDevice {}

+ 16 - 1
kernel/src/driver/keyboard/ps2_keyboard.rs

@@ -20,7 +20,7 @@ use crate::{
         InterruptArch, IrqNumber,
         InterruptArch, IrqNumber,
     },
     },
     filesystem::{
     filesystem::{
-        devfs::{devfs_register, DevFS, DeviceINode},
+        devfs::{devfs_register, DevFS, DeviceINode, LockedDevFSInode},
         vfs::{
         vfs::{
             file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData,
             file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData,
             FileSystem, FileType, IndexNode, Metadata,
             FileSystem, FileType, IndexNode, Metadata,
@@ -66,6 +66,7 @@ pub struct PS2KeyBoardInode {
     /// 指向自身的弱引用
     /// 指向自身的弱引用
     self_ref: Weak<LockedPS2KeyBoardInode>,
     self_ref: Weak<LockedPS2KeyBoardInode>,
     /// 指向inode所在的文件系统对象的指针
     /// 指向inode所在的文件系统对象的指针
+    parent: Weak<LockedDevFSInode>,
     fs: Weak<DevFS>,
     fs: Weak<DevFS>,
     /// INode 元数据
     /// INode 元数据
     metadata: Metadata,
     metadata: Metadata,
@@ -76,6 +77,7 @@ impl LockedPS2KeyBoardInode {
         let inode = PS2KeyBoardInode {
         let inode = PS2KeyBoardInode {
             // uuid: Uuid::new_v5(),
             // uuid: Uuid::new_v5(),
             self_ref: Weak::default(),
             self_ref: Weak::default(),
+            parent: Weak::default(),
             fs: Weak::default(),
             fs: Weak::default(),
             metadata: Metadata {
             metadata: Metadata {
                 dev_id: 1,
                 dev_id: 1,
@@ -107,6 +109,11 @@ impl DeviceINode for LockedPS2KeyBoardInode {
     fn set_fs(&self, fs: Weak<DevFS>) {
     fn set_fs(&self, fs: Weak<DevFS>) {
         self.0.write().fs = fs;
         self.0.write().fs = fs;
     }
     }
+
+    fn set_parent(&self, parent: Weak<LockedDevFSInode>) {
+        let mut inode = self.0.write();
+        inode.parent = parent;
+    }
 }
 }
 
 
 fn ps2_keyboard_register() {
 fn ps2_keyboard_register() {
@@ -175,6 +182,14 @@ impl IndexNode for LockedPS2KeyBoardInode {
     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
         return Err(SystemError::ENOSYS);
         return Err(SystemError::ENOSYS);
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.0.read().parent.upgrade();
+        if let Some(parent) = parent {
+            return Ok(parent as Arc<dyn IndexNode>);
+        }
+        Err(SystemError::ENOENT)
+    }
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]

+ 2 - 2
kernel/src/driver/scsi/mod.rs

@@ -1,4 +1,4 @@
-use bitmap::traits::BitMapOps;
+use bitmap::{static_bitmap, traits::BitMapOps};
 use system_error::SystemError;
 use system_error::SystemError;
 use unified_init::macros::unified_init;
 use unified_init::macros::unified_init;
 
 
@@ -29,7 +29,7 @@ pub struct ScsiManager {
 }
 }
 
 
 struct InnerScsiManager {
 struct InnerScsiManager {
-    id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
+    id_bmp: static_bitmap!(ScsiManager::MAX_DEVICES),
     devname: [Option<DevName>; ScsiManager::MAX_DEVICES],
     devname: [Option<DevName>; ScsiManager::MAX_DEVICES],
 }
 }
 
 

+ 52 - 7
kernel/src/driver/tty/tty_device.rs

@@ -26,12 +26,13 @@ use crate::{
         serial::serial_init,
         serial::serial_init,
     },
     },
     filesystem::{
     filesystem::{
-        devfs::{devfs_register, DevFS, DeviceINode},
+        devfs::{devfs_register, DevFS, DeviceINode, LockedDevFSInode},
+        devpts::{DevPtsFs, LockedDevPtsFSInode},
         epoll::EPollItem,
         epoll::EPollItem,
         kernfs::KernFSInode,
         kernfs::KernFSInode,
         vfs::{
         vfs::{
-            file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata,
-            PollableInode,
+            file::FileMode, syscall::ModeType, utils::DName, FilePrivateData, FileType, IndexNode,
+            Metadata, PollableInode,
         },
         },
     },
     },
     init::initcall::INITCALL_DEVICE,
     init::initcall::INITCALL_DEVICE,
@@ -107,7 +108,19 @@ pub struct TtyDevice {
     inner: RwLock<InnerTtyDevice>,
     inner: RwLock<InnerTtyDevice>,
     kobj_state: LockedKObjectState,
     kobj_state: LockedKObjectState,
     /// TTY所属的文件系统
     /// TTY所属的文件系统
-    fs: RwLock<Weak<DevFS>>,
+    fs: RwLock<TtyDeviceFs>,
+    parent: RwLock<TtyDeviceParent>,
+}
+
+pub enum TtyDeviceFs {
+    DevFs(Weak<DevFS>),
+    DevPtsFs(Weak<DevPtsFs>),
+    None,
+}
+pub enum TtyDeviceParent {
+    DevFS(Weak<LockedDevFSInode>),
+    DevPts(Weak<LockedDevPtsFSInode>),
+    None,
 }
 }
 
 
 impl TtyDevice {
 impl TtyDevice {
@@ -118,7 +131,8 @@ impl TtyDevice {
             id_table,
             id_table,
             inner: RwLock::new(InnerTtyDevice::new()),
             inner: RwLock::new(InnerTtyDevice::new()),
             kobj_state: LockedKObjectState::new(None),
             kobj_state: LockedKObjectState::new(None),
-            fs: RwLock::new(Weak::default()),
+            fs: RwLock::new(TtyDeviceFs::None),
+            parent: RwLock::new(TtyDeviceParent::None),
             tty_type,
             tty_type,
         };
         };
 
 
@@ -361,7 +375,17 @@ impl IndexNode for TtyDevice {
     }
     }
 
 
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
-        todo!()
+        match &*self.fs.read() {
+            TtyDeviceFs::DevFs(fs) => fs.upgrade().unwrap(),
+            TtyDeviceFs::DevPtsFs(fs) => fs.upgrade().unwrap(),
+            TtyDeviceFs::None => {
+                panic!("TtyDevice has no filesystem set");
+            }
+        }
+    }
+
+    fn dname(&self) -> Result<DName, SystemError> {
+        Ok(self.name.clone().into())
     }
     }
 
 
     fn as_any_ref(&self) -> &dyn core::any::Any {
     fn as_any_ref(&self) -> &dyn core::any::Any {
@@ -483,11 +507,32 @@ impl IndexNode for TtyDevice {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
         Ok(self)
         Ok(self)
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.parent.read();
+        match &*parent {
+            TtyDeviceParent::DevFS(devfs) => Ok(devfs.upgrade().unwrap()),
+            TtyDeviceParent::DevPts(devpts) => Ok(devpts.upgrade().unwrap()),
+            TtyDeviceParent::None => panic!("TtyDevice has no filesystem set"),
+        }
+    }
 }
 }
 
 
 impl DeviceINode for TtyDevice {
 impl DeviceINode for TtyDevice {
     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
     fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
-        *self.fs.write() = fs;
+        *self.fs.write() = TtyDeviceFs::DevFs(fs);
+    }
+
+    fn set_parent(&self, parent: Weak<crate::filesystem::devfs::LockedDevFSInode>) {
+        *self.parent.write() = TtyDeviceParent::DevFS(parent);
+    }
+
+    fn set_devpts_fs(&self, devpts: Weak<crate::filesystem::devpts::DevPtsFs>) {
+        *self.fs.write() = TtyDeviceFs::DevPtsFs(devpts);
+    }
+
+    fn set_devpts_parent(&self, parent: Weak<LockedDevPtsFSInode>) {
+        *self.parent.write() = TtyDeviceParent::DevPts(parent);
     }
     }
 }
 }
 
 

+ 3 - 3
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -2,7 +2,7 @@ use alloc::boxed::Box;
 use core::intrinsics::likely;
 use core::intrinsics::likely;
 use core::ops::BitXor;
 use core::ops::BitXor;
 
 
-use bitmap::{traits::BitMapOps, StaticBitmap};
+use bitmap::{static_bitmap, traits::BitMapOps, StaticBitmap};
 
 
 use alloc::sync::{Arc, Weak};
 use alloc::sync::{Arc, Weak};
 use system_error::SystemError;
 use system_error::SystemError;
@@ -119,8 +119,8 @@ pub struct NTtyData {
     read_buf: Box<[u8; NTTY_BUFSIZE]>,
     read_buf: Box<[u8; NTTY_BUFSIZE]>,
     echo_buf: Box<[u8; NTTY_BUFSIZE]>,
     echo_buf: Box<[u8; NTTY_BUFSIZE]>,
 
 
-    read_flags: StaticBitmap<NTTY_BUFSIZE>,
-    char_map: StaticBitmap<256>,
+    read_flags: static_bitmap!(NTTY_BUFSIZE),
+    char_map: static_bitmap!(256),
 
 
     tty: Weak<TtyCore>,
     tty: Weak<TtyCore>,
 }
 }

+ 2 - 2
kernel/src/driver/tty/virtual_terminal/virtual_console.rs

@@ -4,7 +4,7 @@ use alloc::{
     sync::{Arc, Weak},
     sync::{Arc, Weak},
     vec::Vec,
     vec::Vec,
 };
 };
-use bitmap::{traits::BitMapOps, StaticBitmap};
+use bitmap::{static_bitmap, traits::BitMapOps, StaticBitmap};
 use log::warn;
 use log::warn;
 
 
 use crate::{
 use crate::{
@@ -132,7 +132,7 @@ pub struct VirtualConsoleData {
     /// 字符转换表 用于将输入字符映射到特定的字符
     /// 字符转换表 用于将输入字符映射到特定的字符
     pub translate: TranslationMap,
     pub translate: TranslationMap,
 
 
-    pub tab_stop: StaticBitmap<256>,
+    pub tab_stop: static_bitmap!(256),
 
 
     pub attr: u8,
     pub attr: u8,
 
 

+ 15 - 1
kernel/src/driver/video/fbdev/base/fbmem.rs

@@ -25,7 +25,7 @@ use crate::{
         subsys::SubSysPrivate,
         subsys::SubSysPrivate,
     },
     },
     filesystem::{
     filesystem::{
-        devfs::{devfs_register, DevFS, DeviceINode},
+        devfs::{devfs_register, DevFS, DeviceINode, LockedDevFSInode},
         kernfs::KernFSInode,
         kernfs::KernFSInode,
         sysfs::AttributeGroup,
         sysfs::AttributeGroup,
         vfs::{
         vfs::{
@@ -227,6 +227,7 @@ impl FbDevice {
                 device_common: DeviceCommonData::default(),
                 device_common: DeviceCommonData::default(),
                 fb_id: id,
                 fb_id: id,
                 device_inode_fs: None,
                 device_inode_fs: None,
+                parent: Weak::default(),
                 devfs_metadata: Metadata::new(
                 devfs_metadata: Metadata::new(
                     FileType::FramebufferDevice,
                     FileType::FramebufferDevice,
                     ModeType::from_bits_truncate(0o666),
                     ModeType::from_bits_truncate(0o666),
@@ -272,6 +273,7 @@ struct InnerFbDevice {
 
 
     /// device inode要求的字段
     /// device inode要求的字段
     device_inode_fs: Option<Weak<DevFS>>,
     device_inode_fs: Option<Weak<DevFS>>,
+    parent: Weak<LockedDevFSInode>,
     devfs_metadata: Metadata,
     devfs_metadata: Metadata,
 }
 }
 
 
@@ -394,6 +396,10 @@ impl DeviceINode for FbDevice {
     fn set_fs(&self, fs: Weak<DevFS>) {
     fn set_fs(&self, fs: Weak<DevFS>) {
         self.inner.lock().device_inode_fs = Some(fs);
         self.inner.lock().device_inode_fs = Some(fs);
     }
     }
+
+    fn set_parent(&self, parent: Weak<crate::filesystem::devfs::LockedDevFSInode>) {
+        self.inner.lock().parent = parent;
+    }
 }
 }
 
 
 impl IndexNode for FbDevice {
 impl IndexNode for FbDevice {
@@ -455,4 +461,12 @@ impl IndexNode for FbDevice {
     fn resize(&self, _len: usize) -> Result<(), SystemError> {
     fn resize(&self, _len: usize) -> Result<(), SystemError> {
         return Ok(());
         return Ok(());
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.inner.lock().parent.upgrade();
+        if let Some(parent) = parent {
+            return Ok(parent as Arc<dyn IndexNode>);
+        }
+        Err(SystemError::ENOENT)
+    }
 }
 }

+ 35 - 23
kernel/src/filesystem/devfs/mod.rs

@@ -2,13 +2,18 @@
 pub mod null_dev;
 pub mod null_dev;
 pub mod zero_dev;
 pub mod zero_dev;
 
 
-use super::vfs::{
-    file::FileMode, syscall::ModeType, utils::DName, vcore::generate_inode_id, FilePrivateData,
-    FileSystem, FileType, FsInfo, IndexNode, Magic, Metadata, SuperBlock,
+use super::{
+    devpts::{DevPtsFs, LockedDevPtsFSInode},
+    vfs::{
+        file::FileMode, syscall::ModeType, utils::DName, vcore::generate_inode_id, FilePrivateData,
+        FileSystem, FileType, FsInfo, IndexNode, Magic, Metadata, SuperBlock,
+    },
 };
 };
 use crate::{
 use crate::{
     driver::base::{block::gendisk::GenDisk, device::device_number::DeviceNumber},
     driver::base::{block::gendisk::GenDisk, device::device_number::DeviceNumber},
+    filesystem::vfs::mount::MountFlags,
     libs::{
     libs::{
+        casting::DowncastArc,
         once::Once,
         once::Once,
         spinlock::{SpinLock, SpinLockGuard},
         spinlock::{SpinLock, SpinLockGuard},
     },
     },
@@ -73,6 +78,8 @@ impl DevFS {
             DevFSInode::new(FileType::Dir, ModeType::from_bits_truncate(0o755), 0),
             DevFSInode::new(FileType::Dir, ModeType::from_bits_truncate(0o755), 0),
         )));
         )));
 
 
+        // panic!("devfs root inode id: {:?}", root.0.lock().metadata.inode_id);
+
         let devfs: Arc<DevFS> = Arc::new(DevFS {
         let devfs: Arc<DevFS> = Arc::new(DevFS {
             root_inode: root,
             root_inode: root,
             super_block,
             super_block,
@@ -121,7 +128,7 @@ impl DevFS {
         name: &str,
         name: &str,
         device: Arc<T>,
         device: Arc<T>,
     ) -> Result<(), SystemError> {
     ) -> Result<(), SystemError> {
-        let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
+        let dev_root_inode = self.root_inode.clone();
         let metadata = device.metadata()?;
         let metadata = device.metadata()?;
         match metadata.file_type {
         match metadata.file_type {
             // 字节设备挂载在 /dev/char
             // 字节设备挂载在 /dev/char
@@ -135,11 +142,10 @@ impl DevFS {
                 }
                 }
 
 
                 let any_char_inode = dev_root_inode.find("char")?;
                 let any_char_inode = dev_root_inode.find("char")?;
-                let dev_char_inode: &LockedDevFSInode = any_char_inode
-                    .as_any_ref()
-                    .downcast_ref::<LockedDevFSInode>()
-                    .unwrap();
+                let dev_char_inode = any_char_inode.downcast_arc::<LockedDevFSInode>().unwrap();
 
 
+                device.set_fs(dev_root_inode.0.lock().fs.clone());
+                device.set_parent(Arc::downgrade(&dev_root_inode));
                 // 特殊处理 tty 设备,挂载在 /dev 下
                 // 特殊处理 tty 设备,挂载在 /dev 下
                 if name.starts_with("tty") && name.len() >= 3 {
                 if name.starts_with("tty") && name.len() >= 3 {
                     dev_root_inode.add_dev(name, device.clone())?;
                     dev_root_inode.add_dev(name, device.clone())?;
@@ -154,8 +160,8 @@ impl DevFS {
                 } else {
                 } else {
                     // 在 /dev/char 下创建设备节点
                     // 在 /dev/char 下创建设备节点
                     dev_char_inode.add_dev(name, device.clone())?;
                     dev_char_inode.add_dev(name, device.clone())?;
+                    device.set_parent(Arc::downgrade(&dev_char_inode));
                 }
                 }
-                device.set_fs(dev_char_inode.0.lock().fs.clone());
             }
             }
             FileType::BlockDevice => {
             FileType::BlockDevice => {
                 if dev_root_inode.find("block").is_err() {
                 if dev_root_inode.find("block").is_err() {
@@ -167,10 +173,11 @@ impl DevFS {
                 }
                 }
 
 
                 let any_block_inode = dev_root_inode.find("block")?;
                 let any_block_inode = dev_root_inode.find("block")?;
-                let dev_block_inode: &LockedDevFSInode = any_block_inode
-                    .as_any_ref()
-                    .downcast_ref::<LockedDevFSInode>()
-                    .unwrap();
+                let dev_block_inode = any_block_inode.downcast_arc::<LockedDevFSInode>().unwrap();
+
+                // default parent is dev_root_inode
+                device.set_parent(Arc::downgrade(&dev_root_inode));
+                device.set_fs(dev_root_inode.0.lock().fs.clone());
 
 
                 if name.starts_with("vd") && name.len() > 2 {
                 if name.starts_with("vd") && name.len() > 2 {
                     // 虚拟磁盘设备挂载在 /dev 下
                     // 虚拟磁盘设备挂载在 /dev 下
@@ -188,24 +195,22 @@ impl DevFS {
                     dev_root_inode.add_dev(name, device.clone())?;
                     dev_root_inode.add_dev(name, device.clone())?;
                 } else {
                 } else {
                     dev_block_inode.add_dev(name, device.clone())?;
                     dev_block_inode.add_dev(name, device.clone())?;
+                    device.set_parent(Arc::downgrade(&dev_block_inode));
                 }
                 }
-                device.set_fs(dev_block_inode.0.lock().fs.clone());
-            }
-            FileType::KvmDevice => {
-                dev_root_inode
-                    .add_dev(name, device.clone())
-                    .expect("DevFS: Failed to register /dev/kvm");
             }
             }
-            FileType::FramebufferDevice => {
+            FileType::KvmDevice | FileType::FramebufferDevice => {
                 dev_root_inode
                 dev_root_inode
                     .add_dev(name, device.clone())
                     .add_dev(name, device.clone())
-                    .expect("DevFS: Failed to register /dev/fb");
+                    .unwrap_or_else(|_| panic!("DevFS: Failed to register /dev/{}", name));
+
+                // default parent is dev_root_inode
+                device.set_parent(Arc::downgrade(&dev_root_inode));
+                device.set_fs(dev_root_inode.0.lock().fs.clone());
             }
             }
             _ => {
             _ => {
                 return Err(SystemError::ENOSYS);
                 return Err(SystemError::ENOSYS);
             }
             }
         }
         }
-
         return Ok(());
         return Ok(());
     }
     }
 
 
@@ -677,6 +682,13 @@ impl IndexNode for LockedDevFSInode {
 /// @brief 所有的设备INode都需要额外实现这个trait
 /// @brief 所有的设备INode都需要额外实现这个trait
 pub trait DeviceINode: IndexNode {
 pub trait DeviceINode: IndexNode {
     fn set_fs(&self, fs: Weak<DevFS>);
     fn set_fs(&self, fs: Weak<DevFS>);
+    fn set_parent(&self, parent: Weak<LockedDevFSInode>);
+    fn set_devpts_fs(&self, _devpts: Weak<DevPtsFs>) {
+        panic!("DeviceINode: set_devpts_fs is not implemented!");
+    }
+    fn set_devpts_parent(&self, _parent: Weak<LockedDevPtsFSInode>) {
+        panic!("DeviceINode: set_devpts_parent is not implemented!");
+    }
     // TODO: 增加 unregister 方法
     // TODO: 增加 unregister 方法
 }
 }
 
 
@@ -727,7 +739,7 @@ pub fn devfs_init() -> Result<(), SystemError> {
         root_inode
         root_inode
             .mkdir("dev", ModeType::from_bits_truncate(0o755))
             .mkdir("dev", ModeType::from_bits_truncate(0o755))
             .expect("Unabled to find /dev")
             .expect("Unabled to find /dev")
-            .mount(devfs)
+            .mount(devfs, MountFlags::empty())
             .expect("Failed to mount at /dev");
             .expect("Failed to mount at /dev");
         info!("DevFS mounted.");
         info!("DevFS mounted.");
         result = Some(Ok(()));
         result = Some(Ok(()));

+ 15 - 0
kernel/src/filesystem/devfs/null_dev.rs

@@ -1,4 +1,5 @@
 use crate::driver::base::device::device_number::DeviceNumber;
 use crate::driver::base::device::device_number::DeviceNumber;
+use crate::filesystem::devfs::LockedDevFSInode;
 use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::syscall::ModeType;
 use crate::filesystem::vfs::syscall::ModeType;
 use crate::filesystem::vfs::{
 use crate::filesystem::vfs::{
@@ -25,6 +26,7 @@ pub struct NullInode {
     fs: Weak<DevFS>,
     fs: Weak<DevFS>,
     /// INode 元数据
     /// INode 元数据
     metadata: Metadata,
     metadata: Metadata,
+    parent: Weak<LockedDevFSInode>,
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]
@@ -36,6 +38,7 @@ impl LockedNullInode {
             // uuid: Uuid::new_v5(),
             // uuid: Uuid::new_v5(),
             self_ref: Weak::default(),
             self_ref: Weak::default(),
             fs: Weak::default(),
             fs: Weak::default(),
+            parent: Weak::default(),
             metadata: Metadata {
             metadata: Metadata {
                 dev_id: 1,
                 dev_id: 1,
                 inode_id: generate_inode_id(),
                 inode_id: generate_inode_id(),
@@ -66,6 +69,10 @@ impl DeviceINode for LockedNullInode {
     fn set_fs(&self, fs: Weak<DevFS>) {
     fn set_fs(&self, fs: Weak<DevFS>) {
         self.0.lock().fs = fs;
         self.0.lock().fs = fs;
     }
     }
+
+    fn set_parent(&self, parent: Weak<super::LockedDevFSInode>) {
+        self.0.lock().parent = parent;
+    }
 }
 }
 
 
 impl IndexNode for LockedNullInode {
 impl IndexNode for LockedNullInode {
@@ -135,4 +142,12 @@ impl IndexNode for LockedNullInode {
 
 
         Ok(len)
         Ok(len)
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.0.lock().parent.upgrade();
+        if let Some(parent) = parent {
+            return Ok(parent);
+        }
+        Err(SystemError::ENOENT)
+    }
 }
 }

+ 15 - 0
kernel/src/filesystem/devfs/zero_dev.rs

@@ -1,4 +1,5 @@
 use crate::driver::base::device::device_number::DeviceNumber;
 use crate::driver::base::device::device_number::DeviceNumber;
+use crate::filesystem::devfs::LockedDevFSInode;
 use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::syscall::ModeType;
 use crate::filesystem::vfs::syscall::ModeType;
 use crate::filesystem::vfs::{
 use crate::filesystem::vfs::{
@@ -23,6 +24,7 @@ pub struct ZeroInode {
     self_ref: Weak<LockedZeroInode>,
     self_ref: Weak<LockedZeroInode>,
     /// 指向inode所在的文件系统对象的指针
     /// 指向inode所在的文件系统对象的指针
     fs: Weak<DevFS>,
     fs: Weak<DevFS>,
+    parent: Weak<LockedDevFSInode>,
     /// INode 元数据
     /// INode 元数据
     metadata: Metadata,
     metadata: Metadata,
 }
 }
@@ -35,6 +37,7 @@ impl LockedZeroInode {
         let inode = ZeroInode {
         let inode = ZeroInode {
             // uuid: Uuid::new_v5(),
             // uuid: Uuid::new_v5(),
             self_ref: Weak::default(),
             self_ref: Weak::default(),
+            parent: Weak::default(),
             fs: Weak::default(),
             fs: Weak::default(),
             metadata: Metadata {
             metadata: Metadata {
                 dev_id: 1,
                 dev_id: 1,
@@ -66,6 +69,10 @@ impl DeviceINode for LockedZeroInode {
     fn set_fs(&self, fs: Weak<DevFS>) {
     fn set_fs(&self, fs: Weak<DevFS>) {
         self.0.lock().fs = fs;
         self.0.lock().fs = fs;
     }
     }
+
+    fn set_parent(&self, parent: Weak<LockedDevFSInode>) {
+        self.0.lock().parent = parent;
+    }
 }
 }
 
 
 impl IndexNode for LockedZeroInode {
 impl IndexNode for LockedZeroInode {
@@ -143,4 +150,12 @@ impl IndexNode for LockedZeroInode {
 
 
         Ok(len)
         Ok(len)
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.0.lock().parent.upgrade();
+        if let Some(parent) = parent {
+            return Ok(parent as Arc<dyn IndexNode>);
+        }
+        Err(SystemError::ENOENT)
+    }
 }
 }

+ 27 - 18
kernel/src/filesystem/devpts/mod.rs

@@ -1,16 +1,5 @@
 use core::sync::atomic::{AtomicU32, Ordering};
 use core::sync::atomic::{AtomicU32, Ordering};
 
 
-use alloc::{
-    collections::BTreeMap,
-    string::{String, ToString},
-    sync::{Arc, Weak},
-    vec::Vec,
-};
-use ida::IdAllocator;
-use log::info;
-use system_error::SystemError;
-use unified_init::macros::unified_init;
-
 use crate::{
 use crate::{
     driver::{
     driver::{
         base::device::{
         base::device::{
@@ -22,14 +11,27 @@ use crate::{
             tty_device::{PtyType, TtyDevice, TtyType},
             tty_device::{PtyType, TtyDevice, TtyType},
         },
         },
     },
     },
-    filesystem::vfs::{mount::do_mount_mkdir, syscall::ModeType, FileType},
-    init::initcall::INITCALL_FS,
+    filesystem::vfs::{
+        mount::{do_mount_mkdir, MountFlags},
+        syscall::ModeType,
+        FileType,
+    },
     libs::spinlock::{SpinLock, SpinLockGuard},
     libs::spinlock::{SpinLock, SpinLockGuard},
     time::PosixTimeSpec,
     time::PosixTimeSpec,
 };
 };
+use alloc::{
+    collections::BTreeMap,
+    string::{String, ToString},
+    sync::{Arc, Weak},
+    vec::Vec,
+};
+use ida::IdAllocator;
+use log::info;
+use system_error::SystemError;
 
 
-use super::vfs::{
-    vcore::generate_inode_id, FilePrivateData, FileSystem, FsInfo, IndexNode, Metadata,
+use super::{
+    devfs::DeviceINode,
+    vfs::{vcore::generate_inode_id, FilePrivateData, FileSystem, FsInfo, IndexNode, Metadata},
 };
 };
 
 
 const DEV_PTYFS_MAX_NAMELEN: usize = 16;
 const DEV_PTYFS_MAX_NAMELEN: usize = 16;
@@ -48,6 +50,8 @@ pub struct DevPtsFs {
 impl DevPtsFs {
 impl DevPtsFs {
     pub fn new() -> Arc<Self> {
     pub fn new() -> Arc<Self> {
         let root_inode = Arc::new(LockedDevPtsFSInode::new());
         let root_inode = Arc::new(LockedDevPtsFSInode::new());
+        root_inode.inner.lock().parent = Arc::downgrade(&root_inode);
+        root_inode.inner.lock().self_ref = Arc::downgrade(&root_inode);
         let ret = Arc::new(Self {
         let ret = Arc::new(Self {
             root_inode,
             root_inode,
             pts_ida: SpinLock::new(IdAllocator::new(0, NR_UNIX98_PTY_MAX as usize).unwrap()),
             pts_ida: SpinLock::new(IdAllocator::new(0, NR_UNIX98_PTY_MAX as usize).unwrap()),
@@ -100,6 +104,8 @@ impl LockedDevPtsFSInode {
             inner: SpinLock::new(PtsDevInode {
             inner: SpinLock::new(PtsDevInode {
                 fs: Weak::new(),
                 fs: Weak::new(),
                 children: Some(BTreeMap::new()),
                 children: Some(BTreeMap::new()),
+                parent: Weak::new(),
+                self_ref: Weak::new(),
                 metadata: Metadata {
                 metadata: Metadata {
                     dev_id: 0,
                     dev_id: 0,
                     inode_id: generate_inode_id(),
                     inode_id: generate_inode_id(),
@@ -131,6 +137,8 @@ pub struct PtsDevInode {
     fs: Weak<DevPtsFs>,
     fs: Weak<DevPtsFs>,
     children: Option<BTreeMap<String, Arc<TtyDevice>>>,
     children: Option<BTreeMap<String, Arc<TtyDevice>>>,
     metadata: Metadata,
     metadata: Metadata,
+    parent: Weak<LockedDevPtsFSInode>,
+    self_ref: Weak<LockedDevPtsFSInode>,
 }
 }
 
 
 impl PtsDevInode {
 impl PtsDevInode {
@@ -247,6 +255,9 @@ impl IndexNode for LockedDevPtsFSInode {
 
 
         result.set_metadata(&metadata)?;
         result.set_metadata(&metadata)?;
 
 
+        result.set_devpts_fs(Arc::downgrade(&fs));
+        result.set_devpts_parent(guard.self_ref.clone());
+
         guard
         guard
             .children_unchecked_mut()
             .children_unchecked_mut()
             .insert(name.to_string(), result.clone());
             .insert(name.to_string(), result.clone());
@@ -273,13 +284,11 @@ impl IndexNode for LockedDevPtsFSInode {
     }
     }
 }
 }
 
 
-#[unified_init(INITCALL_FS)]
-#[inline(never)]
 pub fn devpts_init() -> Result<(), SystemError> {
 pub fn devpts_init() -> Result<(), SystemError> {
     // 创建 devptsfs 实例
     // 创建 devptsfs 实例
     let ptsfs: Arc<DevPtsFs> = DevPtsFs::new();
     let ptsfs: Arc<DevPtsFs> = DevPtsFs::new();
 
 
-    do_mount_mkdir(ptsfs, "/dev/pts").expect("Failed to mount DevPtsFS");
+    do_mount_mkdir(ptsfs, "/dev/pts", MountFlags::empty()).expect("Failed to mount DevPtsFS");
     info!("DevPtsFs mounted.");
     info!("DevPtsFs mounted.");
 
 
     Ok(())
     Ok(())

+ 6 - 0
kernel/src/filesystem/epoll/fs.rs

@@ -1,3 +1,5 @@
+use alloc::string::String;
+
 use crate::{
 use crate::{
     filesystem::vfs::{file::FileMode, FilePrivateData, IndexNode, Metadata},
     filesystem::vfs::{file::FileMode, FilePrivateData, IndexNode, Metadata},
     libs::spinlock::SpinLockGuard,
     libs::spinlock::SpinLockGuard,
@@ -74,4 +76,8 @@ impl IndexNode for EPollInode {
     ) -> Result<(), SystemError> {
     ) -> Result<(), SystemError> {
         Ok(())
         Ok(())
     }
     }
+
+    fn absolute_path(&self) -> Result<String, SystemError> {
+        Ok(String::from("epoll"))
+    }
 }
 }

+ 4 - 0
kernel/src/filesystem/eventfd.rs

@@ -274,6 +274,10 @@ impl IndexNode for EventFdInode {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
         Ok(self)
         Ok(self)
     }
     }
+
+    fn absolute_path(&self) -> Result<String, SystemError> {
+        Ok(String::from("eventfd"))
+    }
 }
 }
 
 
 impl Syscall {
 impl Syscall {

+ 8 - 11
kernel/src/filesystem/kernfs/mod.rs

@@ -32,6 +32,7 @@ pub mod callback;
 #[derive(Debug)]
 #[derive(Debug)]
 pub struct KernFS {
 pub struct KernFS {
     root_inode: Arc<KernFSInode>,
     root_inode: Arc<KernFSInode>,
+    fsname: &'static str,
 }
 }
 
 
 impl FileSystem for KernFS {
 impl FileSystem for KernFS {
@@ -51,7 +52,7 @@ impl FileSystem for KernFS {
     }
     }
 
 
     fn name(&self) -> &str {
     fn name(&self) -> &str {
-        "kernfs"
+        self.fsname
     }
     }
 
 
     fn super_block(&self) -> SuperBlock {
     fn super_block(&self) -> SuperBlock {
@@ -66,19 +67,15 @@ impl FileSystem for KernFS {
 impl KernFS {
 impl KernFS {
     pub const MAX_NAMELEN: usize = 4096;
     pub const MAX_NAMELEN: usize = 4096;
     pub const KERNFS_BLOCK_SIZE: u64 = 512;
     pub const KERNFS_BLOCK_SIZE: u64 = 512;
-    #[allow(dead_code)]
-    pub fn new() -> Arc<Self> {
+
+    #[inline(never)]
+    pub fn new(fsname: &'static str) -> Arc<Self> {
         let root_inode = Self::create_root_inode();
         let root_inode = Self::create_root_inode();
         let fs = Arc::new(Self {
         let fs = Arc::new(Self {
             root_inode: root_inode.clone(),
             root_inode: root_inode.clone(),
+            fsname,
         });
         });
 
 
-        {
-            let ptr = root_inode.as_ref() as *const KernFSInode as *mut KernFSInode;
-            unsafe {
-                (*ptr).self_ref = Arc::downgrade(&root_inode);
-            }
-        }
         root_inode.inner.write().parent = Arc::downgrade(&root_inode);
         root_inode.inner.write().parent = Arc::downgrade(&root_inode);
         *root_inode.fs.write() = Arc::downgrade(&fs);
         *root_inode.fs.write() = Arc::downgrade(&fs);
         return fs;
         return fs;
@@ -102,7 +99,7 @@ impl KernFS {
             nlinks: 1,
             nlinks: 1,
             raw_dev: DeviceNumber::default(),
             raw_dev: DeviceNumber::default(),
         };
         };
-        let root_inode = Arc::new(KernFSInode {
+        let root_inode = Arc::new_cyclic(|self_ref| KernFSInode {
             name: String::from(""),
             name: String::from(""),
             inner: RwLock::new(InnerKernFSInode {
             inner: RwLock::new(InnerKernFSInode {
                 parent: Weak::new(),
                 parent: Weak::new(),
@@ -110,7 +107,7 @@ impl KernFS {
                 symlink_target: None,
                 symlink_target: None,
                 symlink_target_absolute_path: None,
                 symlink_target_absolute_path: None,
             }),
             }),
-            self_ref: Weak::new(),
+            self_ref: self_ref.clone(),
             fs: RwLock::new(Weak::new()),
             fs: RwLock::new(Weak::new()),
             private_data: SpinLock::new(None),
             private_data: SpinLock::new(None),
             callback: None,
             callback: None,

+ 11 - 0
kernel/src/filesystem/page_cache.rs

@@ -316,6 +316,17 @@ impl InnerPageCache {
     pub fn pages_count(&self) -> usize {
     pub fn pages_count(&self) -> usize {
         return self.pages.len();
         return self.pages.len();
     }
     }
+
+    /// Synchronize the page cache with the storage device.
+    pub fn sync(&mut self) -> Result<(), SystemError> {
+        for page in self.pages.values() {
+            let mut guard = page.write_irqsave();
+            if guard.flags().contains(PageFlags::PG_DIRTY) {
+                crate::mm::page::PageReclaimer::page_writeback(&mut guard, false);
+            }
+        }
+        Ok(())
+    }
 }
 }
 
 
 impl Drop for InnerPageCache {
 impl Drop for InnerPageCache {

+ 329 - 103
kernel/src/filesystem/procfs/mod.rs

@@ -14,7 +14,7 @@ use system_error::SystemError;
 use crate::{
 use crate::{
     arch::mm::LockedFrameAllocator,
     arch::mm::LockedFrameAllocator,
     driver::base::device::device_number::DeviceNumber,
     driver::base::device::device_number::DeviceNumber,
-    filesystem::vfs::{vcore::generate_inode_id, FileType},
+    filesystem::vfs::{mount::MountFlags, vcore::generate_inode_id, FileType},
     libs::{
     libs::{
         once::Once,
         once::Once,
         rwlock::RwLock,
         rwlock::RwLock,
@@ -34,11 +34,12 @@ use super::vfs::{
 
 
 pub mod kmsg;
 pub mod kmsg;
 pub mod log;
 pub mod log;
+mod proc_mounts;
 mod syscall;
 mod syscall;
 
 
 /// @brief 进程文件类型
 /// @brief 进程文件类型
 /// @usage 用于定义进程文件夹下的各类文件类型
 /// @usage 用于定义进程文件夹下的各类文件类型
-#[derive(Debug)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 #[repr(u8)]
 #[repr(u8)]
 pub enum ProcFileType {
 pub enum ProcFileType {
     ///展示进程状态信息
     ///展示进程状态信息
@@ -49,6 +50,11 @@ pub enum ProcFileType {
     ProcKmsg = 2,
     ProcKmsg = 2,
     /// 可执行路径
     /// 可执行路径
     ProcExe = 3,
     ProcExe = 3,
+    /// /proc/mounts
+    ProcSelf = 4,
+    ProcFdDir = 5,
+    ProcFdFile = 6,
+    ProcMounts = 7,
     //todo: 其他文件类型
     //todo: 其他文件类型
     ///默认文件类型
     ///默认文件类型
     Default,
     Default,
@@ -61,19 +67,105 @@ impl From<u8> for ProcFileType {
             1 => ProcFileType::ProcMeminfo,
             1 => ProcFileType::ProcMeminfo,
             2 => ProcFileType::ProcKmsg,
             2 => ProcFileType::ProcKmsg,
             3 => ProcFileType::ProcExe,
             3 => ProcFileType::ProcExe,
+            4 => ProcFileType::ProcSelf,
+            5 => ProcFileType::ProcFdDir,
+            6 => ProcFileType::ProcFdFile,
+            7 => ProcFileType::ProcMounts,
             _ => ProcFileType::Default,
             _ => ProcFileType::Default,
         }
         }
     }
     }
 }
 }
+/// @brief 创建 ProcFS 文件的参数结构体
+#[derive(Debug, Clone)]
+pub struct ProcFileCreationParams<'a> {
+    pub parent: Arc<dyn IndexNode>,
+    pub name: &'a str,
+    pub file_type: FileType,
+    pub mode: ModeType,
+    pub pid: Option<RawPid>,
+    pub ftype: ProcFileType,
+    pub data: Option<&'a str>,
+}
+
+impl<'a> ProcFileCreationParams<'a> {
+    pub fn builder() -> ProcFileCreationParamsBuilder<'a> {
+        ProcFileCreationParamsBuilder::default()
+    }
+}
+
+/// @brief ProcFileCreationParams 的 Builder 模式实现
+#[derive(Debug, Clone, Default)]
+pub struct ProcFileCreationParamsBuilder<'a> {
+    parent: Option<Arc<dyn IndexNode>>,
+    name: Option<&'a str>,
+    file_type: Option<FileType>,
+    mode: Option<ModeType>,
+    pid: Option<RawPid>,
+    ftype: Option<ProcFileType>,
+    data: Option<&'a str>,
+}
+
+#[allow(dead_code)]
+impl<'a> ProcFileCreationParamsBuilder<'a> {
+    pub fn parent(mut self, parent: Arc<dyn IndexNode>) -> Self {
+        self.parent = Some(parent);
+        self
+    }
+
+    pub fn name(mut self, name: &'a str) -> Self {
+        self.name = Some(name);
+        self
+    }
+
+    pub fn file_type(mut self, file_type: FileType) -> Self {
+        self.file_type = Some(file_type);
+        self
+    }
+
+    pub fn mode(mut self, mode: ModeType) -> Self {
+        self.mode = Some(mode);
+        self
+    }
+
+    pub fn pid(mut self, pid: RawPid) -> Self {
+        self.pid = Some(pid);
+        self
+    }
+
+    pub fn ftype(mut self, ftype: ProcFileType) -> Self {
+        self.ftype = Some(ftype);
+        self
+    }
+
+    pub fn data(mut self, data: &'a str) -> Self {
+        self.data = Some(data);
+        self
+    }
+
+    pub fn build(self) -> Result<ProcFileCreationParams<'a>, SystemError> {
+        Ok(ProcFileCreationParams {
+            parent: self.parent.ok_or(SystemError::EINVAL)?,
+            name: self.name.ok_or(SystemError::EINVAL)?,
+            file_type: self.file_type.ok_or(SystemError::EINVAL)?,
+            mode: self.mode.unwrap_or(ModeType::S_IRUGO),
+            pid: self.pid,
+            ftype: self.ftype.ok_or(SystemError::EINVAL)?,
+            data: self.data,
+        })
+    }
+}
+
 /// @brief 节点私有信息结构体
 /// @brief 节点私有信息结构体
 /// @usage 用于传入各类文件所需的信息
 /// @usage 用于传入各类文件所需的信息
 #[derive(Debug)]
 #[derive(Debug)]
 pub struct InodeInfo {
 pub struct InodeInfo {
     ///进程的pid
     ///进程的pid
-    pid: RawPid,
+    pid: Option<RawPid>,
     ///文件类型
     ///文件类型
     ftype: ProcFileType,
     ftype: ProcFileType,
-    //其他需要传入的信息在此定义
+    /// 文件描述符
+    fd: i32,
+    // 其他需要传入的信息在此定义
 }
 }
 
 
 /// @brief procfs的inode名称的最大长度
 /// @brief procfs的inode名称的最大长度
@@ -144,7 +236,10 @@ impl ProcFSInode {
     ///
     ///
     fn open_status(&self, pdata: &mut ProcfsFilePrivateData) -> Result<i64, SystemError> {
     fn open_status(&self, pdata: &mut ProcfsFilePrivateData) -> Result<i64, SystemError> {
         // 获取该pid对应的pcb结构体
         // 获取该pid对应的pcb结构体
-        let pid = self.fdata.pid;
+        let pid = self
+            .fdata
+            .pid
+            .expect("ProcFS: pid is None when opening 'status' file.");
         let pcb = ProcessManager::find_task_by_vpid(pid);
         let pcb = ProcessManager::find_task_by_vpid(pid);
         let pcb = if let Some(pcb) = pcb {
         let pcb = if let Some(pcb) = pcb {
             pcb
             pcb
@@ -179,7 +274,8 @@ impl ProcFSInode {
 
 
         let priority = sched_info_guard.policy();
         let priority = sched_info_guard.policy();
         let vrtime = sched_info_guard.sched_entity.vruntime;
         let vrtime = sched_info_guard.sched_entity.vruntime;
-
+        let time = sched_info_guard.sched_entity.sum_exec_runtime;
+        let start_time = sched_info_guard.sched_entity.exec_start;
         // State
         // State
         pdata.append(&mut format!("\nState:\t{:?}", state).as_bytes().to_owned());
         pdata.append(&mut format!("\nState:\t{:?}", state).as_bytes().to_owned());
 
 
@@ -229,9 +325,12 @@ impl ProcFSInode {
         };
         };
         pdata.append(&mut format!("\nTty:\t{}", name).as_bytes().to_owned());
         pdata.append(&mut format!("\nTty:\t{}", name).as_bytes().to_owned());
 
 
+        // 进程在cpu上的运行时间
+        pdata.append(&mut format!("\nTime:\t{}", time).as_bytes().to_owned());
+        // 进程开始运行的时间
+        pdata.append(&mut format!("\nStime:\t{}", start_time).as_bytes().to_owned());
         // kthread
         // kthread
         pdata.append(&mut format!("\nKthread:\t{}", pcb.is_kthread() as usize).into());
         pdata.append(&mut format!("\nKthread:\t{}", pcb.is_kthread() as usize).into());
-
         pdata.append(&mut format!("\ncpu_id:\t{}", cpu_id).as_bytes().to_owned());
         pdata.append(&mut format!("\ncpu_id:\t{}", cpu_id).as_bytes().to_owned());
         pdata.append(&mut format!("\npriority:\t{:?}", priority).as_bytes().to_owned());
         pdata.append(&mut format!("\npriority:\t{:?}", priority).as_bytes().to_owned());
         pdata.append(
         pdata.append(
@@ -304,15 +403,21 @@ impl ProcFSInode {
         return Ok(0);
         return Ok(0);
     }
     }
 
 
+    fn open_self(&self, _pdata: &mut ProcfsFilePrivateData) -> Result<i64, SystemError> {
+        let pid = ProcessManager::current_pid().data();
+        return Ok(pid.to_string().as_bytes().len() as _);
+    }
+
     // 读取exe文件
     // 读取exe文件
-    fn read_link(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
+    fn read_exe_link(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
         // 判断是否有记录pid信息,有的话就是当前进程的exe文件,没有则是当前进程的exe文件
         // 判断是否有记录pid信息,有的话就是当前进程的exe文件,没有则是当前进程的exe文件
-        let pid = self.fdata.pid;
-        let pcb = if pid == RawPid::from(0) {
-            ProcessManager::current_pcb()
-        } else {
+        let pcb = if let Some(pid) = self.fdata.pid {
             ProcessManager::find_task_by_vpid(pid).ok_or(SystemError::ESRCH)?
             ProcessManager::find_task_by_vpid(pid).ok_or(SystemError::ESRCH)?
+        } else {
+            // 如果没有pid信息,则读取当前进程的exe文件
+            ProcessManager::current_pcb()
         };
         };
+
         let exe = pcb.execute_path();
         let exe = pcb.execute_path();
         let exe_bytes = exe.as_bytes();
         let exe_bytes = exe.as_bytes();
         let len = exe_bytes.len().min(buf.len());
         let len = exe_bytes.len().min(buf.len());
@@ -320,6 +425,31 @@ impl ProcFSInode {
         Ok(len)
         Ok(len)
     }
     }
 
 
+    /// read current task pid dynamically
+    fn read_self_link(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let pid = ProcessManager::current_pid().data();
+        let pid_bytes = pid.to_string();
+        let len = pid_bytes.len().min(buf.len());
+        buf[..len].copy_from_slice(&pid_bytes.as_bytes()[..len]);
+        Ok(len)
+    }
+
+    fn read_fd_link(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let fd = self.fdata.fd;
+        let fd_table = ProcessManager::current_pcb().fd_table();
+        let fd_table = fd_table.read();
+        let file = fd_table.get_file_by_fd(fd);
+        if let Some(file) = file {
+            let inode = file.inode();
+            let path = inode.absolute_path().unwrap();
+            let len = path.len().min(buf.len());
+            buf[..len].copy_from_slice(&path.as_bytes()[..len]);
+            Ok(len)
+        } else {
+            return Err(SystemError::EBADF);
+        }
+    }
+
     /// proc文件系统读取函数
     /// proc文件系统读取函数
     fn proc_read(
     fn proc_read(
         &self,
         &self,
@@ -368,6 +498,26 @@ impl FileSystem for ProcFS {
 }
 }
 
 
 impl ProcFS {
 impl ProcFS {
+    #[inline(never)]
+    fn create_proc_file(&self, params: ProcFileCreationParams) -> Result<(), SystemError> {
+        let binding = params
+            .parent
+            .create(params.name, params.file_type, params.mode)?;
+        let proc_file = binding
+            .as_any_ref()
+            .downcast_ref::<LockedProcFSInode>()
+            .unwrap();
+        let mut proc_file_guard = proc_file.0.lock();
+        proc_file_guard.fdata.pid = params.pid;
+        proc_file_guard.fdata.ftype = params.ftype;
+        if let Some(data_content) = params.data {
+            proc_file_guard.data = data_content.to_string().as_bytes().to_vec();
+        }
+        drop(proc_file_guard);
+        Ok(())
+    }
+
+    #[inline(never)]
     pub fn new() -> Arc<Self> {
     pub fn new() -> Arc<Self> {
         let super_block = SuperBlock::new(
         let super_block = SuperBlock::new(
             Magic::PROC_MAGIC,
             Magic::PROC_MAGIC,
@@ -400,8 +550,9 @@ impl ProcFS {
                 },
                 },
                 fs: Weak::default(),
                 fs: Weak::default(),
                 fdata: InodeInfo {
                 fdata: InodeInfo {
-                    pid: RawPid::new(0),
+                    pid: None,
                     ftype: ProcFileType::Default,
                     ftype: ProcFileType::Default,
+                    fd: -1,
                 },
                 },
                 dname: DName::default(),
                 dname: DName::default(),
             })));
             })));
@@ -420,35 +571,30 @@ impl ProcFS {
         drop(root_guard);
         drop(root_guard);
 
 
         // 创建meminfo文件
         // 创建meminfo文件
-        let inode = result.root_inode();
-        let binding = inode.create(
-            "meminfo",
-            FileType::File,
-            ModeType::from_bits_truncate(0o444),
-        );
-        if let Ok(meminfo) = binding {
-            let meminfo_file = meminfo
-                .as_any_ref()
-                .downcast_ref::<LockedProcFSInode>()
-                .unwrap();
-            meminfo_file.0.lock().fdata.pid = RawPid::new(0);
-            meminfo_file.0.lock().fdata.ftype = ProcFileType::ProcMeminfo;
-        } else {
-            panic!("create meminfo error");
-        }
+        let meminfo_params = ProcFileCreationParams::builder()
+            .parent(result.root_inode())
+            .name("meminfo")
+            .file_type(FileType::File)
+            .mode(ModeType::from_bits_truncate(0o444))
+            .ftype(ProcFileType::ProcMeminfo)
+            .build()
+            .unwrap();
+        result
+            .create_proc_file(meminfo_params)
+            .unwrap_or_else(|_| panic!("create meminfo error"));
 
 
         // 创建kmsg文件
         // 创建kmsg文件
-        let binding = inode.create("kmsg", FileType::File, ModeType::from_bits_truncate(0o444));
-        if let Ok(kmsg) = binding {
-            let kmsg_file = kmsg
-                .as_any_ref()
-                .downcast_ref::<LockedProcFSInode>()
-                .unwrap();
-            kmsg_file.0.lock().fdata.pid = RawPid::new(1);
-            kmsg_file.0.lock().fdata.ftype = ProcFileType::ProcKmsg;
-        } else {
-            panic!("create ksmg error");
-        }
+        let kmsg_params = ProcFileCreationParams::builder()
+            .parent(result.root_inode())
+            .name("kmsg")
+            .file_type(FileType::File)
+            .mode(ModeType::from_bits_truncate(0o444))
+            .ftype(ProcFileType::ProcKmsg)
+            .build()
+            .unwrap();
+        result
+            .create_proc_file(kmsg_params)
+            .unwrap_or_else(|_| panic!("create kmsg error"));
         // 这个文件是用来欺骗Aya框架识别内核版本
         // 这个文件是用来欺骗Aya框架识别内核版本
         /* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
         /* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
          * but Ubuntu provides /proc/version_signature file, as described at
          * but Ubuntu provides /proc/version_signature file, as described at
@@ -460,36 +606,44 @@ impl ProcFS {
          * In the above, 5.4.8 is what kernel is actually expecting, while
          * In the above, 5.4.8 is what kernel is actually expecting, while
          * uname() call will return 5.4.0 in info.release.
          * uname() call will return 5.4.0 in info.release.
          */
          */
-        let binding = inode.create("version_signature", FileType::File, ModeType::S_IRUGO);
-        if let Ok(version_signature) = binding {
-            let version_signature = version_signature
-                .as_any_ref()
-                .downcast_ref::<LockedProcFSInode>()
-                .unwrap();
-            version_signature.0.lock().fdata.ftype = ProcFileType::Default;
-            version_signature.0.lock().data = "DragonOS 6.0.0-generic 6.0.0\n"
-                .to_string()
-                .as_bytes()
-                .to_vec();
-        } else {
-            panic!("create version_signature error");
-        }
+        let version_signature_params = ProcFileCreationParams::builder()
+            .parent(result.root_inode())
+            .name("version_signature")
+            .file_type(FileType::File)
+            .ftype(ProcFileType::Default)
+            .data("DragonOS 6.0.0-generic 6.0.0\n")
+            .build()
+            .unwrap();
+        result
+            .create_proc_file(version_signature_params)
+            .unwrap_or_else(|_| panic!("create version_signature error"));
+
+        let mounts_params = ProcFileCreationParams::builder()
+            .parent(result.root_inode())
+            .name("mounts")
+            .file_type(FileType::File)
+            .ftype(ProcFileType::ProcMounts)
+            .build()
+            .unwrap();
+        result
+            .create_proc_file(mounts_params)
+            .unwrap_or_else(|_| panic!("create mounts error"));
 
 
-        let self_dir = inode
+        let self_dir = result
+            .root_inode()
             .create("self", FileType::Dir, ModeType::from_bits_truncate(0o555))
             .create("self", FileType::Dir, ModeType::from_bits_truncate(0o555))
             .unwrap();
             .unwrap();
 
 
-        let binding = self_dir.create("exe", FileType::SymLink, ModeType::S_IRUGO);
-        if let Ok(exe) = binding {
-            let exe_file = exe
-                .as_any_ref()
-                .downcast_ref::<LockedProcFSInode>()
-                .unwrap();
-            exe_file.0.lock().fdata.pid = RawPid::new(0);
-            exe_file.0.lock().fdata.ftype = ProcFileType::ProcExe;
-        } else {
-            panic!("create exe error");
-        }
+        let exe_params = ProcFileCreationParams::builder()
+            .parent(self_dir)
+            .name("exe")
+            .file_type(FileType::SymLink)
+            .ftype(ProcFileType::ProcExe)
+            .build()
+            .unwrap();
+        result
+            .create_proc_file(exe_params)
+            .unwrap_or_else(|_| panic!("create exe error"));
 
 
         return result;
         return result;
     }
     }
@@ -498,16 +652,16 @@ impl ProcFS {
     /// @usage 在进程中调用并创建进程对应文件
     /// @usage 在进程中调用并创建进程对应文件
     pub fn register_pid(&self, pid: RawPid) -> Result<(), SystemError> {
     pub fn register_pid(&self, pid: RawPid) -> Result<(), SystemError> {
         // 获取当前inode
         // 获取当前inode
-        let inode: Arc<dyn IndexNode> = self.root_inode();
+        let inode = self.root_inode();
         // 创建对应进程文件夹
         // 创建对应进程文件夹
-        let pid_dir: Arc<dyn IndexNode> = inode.create(
+        let pid_dir = inode.create(
             &pid.to_string(),
             &pid.to_string(),
             FileType::Dir,
             FileType::Dir,
             ModeType::from_bits_truncate(0o555),
             ModeType::from_bits_truncate(0o555),
         )?;
         )?;
         // 创建相关文件
         // 创建相关文件
         // status文件
         // status文件
-        let status_binding: Arc<dyn IndexNode> = pid_dir.create(
+        let status_binding = pid_dir.create(
             "status",
             "status",
             FileType::File,
             FileType::File,
             ModeType::from_bits_truncate(0o444),
             ModeType::from_bits_truncate(0o444),
@@ -516,11 +670,11 @@ impl ProcFS {
             .as_any_ref()
             .as_any_ref()
             .downcast_ref::<LockedProcFSInode>()
             .downcast_ref::<LockedProcFSInode>()
             .unwrap();
             .unwrap();
-        status_file.0.lock().fdata.pid = pid;
+        status_file.0.lock().fdata.pid = Some(pid);
         status_file.0.lock().fdata.ftype = ProcFileType::ProcStatus;
         status_file.0.lock().fdata.ftype = ProcFileType::ProcStatus;
 
 
         // exe文件
         // exe文件
-        let exe_binding: Arc<dyn IndexNode> = pid_dir.create_with_data(
+        let exe_binding = pid_dir.create_with_data(
             "exe",
             "exe",
             FileType::SymLink,
             FileType::SymLink,
             ModeType::from_bits_truncate(0o444),
             ModeType::from_bits_truncate(0o444),
@@ -530,9 +684,13 @@ impl ProcFS {
             .as_any_ref()
             .as_any_ref()
             .downcast_ref::<LockedProcFSInode>()
             .downcast_ref::<LockedProcFSInode>()
             .unwrap();
             .unwrap();
-        exe_file.0.lock().fdata.pid = pid;
+        exe_file.0.lock().fdata.pid = Some(pid);
         exe_file.0.lock().fdata.ftype = ProcFileType::ProcExe;
         exe_file.0.lock().fdata.ftype = ProcFileType::ProcExe;
 
 
+        // fd dir
+        let fd = pid_dir.create("fd", FileType::Dir, ModeType::from_bits_truncate(0o555))?;
+        let fd = fd.as_any_ref().downcast_ref::<LockedProcFSInode>().unwrap();
+        fd.0.lock().fdata.ftype = ProcFileType::ProcFdDir;
         //todo: 创建其他文件
         //todo: 创建其他文件
 
 
         return Ok(());
         return Ok(());
@@ -548,6 +706,7 @@ impl ProcFS {
         // 删除进程文件夹下文件
         // 删除进程文件夹下文件
         pid_dir.unlink("status")?;
         pid_dir.unlink("status")?;
         pid_dir.unlink("exe")?;
         pid_dir.unlink("exe")?;
+        pid_dir.rmdir("fd")?;
 
 
         // 查看进程文件是否还存在
         // 查看进程文件是否还存在
         // let pf= pid_dir.find("status").expect("Cannot find status");
         // let pf= pid_dir.find("status").expect("Cannot find status");
@@ -559,6 +718,43 @@ impl ProcFS {
     }
     }
 }
 }
 
 
+impl LockedProcFSInode {
+    fn dynamical_find_fd(&self, fd: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
+        // ::log::info!("ProcFS: Dynamically opening fd files for current process.");
+        let fd = fd.parse::<i32>().map_err(|_| SystemError::EINVAL)?;
+        let pcb = ProcessManager::current_pcb();
+        let fd_table = pcb.fd_table();
+        let fd_table = fd_table.read();
+        let file = fd_table.get_file_by_fd(fd);
+        if file.is_some() {
+            let _ = self.unlink(&fd.to_string());
+            let fd_file = self.create(
+                &fd.to_string(),
+                FileType::SymLink,
+                ModeType::from_bits_truncate(0o444),
+            )?;
+            let fd_file_proc = fd_file
+                .as_any_ref()
+                .downcast_ref::<LockedProcFSInode>()
+                .unwrap();
+            fd_file_proc.0.lock().fdata.fd = fd;
+            fd_file_proc.0.lock().fdata.ftype = ProcFileType::ProcFdFile;
+            return Ok(fd_file);
+        } else {
+            return Err(SystemError::ENOENT);
+        }
+    }
+
+    fn dynamical_list_fd(&self) -> Result<Vec<String>, SystemError> {
+        // ::log::info!("ProcFS: Dynamically listing fd files for current process");
+        let pcb = ProcessManager::current_pcb();
+        let fd_table = pcb.fd_table();
+        let fd_table = fd_table.read();
+        let res = fd_table.iter().map(|(fd, _)| fd.to_string()).collect();
+        return Ok(res);
+    }
+}
+
 impl IndexNode for LockedProcFSInode {
 impl IndexNode for LockedProcFSInode {
     fn open(
     fn open(
         &self,
         &self,
@@ -567,6 +763,7 @@ impl IndexNode for LockedProcFSInode {
     ) -> Result<(), SystemError> {
     ) -> Result<(), SystemError> {
         // 加锁
         // 加锁
         let mut inode: SpinLockGuard<ProcFSInode> = self.0.lock();
         let mut inode: SpinLockGuard<ProcFSInode> = self.0.lock();
+        let proc_ty = inode.fdata.ftype;
 
 
         // 如果inode类型为文件夹,则直接返回成功
         // 如果inode类型为文件夹,则直接返回成功
         if let FileType::Dir = inode.metadata.file_type {
         if let FileType::Dir = inode.metadata.file_type {
@@ -574,22 +771,37 @@ impl IndexNode for LockedProcFSInode {
         }
         }
         let mut private_data = ProcfsFilePrivateData::new();
         let mut private_data = ProcfsFilePrivateData::new();
         // 根据文件类型获取相应数据
         // 根据文件类型获取相应数据
-        let file_size = match inode.fdata.ftype {
+        let file_size = match proc_ty {
             ProcFileType::ProcStatus => inode.open_status(&mut private_data)?,
             ProcFileType::ProcStatus => inode.open_status(&mut private_data)?,
             ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?,
             ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?,
             ProcFileType::ProcExe => inode.open_exe(&mut private_data)?,
             ProcFileType::ProcExe => inode.open_exe(&mut private_data)?,
+            ProcFileType::ProcMounts => inode.open_mounts(&mut private_data)?,
             ProcFileType::Default => inode.data.len() as i64,
             ProcFileType::Default => inode.data.len() as i64,
-            _ => {
-                todo!()
-            }
+            ProcFileType::ProcSelf => inode.open_self(&mut private_data)?,
+            _ => 0,
         };
         };
         *data = FilePrivateData::Procfs(private_data);
         *data = FilePrivateData::Procfs(private_data);
         // 更新metadata里面的文件大小数值
         // 更新metadata里面的文件大小数值
         inode.metadata.size = file_size;
         inode.metadata.size = file_size;
+        drop(inode);
+        return Ok(());
+    }
 
 
+    fn rmdir(&self, name: &str) -> Result<(), SystemError> {
+        let mut guard = self.0.lock();
+        if guard.metadata.file_type != FileType::Dir {
+            return Err(SystemError::ENOTDIR);
+        }
+        let name = DName::from(name);
+        guard.children.remove(&name);
         return Ok(());
         return Ok(());
     }
     }
 
 
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.0.lock().parent.upgrade().ok_or(SystemError::ENOENT)?;
+        return Ok(parent as Arc<dyn IndexNode>);
+    }
+
     fn close(&self, mut data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
     fn close(&self, mut data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
         let guard: SpinLockGuard<ProcFSInode> = self.0.lock();
         let guard: SpinLockGuard<ProcFSInode> = self.0.lock();
         // 如果inode类型为文件夹,则直接返回成功
         // 如果inode类型为文件夹,则直接返回成功
@@ -613,32 +825,30 @@ impl IndexNode for LockedProcFSInode {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
         }
         }
         // 加锁
         // 加锁
-        let inode: SpinLockGuard<ProcFSInode> = self.0.lock();
+        let inode = self.0.lock();
 
 
         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
         if inode.metadata.file_type == FileType::Dir {
         if inode.metadata.file_type == FileType::Dir {
             return Err(SystemError::EISDIR);
             return Err(SystemError::EISDIR);
         }
         }
 
 
-        // 获取数据信息
-        let mut private_data = match &*data {
-            FilePrivateData::Procfs(p) => p.clone(),
-            _ => {
-                panic!("ProcFS: FilePrivateData mismatch!");
-            }
-        };
-
         // 根据文件类型读取相应数据
         // 根据文件类型读取相应数据
         match inode.fdata.ftype {
         match inode.fdata.ftype {
-            ProcFileType::ProcStatus => {
-                return inode.proc_read(offset, len, buf, &mut private_data)
-            }
-            ProcFileType::ProcMeminfo => {
-                return inode.proc_read(offset, len, buf, &mut private_data)
+            ProcFileType::ProcStatus | ProcFileType::ProcMeminfo | ProcFileType::ProcMounts => {
+                // 获取数据信息
+                let mut private_data = match &*data {
+                    FilePrivateData::Procfs(p) => p.clone(),
+                    _ => {
+                        panic!("ProcFS: FilePrivateData mismatch!");
+                    }
+                };
+                return inode.proc_read(offset, len, buf, &mut private_data);
             }
             }
-            ProcFileType::ProcExe => return inode.read_link(buf),
-            ProcFileType::ProcKmsg => (),
-            ProcFileType::Default => (),
+            ProcFileType::ProcExe => return inode.read_exe_link(buf),
+            ProcFileType::ProcSelf => return inode.read_self_link(buf),
+            ProcFileType::ProcFdFile => return inode.read_fd_link(buf),
+
+            _ => (),
         };
         };
 
 
         // 默认读取
         // 默认读取
@@ -677,7 +887,6 @@ impl IndexNode for LockedProcFSInode {
     fn metadata(&self) -> Result<Metadata, SystemError> {
     fn metadata(&self) -> Result<Metadata, SystemError> {
         let inode = self.0.lock();
         let inode = self.0.lock();
         let metadata = inode.metadata.clone();
         let metadata = inode.metadata.clone();
-
         return Ok(metadata);
         return Ok(metadata);
     }
     }
 
 
@@ -749,8 +958,9 @@ impl IndexNode for LockedProcFSInode {
                 },
                 },
                 fs: inode.fs.clone(),
                 fs: inode.fs.clone(),
                 fdata: InodeInfo {
                 fdata: InodeInfo {
-                    pid: RawPid::new(0),
+                    pid: None,
                     ftype: ProcFileType::Default,
                     ftype: ProcFileType::Default,
+                    fd: -1,
                 },
                 },
                 dname: name.clone(),
                 dname: name.clone(),
             })));
             })));
@@ -829,23 +1039,32 @@ impl IndexNode for LockedProcFSInode {
     }
     }
 
 
     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
-        let inode = self.0.lock();
-
-        if inode.metadata.file_type != FileType::Dir {
+        if self.0.lock().metadata.file_type != FileType::Dir {
             return Err(SystemError::ENOTDIR);
             return Err(SystemError::ENOTDIR);
         }
         }
 
 
         match name {
         match name {
             "" | "." => {
             "" | "." => {
-                return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
+                return Ok(self
+                    .0
+                    .lock()
+                    .self_ref
+                    .upgrade()
+                    .ok_or(SystemError::ENOENT)?);
             }
             }
 
 
             ".." => {
             ".." => {
-                return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?);
+                return Ok(self.0.lock().parent.upgrade().ok_or(SystemError::ENOENT)?);
             }
             }
+
             name => {
             name => {
+                if self.0.lock().fdata.ftype == ProcFileType::ProcFdDir {
+                    return self.dynamical_find_fd(name);
+                }
                 // 在子目录项中查找
                 // 在子目录项中查找
-                return Ok(inode
+                return Ok(self
+                    .0
+                    .lock()
                     .children
                     .children
                     .get(&DName::from(name))
                     .get(&DName::from(name))
                     .ok_or(SystemError::ENOENT)?
                     .ok_or(SystemError::ENOENT)?
@@ -897,9 +1116,14 @@ impl IndexNode for LockedProcFSInode {
             return Err(SystemError::ENOTDIR);
             return Err(SystemError::ENOTDIR);
         }
         }
 
 
-        let mut keys: Vec<String> = Vec::new();
+        let mut keys = Vec::new();
         keys.push(String::from("."));
         keys.push(String::from("."));
         keys.push(String::from(".."));
         keys.push(String::from(".."));
+
+        if self.0.lock().fdata.ftype == ProcFileType::ProcFdDir {
+            return self.dynamical_list_fd();
+        }
+
         keys.append(
         keys.append(
             &mut self
             &mut self
                 .0
                 .0
@@ -919,6 +1143,7 @@ impl IndexNode for LockedProcFSInode {
 }
 }
 
 
 /// @brief 向procfs注册进程
 /// @brief 向procfs注册进程
+#[inline(never)]
 pub fn procfs_register_pid(pid: RawPid) -> Result<(), SystemError> {
 pub fn procfs_register_pid(pid: RawPid) -> Result<(), SystemError> {
     let root_inode = ProcessManager::current_mntns().root_inode();
     let root_inode = ProcessManager::current_mntns().root_inode();
     let procfs_inode = root_inode.find("proc")?;
     let procfs_inode = root_inode.find("proc")?;
@@ -936,6 +1161,7 @@ pub fn procfs_register_pid(pid: RawPid) -> Result<(), SystemError> {
 }
 }
 
 
 /// @brief 在ProcFS中,解除进程的注册
 /// @brief 在ProcFS中,解除进程的注册
+#[inline(never)]
 pub fn procfs_unregister_pid(pid: RawPid) -> Result<(), SystemError> {
 pub fn procfs_unregister_pid(pid: RawPid) -> Result<(), SystemError> {
     let root_inode = ProcessManager::current_mntns().root_inode();
     let root_inode = ProcessManager::current_mntns().root_inode();
     // 获取procfs实例
     // 获取procfs实例
@@ -963,7 +1189,7 @@ pub fn procfs_init() -> Result<(), SystemError> {
         root_inode
         root_inode
             .mkdir("proc", ModeType::from_bits_truncate(0o755))
             .mkdir("proc", ModeType::from_bits_truncate(0o755))
             .expect("Unabled to find /proc")
             .expect("Unabled to find /proc")
-            .mount(procfs)
+            .mount(procfs, MountFlags::empty())
             .expect("Failed to mount at /proc");
             .expect("Failed to mount at /proc");
         info!("ProcFS mounted.");
         info!("ProcFS mounted.");
         result = Some(Ok(()));
         result = Some(Ok(()));

+ 73 - 0
kernel/src/filesystem/procfs/proc_mounts.rs

@@ -0,0 +1,73 @@
+use alloc::vec::Vec;
+
+use alloc::string::{String, ToString};
+
+use system_error::SystemError;
+
+use crate::{filesystem::vfs::IndexNode, process::ProcessManager};
+
+use super::{ProcFSInode, ProcfsFilePrivateData};
+
+impl ProcFSInode {
+    /// 打开 meminfo 文件
+    #[inline(never)]
+    pub(super) fn open_mounts(
+        &self,
+        pdata: &mut ProcfsFilePrivateData,
+    ) -> Result<i64, SystemError> {
+        // 生成mount信息
+        let mount_content = Self::generate_mounts_content();
+
+        pdata.data = mount_content.into_bytes();
+        return Ok(pdata.data.len() as i64);
+    }
+
+    #[inline(never)]
+    fn generate_mounts_content() -> String {
+        let mntns = ProcessManager::current_mntns();
+        let mounts = mntns.mount_list().clone_inner();
+
+        let mut lines = Vec::with_capacity(mounts.len());
+        let mut cap = 0;
+        for (mp, mfs) in mounts {
+            let mut line = String::new();
+            let fs_type = mfs.fs_type();
+            let source = match fs_type {
+                // 特殊文件系统,直接显示文件系统名称
+                "devfs" | "devpts" | "sysfs" | "procfs" | "tmpfs" | "ramfs" | "rootfs"
+                | "debugfs" | "configfs" => fs_type.to_string(),
+                // 其他文件系统,尝试显示挂载设备名称
+                _ => {
+                    if let Some(s) = mfs.self_mountpoint() {
+                        // 尝试从挂载点获取设备名称
+                        if let Some(device_name) = s.dname().ok().map(|d| d.to_string()) {
+                            device_name
+                        } else {
+                            // 如果获取不到设备名称,使用绝对路径
+                            s.absolute_path().unwrap_or("unknown".to_string())
+                        }
+                    } else {
+                        // 没有挂载点信息,使用文件系统类型
+                        fs_type.to_string()
+                    }
+                }
+            };
+
+            line.push_str(&format!("{source} {m} {fs_type}", m = mp.as_str()));
+
+            line.push(' ');
+            line.push_str(&mfs.mount_flags().options_string());
+
+            line.push_str(" 0 0\n");
+            cap += line.len();
+            lines.push(line);
+        }
+
+        let mut content = String::with_capacity(cap);
+        for line in lines {
+            content.push_str(&line);
+        }
+
+        return content;
+    }
+}

+ 3 - 2
kernel/src/filesystem/sysfs/mod.rs

@@ -8,6 +8,7 @@ use super::{
 };
 };
 use crate::{
 use crate::{
     driver::base::kobject::KObject,
     driver::base::kobject::KObject,
+    filesystem::vfs::mount::MountFlags,
     libs::{casting::DowncastArc, once::Once},
     libs::{casting::DowncastArc, once::Once},
     process::ProcessManager,
     process::ProcessManager,
 };
 };
@@ -45,7 +46,7 @@ pub fn sysfs_init() -> Result<(), SystemError> {
         root_inode
         root_inode
             .mkdir("sys", ModeType::from_bits_truncate(0o755))
             .mkdir("sys", ModeType::from_bits_truncate(0o755))
             .expect("Unabled to find /sys")
             .expect("Unabled to find /sys")
-            .mount(sysfs_instance().fs().clone())
+            .mount(sysfs_instance().fs().clone(), MountFlags::empty())
             .expect("Failed to mount at /sys");
             .expect("Failed to mount at /sys");
         info!("SysFS mounted.");
         info!("SysFS mounted.");
 
 
@@ -207,7 +208,7 @@ pub struct SysFS {
 
 
 impl SysFS {
 impl SysFS {
     pub fn new() -> Self {
     pub fn new() -> Self {
-        let kernfs: Arc<KernFS> = KernFS::new();
+        let kernfs: Arc<KernFS> = KernFS::new("sysfs");
 
 
         let root_inode: Arc<KernFSInode> = kernfs.root_inode().downcast_arc().unwrap();
         let root_inode: Arc<KernFSInode> = kernfs.root_inode().downcast_arc().unwrap();
 
 

+ 4 - 2
kernel/src/filesystem/vfs/file.rs

@@ -145,16 +145,18 @@ impl File {
             }
             }
         }
         }
 
 
+        let private_data = SpinLock::new(FilePrivateData::default());
+        inode.open(private_data.lock(), &mode)?;
+
         let f = File {
         let f = File {
             inode,
             inode,
             offset: AtomicUsize::new(0),
             offset: AtomicUsize::new(0),
             mode: RwLock::new(mode),
             mode: RwLock::new(mode),
             file_type,
             file_type,
             readdir_subdirs_name: SpinLock::new(Vec::default()),
             readdir_subdirs_name: SpinLock::new(Vec::default()),
-            private_data: SpinLock::new(FilePrivateData::default()),
+            private_data,
             cred: ProcessManager::current_pcb().cred(),
             cred: ProcessManager::current_pcb().cred(),
         };
         };
-        f.inode.open(f.private_data.lock(), &mode)?;
 
 
         return Ok(f);
         return Ok(f);
     }
     }

+ 19 - 18
kernel/src/filesystem/vfs/mod.rs

@@ -12,6 +12,7 @@ use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize};
 use alloc::{string::String, sync::Arc, vec::Vec};
 use alloc::{string::String, sync::Arc, vec::Vec};
 use derive_builder::Builder;
 use derive_builder::Builder;
 use intertrait::CastFromSync;
 use intertrait::CastFromSync;
+use mount::MountFlags;
 use system_error::SystemError;
 use system_error::SystemError;
 
 
 use crate::{
 use crate::{
@@ -476,7 +477,11 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
     ///
     ///
     /// - 该函数会在`MountFS`实例上创建一个新的挂载点。
     /// - 该函数会在`MountFS`实例上创建一个新的挂载点。
     /// - 该函数会在全局的挂载列表中记录新的挂载关系。
     /// - 该函数会在全局的挂载列表中记录新的挂载关系。
-    fn mount(&self, _fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> {
+    fn mount(
+        &self,
+        _fs: Arc<dyn FileSystem>,
+        _mount_flags: MountFlags,
+    ) -> Result<Arc<MountFS>, SystemError> {
         return Err(SystemError::ENOSYS);
         return Err(SystemError::ENOSYS);
     }
     }
 
 
@@ -529,25 +534,17 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
         return Err(SystemError::ENOSYS);
         return Err(SystemError::ENOSYS);
     }
     }
 
 
-    /// # absolute_path 获取目录项绝对路径
-    ///
-    /// ## 参数
+    /// Returns the absolute path of the inode.
     ///
     ///
-    /// 
-    ///
-    /// ## 返回值
+    /// This function only works for `MountFS` and should not be implemented by other file systems.
+    /// The performance of this function is O(n) for path queries, and it is extremely
+    /// inefficient in file systems that do not implement DName caching.
     ///
     ///
-    /// - Ok(String): 路径
-    /// - Err(SystemError): 文件系统不支持dname parent api
+    /// **WARNING**
     ///
     ///
-    /// ## Behavior
+    /// For special inodes(e.g., sockets,pipes, etc.), this function will
+    /// return an special name according to the inode type directly.
     ///
     ///
-    /// 该函数只能被MountFS实现,其他文件系统不应实现这个函数
-    ///
-    /// # Performance
-    ///
-    /// 这是一个O(n)的路径查询,并且在未实现DName缓存的文件系统中,性能极差;
-    /// 即使实现了DName也尽量不要用。
     fn absolute_path(&self) -> Result<String, SystemError> {
     fn absolute_path(&self) -> Result<String, SystemError> {
         return Err(SystemError::ENOSYS);
         return Err(SystemError::ENOSYS);
     }
     }
@@ -561,7 +558,11 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
 
 
     /// @brief 将当前inode的内容同步到具体设备上
     /// @brief 将当前inode的内容同步到具体设备上
     fn sync(&self) -> Result<(), SystemError> {
     fn sync(&self) -> Result<(), SystemError> {
-        return Ok(());
+        let page_cache = self.page_cache();
+        if let Some(page_cache) = page_cache {
+            return page_cache.lock_irqsave().sync();
+        }
+        Ok(())
     }
     }
 
 
     /// ## 创建一个特殊文件节点
     /// ## 创建一个特殊文件节点
@@ -770,7 +771,7 @@ impl dyn IndexNode {
             if file_type == FileType::SymLink && max_follow_times > 0 {
             if file_type == FileType::SymLink && max_follow_times > 0 {
                 let mut content = [0u8; 256];
                 let mut content = [0u8; 256];
                 // 读取符号链接
                 // 读取符号链接
-
+                // TODO:We need to clarify which interfaces require private data and which do not
                 let len = inode.read_at(
                 let len = inode.read_at(
                     0,
                     0,
                     256,
                     256,

+ 239 - 17
kernel/src/filesystem/vfs/mount.rs

@@ -38,6 +38,164 @@ use super::{
     IndexNode, InodeId, Magic, PollableInode, SuperBlock,
     IndexNode, InodeId, Magic, PollableInode, SuperBlock,
 };
 };
 
 
+bitflags! {
+    /// Mount flags for filesystem independent mount options
+    /// These flags correspond to the MS_* constants in Linux
+    ///
+    /// Reference: https://code.dragonos.org.cn/xref/linux-6.6.21/include/uapi/linux/mount.h#13
+    pub struct MountFlags: u32 {
+        /// Mount read-only (MS_RDONLY)
+        const RDONLY = 1;
+        /// Ignore suid and sgid bits (MS_NOSUID)
+        const NOSUID = 2;
+        /// Disallow access to device special files (MS_NODEV)
+        const NODEV = 4;
+        /// Disallow program execution (MS_NOEXEC)
+        const NOEXEC = 8;
+        /// Writes are synced at once (MS_SYNCHRONOUS)
+        const SYNCHRONOUS = 16;
+        /// Alter flags of a mounted FS (MS_REMOUNT)
+        const REMOUNT = 32;
+        /// Allow mandatory locks on an FS (MS_MANDLOCK)
+        const MANDLOCK = 64;
+        /// Directory modifications are synchronous (MS_DIRSYNC)
+        const DIRSYNC = 128;
+        /// Do not follow symlinks (MS_NOSYMFOLLOW)
+        const NOSYMFOLLOW = 256;
+        /// Do not update access times (MS_NOATIME)
+        const NOATIME = 1024;
+        /// Do not update directory access times (MS_NODIRATIME)
+        const NODIRATIME = 2048;
+        /// Bind mount (MS_BIND)
+        const BIND = 4096;
+        /// Move mount (MS_MOVE)
+        const MOVE = 8192;
+        /// Recursive mount (MS_REC)
+        const REC = 16384;
+        /// Silent mount (MS_SILENT, deprecated MS_VERBOSE)
+        const SILENT = 32768;
+        /// VFS does not apply the umask (MS_POSIXACL)
+        const POSIXACL = 1 << 16;
+        /// Change to unbindable (MS_UNBINDABLE)
+        const UNBINDABLE = 1 << 17;
+        /// Change to private (MS_PRIVATE)
+        const PRIVATE = 1 << 18;
+        /// Change to slave (MS_SLAVE)
+        const SLAVE = 1 << 19;
+        /// Change to shared (MS_SHARED)
+        const SHARED = 1 << 20;
+        /// Update atime relative to mtime/ctime (MS_RELATIME)
+        const RELATIME = 1 << 21;
+        /// This is a kern_mount call (MS_KERNMOUNT)
+        const KERNMOUNT = 1 << 22;
+        /// Update inode I_version field (MS_I_VERSION)
+        const I_VERSION = 1 << 23;
+        /// Always perform atime updates (MS_STRICTATIME)
+        const STRICTATIME = 1 << 24;
+        /// Update the on-disk [acm]times lazily (MS_LAZYTIME)
+        const LAZYTIME = 1 << 25;
+        /// This is a submount (MS_SUBMOUNT)
+        const SUBMOUNT = 1 << 26;
+        /// Do not allow remote locking (MS_NOREMOTELOCK)
+        const NOREMOTELOCK = 1 << 27;
+        /// Do not perform security checks (MS_NOSEC)
+        const NOSEC = 1 << 28;
+        /// This mount has been created by the kernel (MS_BORN)
+        const BORN = 1 << 29;
+        /// This mount is active (MS_ACTIVE)
+        const ACTIVE = 1 << 30;
+        /// Mount flags not allowed from userspace (MS_NOUSER)
+        const NOUSER = 1 << 31;
+
+        /// Superblock flags that can be altered by MS_REMOUNT
+        const RMT_MASK = MountFlags::RDONLY.bits() |
+            MountFlags::SYNCHRONOUS.bits() |
+            MountFlags::MANDLOCK.bits() |
+            MountFlags::I_VERSION.bits() |
+            MountFlags::LAZYTIME.bits();
+    }
+}
+
+impl MountFlags {
+    /// Convert mount flags to a comma-separated string representation
+    ///
+    /// This function converts MountFlags to a string format similar to /proc/mounts,
+    /// such as "rw,nosuid,nodev,noexec,relatime".
+    ///
+    /// # Returns
+    ///
+    /// A String containing the mount options in comma-separated format.
+    #[inline(never)]
+    pub fn options_string(&self) -> String {
+        let mut options = Vec::new();
+
+        // Check read/write flag
+        if self.contains(MountFlags::RDONLY) {
+            options.push("ro");
+        } else {
+            options.push("rw");
+        }
+
+        // Check other flags
+        if self.contains(MountFlags::NOSUID) {
+            options.push("nosuid");
+        }
+        if self.contains(MountFlags::NODEV) {
+            options.push("nodev");
+        }
+        if self.contains(MountFlags::NOEXEC) {
+            options.push("noexec");
+        }
+        if self.contains(MountFlags::SYNCHRONOUS) {
+            options.push("sync");
+        }
+        if self.contains(MountFlags::MANDLOCK) {
+            options.push("mand");
+        }
+        if self.contains(MountFlags::DIRSYNC) {
+            options.push("dirsync");
+        }
+        if self.contains(MountFlags::NOSYMFOLLOW) {
+            options.push("nosymfollow");
+        }
+        if self.contains(MountFlags::NOATIME) {
+            options.push("noatime");
+        }
+        if self.contains(MountFlags::NODIRATIME) {
+            options.push("nodiratime");
+        }
+        if self.contains(MountFlags::RELATIME) {
+            options.push("relatime");
+        }
+        if self.contains(MountFlags::STRICTATIME) {
+            options.push("strictatime");
+        }
+        if self.contains(MountFlags::LAZYTIME) {
+            options.push("lazytime");
+        }
+
+        // Mount propagation flags
+        if self.contains(MountFlags::UNBINDABLE) {
+            options.push("unbindable");
+        }
+        if self.contains(MountFlags::PRIVATE) {
+            options.push("private");
+        }
+        if self.contains(MountFlags::SLAVE) {
+            options.push("slave");
+        }
+        if self.contains(MountFlags::SHARED) {
+            options.push("shared");
+        }
+
+        // Internal flags (typically not shown in /proc/mounts)
+        // We'll skip flags like BIND, MOVE, REC, REMOUNT, etc. as they're
+        // not typically displayed in mount options
+
+        options.join(",")
+    }
+}
+
 // MountId类型
 // MountId类型
 int_like!(MountId, usize);
 int_like!(MountId, usize);
 
 
@@ -66,13 +224,15 @@ pub struct MountFS {
     /// 用来存储InodeID->挂载点的MountFS的B树
     /// 用来存储InodeID->挂载点的MountFS的B树
     mountpoints: SpinLock<BTreeMap<InodeId, Arc<MountFS>>>,
     mountpoints: SpinLock<BTreeMap<InodeId, Arc<MountFS>>>,
     /// 当前文件系统挂载到的那个挂载点的Inode
     /// 当前文件系统挂载到的那个挂载点的Inode
-    self_mountpoint: Option<Arc<MountFSInode>>,
+    self_mountpoint: RwLock<Option<Arc<MountFSInode>>>,
     /// 指向当前MountFS的弱引用
     /// 指向当前MountFS的弱引用
     self_ref: Weak<MountFS>,
     self_ref: Weak<MountFS>,
 
 
     namespace: Lazy<Weak<MntNamespace>>,
     namespace: Lazy<Weak<MntNamespace>>,
     propagation: Arc<MountPropagation>,
     propagation: Arc<MountPropagation>,
     mount_id: MountId,
     mount_id: MountId,
+
+    mount_flags: MountFlags,
 }
 }
 
 
 impl Debug for MountFS {
 impl Debug for MountFS {
@@ -101,15 +261,17 @@ impl MountFS {
         self_mountpoint: Option<Arc<MountFSInode>>,
         self_mountpoint: Option<Arc<MountFSInode>>,
         propagation: Arc<MountPropagation>,
         propagation: Arc<MountPropagation>,
         mnt_ns: Option<&Arc<MntNamespace>>,
         mnt_ns: Option<&Arc<MntNamespace>>,
+        mount_flags: MountFlags,
     ) -> Arc<Self> {
     ) -> Arc<Self> {
         let result = Arc::new_cyclic(|self_ref| MountFS {
         let result = Arc::new_cyclic(|self_ref| MountFS {
             inner_filesystem,
             inner_filesystem,
             mountpoints: SpinLock::new(BTreeMap::new()),
             mountpoints: SpinLock::new(BTreeMap::new()),
-            self_mountpoint,
+            self_mountpoint: RwLock::new(self_mountpoint),
             self_ref: self_ref.clone(),
             self_ref: self_ref.clone(),
             namespace: Lazy::new(),
             namespace: Lazy::new(),
             propagation,
             propagation,
             mount_id: MountId::alloc(),
             mount_id: MountId::alloc(),
+            mount_flags,
         });
         });
 
 
         if let Some(mnt_ns) = mnt_ns {
         if let Some(mnt_ns) = mnt_ns {
@@ -119,6 +281,10 @@ impl MountFS {
         result
         result
     }
     }
 
 
+    pub fn mount_flags(&self) -> MountFlags {
+        self.mount_flags
+    }
+
     pub fn propagation(&self) -> Arc<MountPropagation> {
     pub fn propagation(&self) -> Arc<MountPropagation> {
         self.propagation.clone()
         self.propagation.clone()
     }
     }
@@ -127,6 +293,15 @@ impl MountFS {
         self.namespace.init(namespace);
         self.namespace.init(namespace);
     }
     }
 
 
+    pub fn fs_type(&self) -> &str {
+        self.inner_filesystem.name()
+    }
+
+    #[inline(never)]
+    pub fn self_mountpoint(&self) -> Option<Arc<MountFSInode>> {
+        self.self_mountpoint.read().as_ref().cloned()
+    }
+
     /// @brief 用Arc指针包裹MountFS对象。
     /// @brief 用Arc指针包裹MountFS对象。
     /// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针
     /// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针
     /// 本函数只应在构造器中被调用
     /// 本函数只应在构造器中被调用
@@ -168,10 +343,14 @@ impl MountFS {
     /// # Errors
     /// # Errors
     /// 如果当前文件系统是根文件系统,那么将会返回`EINVAL`
     /// 如果当前文件系统是根文件系统,那么将会返回`EINVAL`
     pub fn umount(&self) -> Result<Arc<MountFS>, SystemError> {
     pub fn umount(&self) -> Result<Arc<MountFS>, SystemError> {
-        self.self_mountpoint
-            .as_ref()
+        let r = self
+            .self_mountpoint()
             .ok_or(SystemError::EINVAL)?
             .ok_or(SystemError::EINVAL)?
-            .do_umount()
+            .do_umount();
+
+        self.self_mountpoint.write().take();
+
+        return r;
     }
     }
 }
 }
 
 
@@ -244,7 +423,7 @@ impl MountFSInode {
     pub(super) fn do_parent(&self) -> Result<Arc<MountFSInode>, SystemError> {
     pub(super) fn do_parent(&self) -> Result<Arc<MountFSInode>, SystemError> {
         if self.is_mountpoint_root()? {
         if self.is_mountpoint_root()? {
             // 当前inode是它所在的文件系统的root inode
             // 当前inode是它所在的文件系统的root inode
-            match &self.mount_fs.self_mountpoint {
+            match self.mount_fs.self_mountpoint() {
                 Some(inode) => {
                 Some(inode) => {
                     let inner_inode = inode.parent()?;
                     let inner_inode = inode.parent()?;
                     return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
                     return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
@@ -281,14 +460,36 @@ impl MountFSInode {
             .ok_or(SystemError::ENOENT);
             .ok_or(SystemError::ENOENT);
     }
     }
 
 
+    #[inline(never)]
     fn do_absolute_path(&self) -> Result<String, SystemError> {
     fn do_absolute_path(&self) -> Result<String, SystemError> {
-        let mut path_parts = Vec::new();
         let mut current = self.self_ref.upgrade().unwrap();
         let mut current = self.self_ref.upgrade().unwrap();
+
+        // For special inode, we can directly get the absolute path
+        if let Ok(p) = current.inner_inode.absolute_path() {
+            return Ok(p);
+        }
+
+        let mut path_parts = Vec::new();
         let root_inode = ProcessManager::current_mntns().root_inode();
         let root_inode = ProcessManager::current_mntns().root_inode();
         let inode_id = root_inode.metadata()?.inode_id;
         let inode_id = root_inode.metadata()?.inode_id;
         while current.metadata()?.inode_id != inode_id {
         while current.metadata()?.inode_id != inode_id {
             let name = current.dname()?;
             let name = current.dname()?;
             path_parts.push(name.0);
             path_parts.push(name.0);
+
+            // 防循环检查:如果路径深度超过1024,抛出警告
+            if path_parts.len() > 1024 {
+                #[inline(never)]
+                fn __log_warn(root: usize, cur: usize) {
+                    log::warn!(
+                        "Path depth exceeds 1024, possible infinite loop. root: {}, cur: {}",
+                        root,
+                        cur
+                    );
+                }
+                __log_warn(inode_id.data(), current.metadata().unwrap().inode_id.data());
+                return Err(SystemError::ELOOP);
+            }
+
             current = current.do_parent()?;
             current = current.do_parent()?;
         }
         }
 
 
@@ -318,7 +519,7 @@ impl IndexNode for MountFSInode {
     }
     }
 
 
     fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
     fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
-        return self.inner_inode.close(data);
+        self.inner_inode.close(data)
     }
     }
 
 
     fn create_with_data(
     fn create_with_data(
@@ -508,7 +709,11 @@ impl IndexNode for MountFSInode {
         return self.inner_inode.list();
         return self.inner_inode.list();
     }
     }
 
 
-    fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> {
+    fn mount(
+        &self,
+        fs: Arc<dyn FileSystem>,
+        mount_flags: MountFlags,
+    ) -> Result<Arc<MountFS>, SystemError> {
         let metadata = self.inner_inode.metadata()?;
         let metadata = self.inner_inode.metadata()?;
         if metadata.file_type != FileType::Dir {
         if metadata.file_type != FileType::Dir {
             return Err(SystemError::ENOTDIR);
             return Err(SystemError::ENOTDIR);
@@ -530,6 +735,7 @@ impl IndexNode for MountFSInode {
             Some(self.self_ref.upgrade().unwrap()),
             Some(self.self_ref.upgrade().unwrap()),
             MountPropagation::new_private(), // 暂时不支持传播,后续会补充完善挂载传播性
             MountPropagation::new_private(), // 暂时不支持传播,后续会补充完善挂载传播性
             Some(&ProcessManager::current_mntns()),
             Some(&ProcessManager::current_mntns()),
+            mount_flags,
         );
         );
 
 
         self.mount_fs
         self.mount_fs
@@ -559,9 +765,11 @@ impl IndexNode for MountFSInode {
             .mountpoints
             .mountpoints
             .lock()
             .lock()
             .insert(metadata.inode_id, new_mount_fs.clone());
             .insert(metadata.inode_id, new_mount_fs.clone());
-
-        // MOUNT_LIST().remove(from.absolute_path()?);
-        // MOUNT_LIST().insert(self.absolute_path()?, new_mount_fs.clone());
+        // 更新当前挂载点的self_mountpoint
+        new_mount_fs
+            .self_mountpoint
+            .write()
+            .replace(self.self_ref.upgrade().unwrap());
         return Ok(new_mount_fs);
         return Ok(new_mount_fs);
     }
     }
 
 
@@ -602,7 +810,7 @@ impl IndexNode for MountFSInode {
     /// 在默认情况下,性能非常差!!!
     /// 在默认情况下,性能非常差!!!
     fn dname(&self) -> Result<DName, SystemError> {
     fn dname(&self) -> Result<DName, SystemError> {
         if self.is_mountpoint_root()? {
         if self.is_mountpoint_root()? {
-            if let Some(inode) = &self.mount_fs.self_mountpoint {
+            if let Some(inode) = self.mount_fs.self_mountpoint() {
                 return inode.inner_inode.dname();
                 return inode.inner_inode.dname();
             }
             }
         }
         }
@@ -620,11 +828,19 @@ impl IndexNode for MountFSInode {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
         self.inner_inode.as_pollable_inode()
         self.inner_inode.as_pollable_inode()
     }
     }
+
+    fn read_sync(&self, offset: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
+        self.inner_inode.read_sync(offset, buf)
+    }
+
+    fn write_sync(&self, offset: usize, buf: &[u8]) -> Result<usize, SystemError> {
+        self.inner_inode.write_sync(offset, buf)
+    }
 }
 }
 
 
 impl FileSystem for MountFS {
 impl FileSystem for MountFS {
     fn root_inode(&self) -> Arc<dyn IndexNode> {
     fn root_inode(&self) -> Arc<dyn IndexNode> {
-        match &self.self_mountpoint {
+        match self.self_mountpoint() {
             Some(inode) => return inode.mount_fs.root_inode(),
             Some(inode) => return inode.mount_fs.root_inode(),
             // 当前文件系统是rootfs
             // 当前文件系统是rootfs
             None => self.mountpoint_root_inode(),
             None => self.mountpoint_root_inode(),
@@ -772,14 +988,14 @@ impl MountList {
     pub fn get_mount_point<T: AsRef<str>>(
     pub fn get_mount_point<T: AsRef<str>>(
         &self,
         &self,
         path: T,
         path: T,
-    ) -> Option<(String, String, Arc<MountFS>)> {
+    ) -> Option<(Arc<MountPath>, String, Arc<MountFS>)> {
         self.mounts
         self.mounts
             .upgradeable_read()
             .upgradeable_read()
             .iter()
             .iter()
             .filter_map(|(key, fs)| {
             .filter_map(|(key, fs)| {
                 let strkey = key.as_str();
                 let strkey = key.as_str();
                 if let Some(rest) = path.as_ref().strip_prefix(strkey) {
                 if let Some(rest) = path.as_ref().strip_prefix(strkey) {
-                    return Some((strkey.to_string(), rest.to_string(), fs.clone()));
+                    return Some((key.clone(), rest.to_string(), fs.clone()));
                 }
                 }
                 None
                 None
             })
             })
@@ -803,6 +1019,11 @@ impl MountList {
     pub fn remove<T: Into<MountPath>>(&self, path: T) -> Option<Arc<MountFS>> {
     pub fn remove<T: Into<MountPath>>(&self, path: T) -> Option<Arc<MountFS>> {
         self.mounts.write().remove(&path.into())
         self.mounts.write().remove(&path.into())
     }
     }
+
+    /// # clone_inner - 克隆内部挂载点列表
+    pub fn clone_inner(&self) -> HashMap<Arc<MountPath>, Arc<MountFS>> {
+        self.mounts.read().clone()
+    }
 }
 }
 
 
 impl Debug for MountList {
 impl Debug for MountList {
@@ -843,6 +1064,7 @@ pub fn is_mountpoint_root(inode: &Arc<dyn IndexNode>) -> bool {
 pub fn do_mount_mkdir(
 pub fn do_mount_mkdir(
     fs: Arc<dyn FileSystem>,
     fs: Arc<dyn FileSystem>,
     mount_point: &str,
     mount_point: &str,
+    mount_flags: MountFlags,
 ) -> Result<Arc<MountFS>, SystemError> {
 ) -> Result<Arc<MountFS>, SystemError> {
     let inode = do_mkdir_at(
     let inode = do_mkdir_at(
         AtFlags::AT_FDCWD.bits(),
         AtFlags::AT_FDCWD.bits(),
@@ -855,5 +1077,5 @@ pub fn do_mount_mkdir(
             return Err(SystemError::EBUSY);
             return Err(SystemError::EBUSY);
         }
         }
     }
     }
-    return inode.mount(fs);
+    return inode.mount(fs, mount_flags);
 }
 }

+ 2 - 8
kernel/src/filesystem/vfs/open.rs

@@ -170,14 +170,8 @@ fn do_sys_openat2(
     let path = path.trim();
     let path = path.trim();
 
 
     let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
     let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
-    let inode: Result<Arc<dyn IndexNode>, SystemError> = inode_begin.lookup_follow_symlink(
-        &path,
-        if follow_symlink {
-            VFS_MAX_FOLLOW_SYMLINK_TIMES
-        } else {
-            0
-        },
-    );
+    let inode =
+        inode_begin.lookup_follow_symlink2(&path, VFS_MAX_FOLLOW_SYMLINK_TIMES, follow_symlink);
 
 
     let root_inode = ProcessManager::current_mntns().root_inode();
     let root_inode = ProcessManager::current_mntns().root_inode();
     let inode: Arc<dyn IndexNode> = match inode {
     let inode: Arc<dyn IndexNode> = match inode {

+ 3 - 0
kernel/src/filesystem/vfs/syscall/mod.rs

@@ -52,7 +52,9 @@ mod sys_epoll_ctl;
 mod sys_epoll_pwait;
 mod sys_epoll_pwait;
 
 
 pub mod symlink_utils;
 pub mod symlink_utils;
+mod sys_fsync;
 pub mod sys_mount;
 pub mod sys_mount;
+mod sys_sync;
 pub mod sys_umount2;
 pub mod sys_umount2;
 
 
 #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
 #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
@@ -70,6 +72,7 @@ mod sys_dup2;
 mod sys_epoll_create;
 mod sys_epoll_create;
 #[cfg(target_arch = "x86_64")]
 #[cfg(target_arch = "x86_64")]
 mod sys_epoll_wait;
 mod sys_epoll_wait;
+
 #[cfg(target_arch = "x86_64")]
 #[cfg(target_arch = "x86_64")]
 mod sys_futimesat;
 mod sys_futimesat;
 #[cfg(target_arch = "x86_64")]
 #[cfg(target_arch = "x86_64")]

+ 42 - 0
kernel/src/filesystem/vfs/syscall/sys_fsync.rs

@@ -0,0 +1,42 @@
+use alloc::string::ToString;
+
+use alloc::vec::Vec;
+
+use crate::{
+    arch::{interrupt::TrapFrame, syscall::nr::SYS_FSYNC},
+    syscall::table::{FormattedSyscallParam, Syscall},
+};
+
+/// synchronize a file's in-core state with storagedevice.
+///
+/// See https://man7.org/linux/man-pages/man2/fsync.2.html
+pub struct SysFsyncHandle;
+
+impl Syscall for SysFsyncHandle {
+    fn num_args(&self) -> usize {
+        1
+    }
+
+    fn handle(
+        &self,
+        args: &[usize],
+        _frame: &mut TrapFrame,
+    ) -> Result<usize, system_error::SystemError> {
+        let fd = args[0] as i32;
+        let binding = crate::process::ProcessManager::current_pcb().fd_table();
+        let fd_table_guard = binding.read();
+        let file = fd_table_guard
+            .get_file_by_fd(fd)
+            .ok_or(system_error::SystemError::EBADF)?;
+        drop(fd_table_guard);
+        let inode = file.inode();
+        inode.sync()?;
+        Ok(0)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![FormattedSyscallParam::new("fd", args[0].to_string())]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_FSYNC, SysFsyncHandle);

+ 21 - 9
kernel/src/filesystem/vfs/syscall/sys_mount.rs

@@ -3,8 +3,8 @@
 use crate::{
 use crate::{
     arch::{interrupt::TrapFrame, syscall::nr::SYS_MOUNT},
     arch::{interrupt::TrapFrame, syscall::nr::SYS_MOUNT},
     filesystem::vfs::{
     filesystem::vfs::{
-        fcntl::AtFlags, produce_fs, utils::user_path_at, FileSystem, MountFS, MAX_PATHLEN,
-        VFS_MAX_FOLLOW_SYMLINK_TIMES,
+        fcntl::AtFlags, mount::MountFlags, produce_fs, utils::user_path_at, FileSystem, MountFS,
+        MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES,
     },
     },
     process::ProcessManager,
     process::ProcessManager,
     syscall::{
     syscall::{
@@ -25,7 +25,7 @@ use system_error::SystemError;
 /// - source       挂载设备(目前只支持ext4格式的硬盘)
 /// - source       挂载设备(目前只支持ext4格式的硬盘)
 /// - target       挂载目录
 /// - target       挂载目录
 /// - filesystemtype   文件系统
 /// - filesystemtype   文件系统
-/// - mountflags     挂载选项(暂未实现)
+/// - mountflags     挂载选项
 /// - data        带数据挂载
 /// - data        带数据挂载
 ///
 ///
 /// ## 返回值
 /// ## 返回值
@@ -43,6 +43,9 @@ impl Syscall for SysMountHandle {
         let filesystemtype = Self::filesystemtype(args);
         let filesystemtype = Self::filesystemtype(args);
         let data = Self::raw_data(args);
         let data = Self::raw_data(args);
         let source = Self::source(args);
         let source = Self::source(args);
+        let mount_flags = Self::mountflags(args);
+
+        let mount_flags = MountFlags::from_bits_truncate(mount_flags);
 
 
         let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?
         let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?
             .into_string()
             .into_string()
@@ -57,12 +60,14 @@ impl Syscall for SysMountHandle {
 
 
         let fs = produce_fs(fstype_str, data, source)?;
         let fs = produce_fs(fstype_str, data, source)?;
 
 
-        do_mount(fs, &target)?;
+        do_mount(fs, &target, mount_flags)?;
 
 
         return Ok(0);
         return Ok(0);
     }
     }
 
 
     fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
     fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        let flags = MountFlags::from_bits(Self::mountflags(args)).unwrap_or(MountFlags::empty());
+
         vec![
         vec![
             FormattedSyscallParam::new("source", format!("{:#x}", Self::source(args) as usize)),
             FormattedSyscallParam::new("source", format!("{:#x}", Self::source(args) as usize)),
             FormattedSyscallParam::new("target", format!("{:#x}", Self::target(args) as usize)),
             FormattedSyscallParam::new("target", format!("{:#x}", Self::target(args) as usize)),
@@ -70,7 +75,10 @@ impl Syscall for SysMountHandle {
                 "filesystem type",
                 "filesystem type",
                 format!("{:#x}", Self::filesystemtype(args) as usize),
                 format!("{:#x}", Self::filesystemtype(args) as usize),
             ),
             ),
-            FormattedSyscallParam::new("mountflags", format!("{:#x}", Self::mountflags(args))),
+            FormattedSyscallParam::new(
+                "mountflags",
+                format!("{:?} ({:#x})", flags, Self::mountflags(args)),
+            ),
             FormattedSyscallParam::new("data", format!("{:?}", Self::raw_data(args))),
             FormattedSyscallParam::new("data", format!("{:?}", Self::raw_data(args))),
         ]
         ]
     }
     }
@@ -86,8 +94,8 @@ impl SysMountHandle {
     fn filesystemtype(args: &[usize]) -> *const u8 {
     fn filesystemtype(args: &[usize]) -> *const u8 {
         args[2] as *const u8
         args[2] as *const u8
     }
     }
-    fn mountflags(args: &[usize]) -> usize {
-        args[3]
+    fn mountflags(args: &[usize]) -> u32 {
+        args[3] as u32
     }
     }
     fn raw_data(args: &[usize]) -> Option<&'static str> {
     fn raw_data(args: &[usize]) -> Option<&'static str> {
         let raw = args[4] as *const u8;
         let raw = args[4] as *const u8;
@@ -120,7 +128,11 @@ syscall_table_macros::declare_syscall!(SYS_MOUNT, SysMountHandle);
 ///
 ///
 /// - `Ok(Arc<MountFS>)`: 挂载成功后返回挂载的文件系统。
 /// - `Ok(Arc<MountFS>)`: 挂载成功后返回挂载的文件系统。
 /// - `Err(SystemError)`: 挂载失败时返回错误。
 /// - `Err(SystemError)`: 挂载失败时返回错误。
-pub fn do_mount(fs: Arc<dyn FileSystem>, mount_point: &str) -> Result<Arc<MountFS>, SystemError> {
+pub fn do_mount(
+    fs: Arc<dyn FileSystem>,
+    mount_point: &str,
+    mount_flags: MountFlags,
+) -> Result<Arc<MountFS>, SystemError> {
     let (current_node, rest_path) = user_path_at(
     let (current_node, rest_path) = user_path_at(
         &ProcessManager::current_pcb(),
         &ProcessManager::current_pcb(),
         AtFlags::AT_FDCWD.bits(),
         AtFlags::AT_FDCWD.bits(),
@@ -134,5 +146,5 @@ pub fn do_mount(fs: Arc<dyn FileSystem>, mount_point: &str) -> Result<Arc<MountF
         }
         }
     }
     }
     // 移至IndexNode.mount()来记录
     // 移至IndexNode.mount()来记录
-    return inode.mount(fs);
+    return inode.mount(fs, mount_flags);
 }
 }

+ 69 - 0
kernel/src/filesystem/vfs/syscall/sys_sync.rs

@@ -0,0 +1,69 @@
+use alloc::string::ToString;
+
+use alloc::vec::Vec;
+
+use crate::{
+    arch::{
+        interrupt::TrapFrame,
+        syscall::nr::{SYS_SYNC, SYS_SYNCFS},
+    },
+    mm::page::page_reclaimer_lock_irqsave,
+    syscall::table::{FormattedSyscallParam, Syscall},
+};
+
+/// sync() causes all pending modifications to filesystem metadata and
+/// cached file data to be written to the underlying filesystems.
+///
+/// See https://man7.org/linux/man-pages/man2/sync.2.html
+pub struct SysSyncHandle;
+
+impl Syscall for SysSyncHandle {
+    fn num_args(&self) -> usize {
+        0
+    }
+
+    fn handle(
+        &self,
+        _args: &[usize],
+        _frame: &mut TrapFrame,
+    ) -> Result<usize, system_error::SystemError> {
+        page_reclaimer_lock_irqsave().flush_dirty_pages();
+        Ok(0)
+    }
+
+    fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![FormattedSyscallParam::new(
+            "No arguments",
+            "sync()".to_string(),
+        )]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_SYNC, SysSyncHandle);
+
+/// syncfs() is like sync(), but synchronizes just the filesystem
+/// containing file referred to by the open file descriptor fd.
+pub struct SysSyncFsHandle;
+
+impl Syscall for SysSyncFsHandle {
+    fn num_args(&self) -> usize {
+        1
+    }
+
+    fn handle(
+        &self,
+        _args: &[usize],
+        _frame: &mut TrapFrame,
+    ) -> Result<usize, system_error::SystemError> {
+        // TODO: now, we ignore the fd and sync all filesystems.
+        // In the future, we should sync only the filesystem of the given fd.
+        page_reclaimer_lock_irqsave().flush_dirty_pages();
+        Ok(0)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![FormattedSyscallParam::new("fd", format!("{}", args[0]))]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_SYNCFS, SysSyncHandle);

+ 11 - 1
kernel/src/filesystem/vfs/vcore.rs

@@ -9,6 +9,7 @@ use crate::{
     driver::base::block::{gendisk::GenDisk, manager::block_dev_manager},
     driver::base::block::{gendisk::GenDisk, manager::block_dev_manager},
     filesystem::{
     filesystem::{
         devfs::devfs_init,
         devfs::devfs_init,
+        devpts::devpts_init,
         fat::fs::FATFileSystem,
         fat::fs::FATFileSystem,
         procfs::procfs_init,
         procfs::procfs_init,
         sysfs::sysfs_init,
         sysfs::sysfs_init,
@@ -68,7 +69,13 @@ fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemE
     let current_mntns = ProcessManager::current_mntns();
     let current_mntns = ProcessManager::current_mntns();
     let old_root_inode = current_mntns.root_inode();
     let old_root_inode = current_mntns.root_inode();
     let old_mntfs = current_mntns.root_mntfs().clone();
     let old_mntfs = current_mntns.root_mntfs().clone();
-    let new_fs = MountFS::new(new_fs, None, old_mntfs.propagation(), Some(&current_mntns));
+    let new_fs = MountFS::new(
+        new_fs,
+        None,
+        old_mntfs.propagation(),
+        Some(&current_mntns),
+        old_mntfs.mount_flags(),
+    );
 
 
     // 获取新的根文件系统的根节点的引用
     // 获取新的根文件系统的根节点的引用
     let new_root_inode = new_fs.root_inode();
     let new_root_inode = new_fs.root_inode();
@@ -95,6 +102,9 @@ fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemE
         current_mntns.force_change_root_mountfs(new_fs);
         current_mntns.force_change_root_mountfs(new_fs);
     }
     }
 
 
+    // WARNING: mount devpts after devfs has been mounted,
+    devpts_init().expect("Failed to initialize devpts");
+
     info!("VFS: Migrate filesystems done!");
     info!("VFS: Migrate filesystems done!");
 
 
     return Ok(());
     return Ok(());

+ 5 - 2
kernel/src/init/initial_kthread.rs

@@ -45,6 +45,11 @@ fn kernel_init() -> Result<(), SystemError> {
         .ok();
         .ok();
 
 
     mount_root_fs().expect("Failed to mount root fs");
     mount_root_fs().expect("Failed to mount root fs");
+
+    // WARNING: We must keep `mount_root_fs` before stdio_init,
+    // because `migrate_virtual_filesystem` will change the root directory of the file system.
+    stdio_init().expect("Failed to initialize stdio");
+
     e1000e_init();
     e1000e_init();
     net_init().unwrap_or_else(|err| {
     net_init().unwrap_or_else(|err| {
         error!("Failed to initialize network: {:?}", err);
         error!("Failed to initialize network: {:?}", err);
@@ -60,9 +65,7 @@ fn kenrel_init_freeable() -> Result<(), SystemError> {
     do_initcalls().unwrap_or_else(|err| {
     do_initcalls().unwrap_or_else(|err| {
         panic!("Failed to initialize subsystems: {:?}", err);
         panic!("Failed to initialize subsystems: {:?}", err);
     });
     });
-    stdio_init().expect("Failed to initialize stdio");
     smp_init();
     smp_init();
-
     return Ok(());
     return Ok(());
 }
 }
 
 

+ 6 - 2
kernel/src/ipc/pipe.rs

@@ -1,5 +1,3 @@
-use core::sync::atomic::compiler_fence;
-
 use crate::{
 use crate::{
     arch::ipc::signal::{SigCode, Signal},
     arch::ipc::signal::{SigCode, Signal},
     filesystem::{
     filesystem::{
@@ -17,6 +15,8 @@ use crate::{
     sched::SchedMode,
     sched::SchedMode,
     time::PosixTimeSpec,
     time::PosixTimeSpec,
 };
 };
+use alloc::string::String;
+use core::sync::atomic::compiler_fence;
 
 
 use alloc::{
 use alloc::{
     collections::LinkedList,
     collections::LinkedList,
@@ -513,4 +513,8 @@ impl IndexNode for LockedPipeInode {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
         Ok(self)
         Ok(self)
     }
     }
+
+    fn absolute_path(&self) -> Result<String, SystemError> {
+        Ok(String::from("pipe"))
+    }
 }
 }

+ 100 - 45
kernel/src/libs/futex/futex.rs

@@ -2,7 +2,10 @@ use alloc::{
     collections::LinkedList,
     collections::LinkedList,
     sync::{Arc, Weak},
     sync::{Arc, Weak},
 };
 };
-use core::hash::{Hash, Hasher};
+use core::{
+    hash::{Hash, Hasher},
+    ops::{Deref, DerefMut},
+};
 use core::{
 use core::{
     intrinsics::{likely, unlikely},
     intrinsics::{likely, unlikely},
     mem,
     mem,
@@ -646,17 +649,39 @@ impl Futex {
 const ROBUST_LIST_LIMIT: isize = 2048;
 const ROBUST_LIST_LIMIT: isize = 2048;
 
 
 #[derive(Debug, Copy, Clone)]
 #[derive(Debug, Copy, Clone)]
-pub struct RobustList {
+#[repr(C)]
+struct PosixRobustList {
     next: VirtAddr,
     next: VirtAddr,
 }
 }
 
 
 #[derive(Debug, Copy, Clone)]
 #[derive(Debug, Copy, Clone)]
-pub struct RobustListHead {
-    list: RobustList,
+#[repr(C)]
+pub struct PosixRobustListHead {
+    list: PosixRobustList,
     futex_offset: isize,
     futex_offset: isize,
     list_op_pending: VirtAddr,
     list_op_pending: VirtAddr,
 }
 }
 
 
+#[derive(Debug, Copy, Clone)]
+pub struct RobustListHead {
+    pub posix: PosixRobustListHead,
+    pub uaddr: VirtAddr,
+}
+
+impl Deref for RobustListHead {
+    type Target = PosixRobustListHead;
+
+    fn deref(&self) -> &Self::Target {
+        &self.posix
+    }
+}
+
+impl DerefMut for RobustListHead {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.posix
+    }
+}
+
 impl RobustListHead {
 impl RobustListHead {
     /// # 获得futex的用户空间地址
     /// # 获得futex的用户空间地址
     pub fn futex_uaddr(&self, entry: VirtAddr) -> VirtAddr {
     pub fn futex_uaddr(&self, entry: VirtAddr) -> VirtAddr {
@@ -677,18 +702,21 @@ impl RobustListHead {
     /// - head_uaddr:robust list head用户空间地址
     /// - head_uaddr:robust list head用户空间地址
     /// - len:robust list head的长度    
     /// - len:robust list head的长度    
     pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
     pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
-        let robust_list_head_len = mem::size_of::<RobustListHead>();
+        let robust_list_head_len = mem::size_of::<PosixRobustListHead>();
         if unlikely(len != robust_list_head_len) {
         if unlikely(len != robust_list_head_len) {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
         }
         }
 
 
         let user_buffer_reader = UserBufferReader::new(
         let user_buffer_reader = UserBufferReader::new(
-            head_uaddr.as_ptr::<RobustListHead>(),
-            mem::size_of::<RobustListHead>(),
+            head_uaddr.as_ptr::<PosixRobustListHead>(),
+            mem::size_of::<PosixRobustListHead>(),
             true,
             true,
         )?;
         )?;
-        let robust_list_head = *user_buffer_reader.read_one_from_user::<RobustListHead>(0)?;
-
+        let robust_list_head = *user_buffer_reader.read_one_from_user::<PosixRobustListHead>(0)?;
+        let robust_list_head = RobustListHead {
+            posix: robust_list_head,
+            uaddr: head_uaddr,
+        };
         // 向内核注册robust list
         // 向内核注册robust list
         ProcessManager::current_pcb().set_robust_list(Some(robust_list_head));
         ProcessManager::current_pcb().set_robust_list(Some(robust_list_head));
 
 
@@ -726,11 +754,11 @@ impl RobustListHead {
             core::mem::size_of::<usize>(),
             core::mem::size_of::<usize>(),
             true,
             true,
         )?;
         )?;
-        user_writer.copy_one_to_user(&mem::size_of::<RobustListHead>(), 0)?;
+        user_writer.copy_one_to_user(&mem::size_of::<PosixRobustListHead>(), 0)?;
         // 将head拷贝到用户空间head
         // 将head拷贝到用户空间head
         let mut user_writer = UserBufferWriter::new(
         let mut user_writer = UserBufferWriter::new(
-            head_uaddr.as_ptr::<RobustListHead>(),
-            mem::size_of::<RobustListHead>(),
+            head_uaddr.as_ptr::<PosixRobustListHead>(),
+            mem::size_of::<PosixRobustListHead>(),
             true,
             true,
         )?;
         )?;
         user_writer.copy_one_to_user(&robust_list_head, 0)?;
         user_writer.copy_one_to_user(&robust_list_head, 0)?;
@@ -750,6 +778,7 @@ impl RobustListHead {
                 return;
                 return;
             }
             }
         };
         };
+
         // 遍历当前进程/线程的robust list
         // 遍历当前进程/线程的robust list
         for futex_uaddr in head.futexes() {
         for futex_uaddr in head.futexes() {
             let ret = Self::handle_futex_death(futex_uaddr, pcb.raw_pid().into() as u32);
             let ret = Self::handle_futex_death(futex_uaddr, pcb.raw_pid().into() as u32);
@@ -765,21 +794,50 @@ impl RobustListHead {
         return FutexIterator::new(self);
         return FutexIterator::new(self);
     }
     }
 
 
+    /// # 安全地从用户空间读取任意类型的值,如果地址无效则返回None
+    pub fn safe_read<T>(addr: VirtAddr) -> Option<UserBufferReader<'static>> {
+        // 检查地址是否有效
+        if addr.is_null() {
+            return None;
+        }
+
+        let size = core::mem::size_of::<T>();
+        return UserBufferReader::new_checked(addr.as_ptr::<T>(), size, true).ok();
+    }
+
+    /// # 安全地从用户空间读取u32值,如果地址无效则返回None
+    fn safe_read_u32(addr: VirtAddr) -> Option<u32> {
+        Self::safe_read::<u32>(addr)
+            .and_then(|reader| reader.read_one_from_user::<u32>(0).ok().cloned())
+    }
+
+    /// # 安全地向用户空间写入u32值,如果地址无效则返回false
+    fn safe_write_u32(addr: VirtAddr, val: u32) -> bool {
+        // 尝试写入
+        let mut writer = match UserBufferWriter::new_checked(
+            addr.as_ptr::<u32>(),
+            core::mem::size_of::<u32>(),
+            true,
+        ) {
+            Ok(w) => w,
+            Err(_) => return false,
+        };
+
+        writer.copy_one_to_user(&val, 0).is_ok()
+    }
+
     /// # 处理进程即将死亡时,进程已经持有的futex,唤醒其他等待该futex的线程
     /// # 处理进程即将死亡时,进程已经持有的futex,唤醒其他等待该futex的线程
     /// ## 参数
     /// ## 参数
     /// - futex_uaddr:futex的用户空间地址
     /// - futex_uaddr:futex的用户空间地址
     /// - pid: 当前进程/线程的pid
     /// - pid: 当前进程/线程的pid
     fn handle_futex_death(futex_uaddr: VirtAddr, pid: u32) -> Result<usize, SystemError> {
     fn handle_futex_death(futex_uaddr: VirtAddr, pid: u32) -> Result<usize, SystemError> {
-        let futex_val = {
-            if futex_uaddr.is_null() {
-                return Err(SystemError::EINVAL);
+        // 安全地读取futex值
+        let futex_val = match Self::safe_read_u32(futex_uaddr) {
+            Some(val) => val,
+            None => {
+                // 地址无效,跳过此futex
+                return Ok(0);
             }
             }
-            let user_buffer_reader = UserBufferReader::new(
-                futex_uaddr.as_ptr::<u32>(),
-                core::mem::size_of::<u32>(),
-                true,
-            )?;
-            *user_buffer_reader.read_one_from_user::<u32>(0)?
         };
         };
 
 
         let mut uval = futex_val;
         let mut uval = futex_val;
@@ -793,21 +851,18 @@ impl RobustListHead {
             // 判断是否有FUTEX_WAITERS和标记FUTEX_OWNER_DIED
             // 判断是否有FUTEX_WAITERS和标记FUTEX_OWNER_DIED
             let mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
             let mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
 
 
-            // 读取用户空间目前的futex字段,判断在此之前futex是否有被修改
-            let user_buffer_reader = UserBufferReader::new(
-                futex_uaddr.as_ptr::<u32>(),
-                core::mem::size_of::<u32>(),
-                true,
-            )?;
-            let nval = *user_buffer_reader.read_one_from_user::<u32>(0)?;
+            // 安全地读取当前值
+            let nval = match Self::safe_read_u32(futex_uaddr) {
+                Some(val) => val,
+                None => break, // 读取失败,退出循环
+            };
+
             if nval != mval {
             if nval != mval {
                 uval = nval;
                 uval = nval;
-                let mut user_buffer_writer = UserBufferWriter::new(
-                    futex_uaddr.as_ptr::<u32>(),
-                    core::mem::size_of::<u32>(),
-                    true,
-                )?;
-                user_buffer_writer.copy_one_to_user(&mval, 0)?;
+                // 安全地写入新值
+                if !Self::safe_write_u32(futex_uaddr, mval) {
+                    continue; // 写入失败,继续下一次循环
+                }
                 continue;
                 continue;
             }
             }
 
 
@@ -815,7 +870,8 @@ impl RobustListHead {
             if nval & FUTEX_WAITERS != 0 {
             if nval & FUTEX_WAITERS != 0 {
                 let mut flags = FutexFlag::FLAGS_MATCH_NONE;
                 let mut flags = FutexFlag::FLAGS_MATCH_NONE;
                 flags.insert(FutexFlag::FLAGS_SHARED);
                 flags.insert(FutexFlag::FLAGS_SHARED);
-                Futex::futex_wake(futex_uaddr, flags, 1, FUTEX_BITSET_MATCH_ANY)?;
+                // 唤醒操作可能会失败,但不影响流程
+                let _ = Futex::futex_wake(futex_uaddr, flags, 1, FUTEX_BITSET_MATCH_ANY);
             }
             }
             break;
             break;
         }
         }
@@ -852,7 +908,7 @@ impl Iterator for FutexIterator<'_> {
             return None;
             return None;
         }
         }
 
 
-        while self.entry.data() != &self.robust_list_head.list as *const RobustList as usize {
+        while self.entry.data() != self.robust_list_head.uaddr.data() {
             if self.count == ROBUST_LIST_LIMIT {
             if self.count == ROBUST_LIST_LIMIT {
                 break;
                 break;
             }
             }
@@ -867,15 +923,14 @@ impl Iterator for FutexIterator<'_> {
                 None
                 None
             };
             };
 
 
-            let user_buffer_reader = UserBufferReader::new(
-                self.entry.as_ptr::<RobustList>(),
-                mem::size_of::<RobustList>(),
-                true,
-            )
-            .ok()?;
-            let next_entry = user_buffer_reader
-                .read_one_from_user::<RobustList>(0)
-                .ok()?;
+            // 安全地读取下一个entry
+            let next_entry =
+                RobustListHead::safe_read::<PosixRobustList>(self.entry).and_then(|reader| {
+                    reader
+                        .read_one_from_user::<PosixRobustList>(0)
+                        .ok()
+                        .cloned()
+                })?;
 
 
             self.entry = next_entry.next;
             self.entry = next_entry.next;
 
 

+ 7 - 4
kernel/src/libs/futex/syscall.rs

@@ -1,15 +1,13 @@
 use system_error::SystemError;
 use system_error::SystemError;
 
 
 use crate::{
 use crate::{
+    libs::futex::futex::RobustListHead,
     mm::{verify_area, VirtAddr},
     mm::{verify_area, VirtAddr},
     syscall::Syscall,
     syscall::Syscall,
     time::PosixTimeSpec,
     time::PosixTimeSpec,
 };
 };
 
 
-use super::{
-    constant::*,
-    futex::{Futex, RobustListHead},
-};
+use super::{constant::*, futex::Futex};
 
 
 impl Syscall {
 impl Syscall {
     pub fn do_futex(
     pub fn do_futex(
@@ -117,6 +115,11 @@ impl Syscall {
         verify_area(head_uaddr, core::mem::size_of::<u32>())?;
         verify_area(head_uaddr, core::mem::size_of::<u32>())?;
 
 
         let ret = RobustListHead::set_robust_list(head_uaddr, len);
         let ret = RobustListHead::set_robust_list(head_uaddr, len);
+        // log::debug!(
+        //     "set_robust_list: pid: {} head_uaddr={:?}",
+        //     crate::process::ProcessManager::current_pid(),
+        //     head_uaddr
+        // );
         return ret;
         return ret;
     }
     }
 
 

+ 2 - 2
kernel/src/mm/no_init.rs

@@ -8,7 +8,7 @@
 //! 对于x86:
 //! 对于x86:
 //! 这里假设在内核引导文件中,已经填写了前100M的页表,其中,前50M是真实映射到内存的,后面的仅仅创建了页表,表项全部为0。
 //! 这里假设在内核引导文件中,已经填写了前100M的页表,其中,前50M是真实映射到内存的,后面的仅仅创建了页表,表项全部为0。
 
 
-use bitmap::{traits::BitMapOps, StaticBitmap};
+use bitmap::{static_bitmap, traits::BitMapOps, StaticBitmap};
 
 
 use crate::{
 use crate::{
     libs::spinlock::SpinLock,
     libs::spinlock::SpinLock,
@@ -45,7 +45,7 @@ impl EarlyRemapPage {
 #[repr(C)]
 #[repr(C)]
 pub struct EarlyIoRemapPages {
 pub struct EarlyIoRemapPages {
     pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM],
     pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM],
-    bmp: StaticBitmap<{ Self::EARLY_REMAP_PAGES_NUM }>,
+    bmp: static_bitmap!(Self::EARLY_REMAP_PAGES_NUM),
 }
 }
 
 
 impl EarlyIoRemapPages {
 impl EarlyIoRemapPages {

+ 4 - 0
kernel/src/perf/bpf.rs

@@ -322,6 +322,10 @@ impl IndexNode for BpfPerfEvent {
     fn page_cache(&self) -> Option<Arc<PageCache>> {
     fn page_cache(&self) -> Option<Arc<PageCache>> {
         Some(self.data.lock().page_cache.clone())
         Some(self.data.lock().page_cache.clone())
     }
     }
+
+    fn absolute_path(&self) -> core::result::Result<String, SystemError> {
+        Ok(String::from("bpf_perf_event"))
+    }
 }
 }
 
 
 impl PerfEventOps for BpfPerfEvent {
 impl PerfEventOps for BpfPerfEvent {

+ 4 - 0
kernel/src/perf/kprobe.rs

@@ -134,6 +134,10 @@ impl IndexNode for KprobePerfEvent {
     fn page_cache(&self) -> Option<Arc<PageCache>> {
     fn page_cache(&self) -> Option<Arc<PageCache>> {
         None
         None
     }
     }
+
+    fn absolute_path(&self) -> core::result::Result<String, SystemError> {
+        Ok(String::from("kprobe_perf_event"))
+    }
 }
 }
 
 
 impl PerfEventOps for KprobePerfEvent {
 impl PerfEventOps for KprobePerfEvent {

+ 4 - 0
kernel/src/perf/mod.rs

@@ -282,6 +282,10 @@ impl IndexNode for PerfEventInode {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode> {
     fn as_pollable_inode(&self) -> Result<&dyn PollableInode> {
         Ok(self)
         Ok(self)
     }
     }
+
+    fn absolute_path(&self) -> core::result::Result<String, SystemError> {
+        Ok(String::from("perf_event"))
+    }
 }
 }
 
 
 impl PollableInode for PerfEventInode {
 impl PollableInode for PerfEventInode {

+ 8 - 0
kernel/src/perf/tracepoint.rs

@@ -73,6 +73,14 @@ impl IndexNode for TracepointPerfEvent {
     fn page_cache(&self) -> Option<Arc<PageCache>> {
     fn page_cache(&self) -> Option<Arc<PageCache>> {
         None
         None
     }
     }
+
+    fn absolute_path(&self) -> core::result::Result<String, SystemError> {
+        Ok(format!(
+            "tracepoint: {}:{}",
+            self.tp.system(),
+            self.tp.name()
+        ))
+    }
 }
 }
 
 
 pub struct TracePointPerfCallBack(BasicPerfEbpfCallBack);
 pub struct TracePointPerfCallBack(BasicPerfEbpfCallBack);

+ 13 - 0
kernel/src/process/cred.rs

@@ -43,6 +43,8 @@ pub struct Cred {
     pub euid: Kuid,
     pub euid: Kuid,
     /// 进程有效的gid
     /// 进程有效的gid
     pub egid: Kgid,
     pub egid: Kgid,
+    /// supplementary groups
+    pub groups: Vec<Kgid>,
     /// UID for VFS ops
     /// UID for VFS ops
     pub fsuid: Kuid,
     pub fsuid: Kuid,
     /// GID for VFS ops
     /// GID for VFS ops
@@ -74,6 +76,7 @@ impl Cred {
             egid: GLOBAL_ROOT_GID,
             egid: GLOBAL_ROOT_GID,
             fsuid: GLOBAL_ROOT_UID,
             fsuid: GLOBAL_ROOT_UID,
             fsgid: GLOBAL_ROOT_GID,
             fsgid: GLOBAL_ROOT_GID,
+            groups: Vec::new(),
             cap_inheritable: CAPFlags::CAP_EMPTY_SET,
             cap_inheritable: CAPFlags::CAP_EMPTY_SET,
             cap_permitted: CAPFlags::CAP_FULL_SET,
             cap_permitted: CAPFlags::CAP_FULL_SET,
             cap_effective: CAPFlags::CAP_FULL_SET,
             cap_effective: CAPFlags::CAP_FULL_SET,
@@ -179,6 +182,16 @@ impl Cred {
     pub fn setfsgid(&mut self, fsgid: usize) {
     pub fn setfsgid(&mut self, fsgid: usize) {
         self.fsgid.0 = fsgid;
         self.fsgid.0 = fsgid;
     }
     }
+
+    /// Set supplementary groups
+    pub fn setgroups(&mut self, groups: Vec<Kgid>) {
+        self.groups = groups;
+    }
+
+    /// Get supplementary groups
+    pub fn getgroups(&self) -> &Vec<Kgid> {
+        &self.groups
+    }
 }
 }
 
 
 #[derive(Debug, Clone, PartialEq, Eq, Default)]
 #[derive(Debug, Clone, PartialEq, Eq, Default)]

+ 0 - 1
kernel/src/process/fork.rs

@@ -339,7 +339,6 @@ impl ProcessManager {
         clone_args: KernelCloneArgs,
         clone_args: KernelCloneArgs,
         current_trapframe: &TrapFrame,
         current_trapframe: &TrapFrame,
     ) -> Result<(), SystemError> {
     ) -> Result<(), SystemError> {
-        // log::debug!("fork: clone_flags: {:?}", clone_args.flags);
         let clone_flags = clone_args.flags;
         let clone_flags = clone_args.flags;
         // 不允许与不同namespace的进程共享根目录
         // 不允许与不同namespace的进程共享根目录
 
 

+ 1 - 4
kernel/src/process/mod.rs

@@ -452,9 +452,6 @@ impl ProcessManager {
 
 
             // 进行进程退出后的工作
             // 进行进程退出后的工作
             let thread = pcb.thread.write_irqsave();
             let thread = pcb.thread.write_irqsave();
-            if let Some(addr) = thread.set_child_tid {
-                unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
-            }
 
 
             if let Some(addr) = thread.clear_child_tid {
             if let Some(addr) = thread.clear_child_tid {
                 if Arc::strong_count(&pcb.basic().user_vm().expect("User VM Not found")) > 1 {
                 if Arc::strong_count(&pcb.basic().user_vm().expect("User VM Not found")) > 1 {
@@ -467,9 +464,9 @@ impl ProcessManager {
                 }
                 }
                 unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
                 unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
             }
             }
+            compiler_fence(Ordering::SeqCst);
 
 
             RobustListHead::exit_robust_list(pcb.clone());
             RobustListHead::exit_robust_list(pcb.clone());
-
             // 如果是vfork出来的进程,则需要处理completion
             // 如果是vfork出来的进程,则需要处理completion
             if thread.vfork_done.is_some() {
             if thread.vfork_done.is_some() {
                 thread.vfork_done.as_ref().unwrap().complete_all();
                 thread.vfork_done.as_ref().unwrap().complete_all();

+ 25 - 4
kernel/src/process/namespace/mnt.rs

@@ -1,6 +1,6 @@
 use crate::{
 use crate::{
     filesystem::vfs::{
     filesystem::vfs::{
-        mount::{MountList, MountPath},
+        mount::{MountFlags, MountList, MountPath},
         FileSystem, IndexNode, MountFS,
         FileSystem, IndexNode, MountFS,
     },
     },
     libs::{once::Once, spinlock::SpinLock},
     libs::{once::Once, spinlock::SpinLock},
@@ -62,7 +62,13 @@ impl MntNamespace {
         let mount_list = MountList::new();
         let mount_list = MountList::new();
 
 
         let ramfs = crate::filesystem::ramfs::RamFS::new();
         let ramfs = crate::filesystem::ramfs::RamFS::new();
-        let ramfs = MountFS::new(ramfs, None, MountPropagation::new_private(), None);
+        let ramfs = MountFS::new(
+            ramfs,
+            None,
+            MountPropagation::new_private(),
+            None,
+            MountFlags::empty(),
+        );
 
 
         let result = Arc::new_cyclic(|self_ref| Self {
         let result = Arc::new_cyclic(|self_ref| Self {
             ns_common: NsCommon::new(0, NamespaceType::Mount),
             ns_common: NsCommon::new(0, NamespaceType::Mount),
@@ -75,7 +81,11 @@ impl MntNamespace {
                 _dead: false,
                 _dead: false,
             }),
             }),
         });
         });
+
         ramfs.set_namespace(Arc::downgrade(&result));
         ramfs.set_namespace(Arc::downgrade(&result));
+        result
+            .add_mount(Arc::new(MountPath::from("/")), ramfs)
+            .expect("Failed to add root mount");
 
 
         return result;
         return result;
     }
     }
@@ -84,9 +94,13 @@ impl MntNamespace {
     ///
     ///
     /// 本方法仅供dragonos初始化时使用
     /// 本方法仅供dragonos初始化时使用
     pub unsafe fn force_change_root_mountfs(&self, new_root: Arc<MountFS>) {
     pub unsafe fn force_change_root_mountfs(&self, new_root: Arc<MountFS>) {
+        let inner_guard = self.inner.lock();
         let ptr = self as *const Self as *mut Self;
         let ptr = self as *const Self as *mut Self;
         let self_mut = (ptr).as_mut().unwrap();
         let self_mut = (ptr).as_mut().unwrap();
-        self_mut.root_mountfs = new_root;
+        self_mut.root_mountfs = new_root.clone();
+        let (path, _, _) = inner_guard.mount_list.get_mount_point("/").unwrap();
+
+        inner_guard.mount_list.insert(path, new_root);
     }
     }
 
 
     /// Creates a copy of the mount namespace for process cloning.
     /// Creates a copy of the mount namespace for process cloning.
@@ -136,11 +150,18 @@ impl MntNamespace {
         return Ok(());
         return Ok(());
     }
     }
 
 
+    pub fn mount_list(&self) -> Arc<MountList> {
+        self.inner.lock().mount_list.clone()
+    }
+
     pub fn remove_mount(&self, mount_path: &str) -> Option<Arc<MountFS>> {
     pub fn remove_mount(&self, mount_path: &str) -> Option<Arc<MountFS>> {
         return self.inner.lock().mount_list.remove(mount_path);
         return self.inner.lock().mount_list.remove(mount_path);
     }
     }
 
 
-    pub fn get_mount_point(&self, mount_point: &str) -> Option<(String, String, Arc<MountFS>)> {
+    pub fn get_mount_point(
+        &self,
+        mount_point: &str,
+    ) -> Option<(Arc<MountPath>, String, Arc<MountFS>)> {
         self.inner.lock().mount_list.get_mount_point(mount_point)
         self.inner.lock().mount_list.get_mount_point(mount_point)
     }
     }
 }
 }

+ 1 - 0
kernel/src/process/namespace/mod.rs

@@ -1,6 +1,7 @@
 pub mod mnt;
 pub mod mnt;
 pub mod nsproxy;
 pub mod nsproxy;
 pub mod pid_namespace;
 pub mod pid_namespace;
+pub mod unshare;
 pub mod user_namespace;
 pub mod user_namespace;
 
 
 use nsproxy::NsCommon;
 use nsproxy::NsCommon;

+ 11 - 3
kernel/src/process/namespace/nsproxy.rs

@@ -23,8 +23,9 @@ pub struct NsProxy {
     pub pid_ns_for_children: Arc<PidNamespace>,
     pub pid_ns_for_children: Arc<PidNamespace>,
     /// mount namespace(挂载命名空间)
     /// mount namespace(挂载命名空间)
     pub mnt_ns: Arc<MntNamespace>,
     pub mnt_ns: Arc<MntNamespace>,
+    // 注意,user_ns 存储在cred,不存储在nsproxy
+
     // 其他namespace(为未来扩展预留)
     // 其他namespace(为未来扩展预留)
-    // pub user_ns: Option<Arc<UserNamespace>>,
     // pub net_ns: Option<Arc<NetNamespace>>,
     // pub net_ns: Option<Arc<NetNamespace>>,
     // pub ipc_ns: Option<Arc<IpcNamespace>>,
     // pub ipc_ns: Option<Arc<IpcNamespace>>,
     // pub uts_ns: Option<Arc<UtsNamespace>>,
     // pub uts_ns: Option<Arc<UtsNamespace>>,
@@ -58,6 +59,13 @@ impl NsProxy {
     pub fn mnt_namespace(&self) -> &Arc<MntNamespace> {
     pub fn mnt_namespace(&self) -> &Arc<MntNamespace> {
         &self.mnt_ns
         &self.mnt_ns
     }
     }
+
+    pub fn clone_inner(&self) -> Self {
+        Self {
+            pid_ns_for_children: self.pid_ns_for_children.clone(),
+            mnt_ns: self.mnt_ns.clone(),
+        }
+    }
 }
 }
 
 
 impl ProcessManager {
 impl ProcessManager {
@@ -123,7 +131,7 @@ impl ProcessManager {
 /// 返回新创建的nsproxy。调用者需要负责正确的加锁并将其附加到进程上。
 /// 返回新创建的nsproxy。调用者需要负责正确的加锁并将其附加到进程上。
 ///
 ///
 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/nsproxy.c?r=&mo=3770&fi=151#67
 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/nsproxy.c?r=&mo=3770&fi=151#67
-fn create_new_namespaces(
+pub(super) fn create_new_namespaces(
     clone_flags: &CloneFlags,
     clone_flags: &CloneFlags,
     pcb: &Arc<ProcessControlBlock>,
     pcb: &Arc<ProcessControlBlock>,
     user_ns: Arc<UserNamespace>,
     user_ns: Arc<UserNamespace>,
@@ -133,7 +141,7 @@ fn create_new_namespaces(
         .pid_ns_for_children
         .pid_ns_for_children
         .copy_pid_ns(clone_flags, user_ns.clone())?;
         .copy_pid_ns(clone_flags, user_ns.clone())?;
 
 
-    let mnt_ns = nsproxy.mnt_ns.copy_mnt_ns(clone_flags, user_ns)?;
+    let mnt_ns = nsproxy.mnt_ns.copy_mnt_ns(clone_flags, user_ns.clone())?;
     let result = NsProxy {
     let result = NsProxy {
         pid_ns_for_children,
         pid_ns_for_children,
         mnt_ns,
         mnt_ns,

+ 4 - 1
kernel/src/process/namespace/pid_namespace.rs

@@ -124,7 +124,10 @@ impl PidNamespace {
     }
     }
 
 
     /// https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/pid_namespace.c#72
     /// https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/pid_namespace.c#72
-    fn create_pid_namespace(&self, user_ns: Arc<UserNamespace>) -> Result<Arc<Self>, SystemError> {
+    pub(super) fn create_pid_namespace(
+        &self,
+        user_ns: Arc<UserNamespace>,
+    ) -> Result<Arc<Self>, SystemError> {
         let level = self.level() + 1;
         let level = self.level() + 1;
         if !self.user_ns.is_ancestor_of(&user_ns) {
         if !self.user_ns.is_ancestor_of(&user_ns) {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);

+ 110 - 0
kernel/src/process/namespace/unshare.rs

@@ -0,0 +1,110 @@
+use alloc::sync::Arc;
+
+use system_error::SystemError;
+
+use crate::process::{
+    fork::CloneFlags,
+    namespace::nsproxy::{switch_task_namespaces, NsProxy},
+    ProcessManager,
+};
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/fork.c#3385
+pub fn ksys_unshare(flags: CloneFlags) -> Result<(), SystemError> {
+    // 检查 unshare 标志位
+    check_unshare_flags(flags)?;
+
+    let new_nsproxy = unshare_nsproxy_namespaces(flags)?;
+
+    if let Some(new_nsproxy) = new_nsproxy {
+        // 更新当前进程的 Namespace 代理
+        let current_pcb = ProcessManager::current_pcb();
+        switch_task_namespaces(&current_pcb, new_nsproxy)?;
+    }
+    // TODO: 处理其他命名空间的 unshare 操作
+    // CLONE_NEWNS, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, CLONE_VM, CLONE_THREAD, CLONE_SYSVSEM,
+    // CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWUSER, CLONE_NEWNET, CLONE_NEWCGROUP, CLONE_NEWTIME
+
+    Ok(())
+}
+
+#[inline(never)]
+fn unshare_nsproxy_namespaces(
+    unshare_flags: CloneFlags,
+) -> Result<Option<Arc<NsProxy>>, SystemError> {
+    const ALL_VALID_FLAGS: CloneFlags = CloneFlags::from_bits_truncate(
+        CloneFlags::CLONE_NEWNS.bits()
+            | CloneFlags::CLONE_NEWUTS.bits()
+            | CloneFlags::CLONE_NEWIPC.bits()
+            | CloneFlags::CLONE_NEWNET.bits()
+            | CloneFlags::CLONE_NEWPID.bits()
+            | CloneFlags::CLONE_NEWCGROUP.bits()
+            | CloneFlags::CLONE_NEWTIME.bits(),
+    );
+    if !unshare_flags.intersects(ALL_VALID_FLAGS) {
+        return Ok(None);
+    }
+
+    // 获取当前进程的 PCB
+    let current_pcb = ProcessManager::current_pcb();
+    let user_ns = ProcessManager::current_user_ns();
+
+    let nsproxy = super::nsproxy::create_new_namespaces(&unshare_flags, &current_pcb, user_ns)?;
+    return Ok(Some(nsproxy));
+}
+
+#[inline(never)]
+fn check_unshare_flags(flags: CloneFlags) -> Result<(), SystemError> {
+    // 检查无效的标志位
+    const ALL_VALID_FLAGS: CloneFlags = CloneFlags::from_bits_truncate(
+        CloneFlags::CLONE_NEWNS.bits()
+            | CloneFlags::CLONE_NEWCGROUP.bits()
+            | CloneFlags::CLONE_NEWUTS.bits()
+            | CloneFlags::CLONE_NEWIPC.bits()
+            | CloneFlags::CLONE_NEWUSER.bits()
+            | CloneFlags::CLONE_NEWPID.bits()
+            | CloneFlags::CLONE_NEWNET.bits()
+            | CloneFlags::CLONE_NEWTIME.bits()
+            | CloneFlags::CLONE_FS.bits()
+            | CloneFlags::CLONE_FILES.bits()
+            | CloneFlags::CLONE_SIGHAND.bits()
+            | CloneFlags::CLONE_VM.bits()
+            | CloneFlags::CLONE_THREAD.bits()
+            | CloneFlags::CLONE_SYSVSEM.bits(),
+    );
+
+    if flags.intersects(!ALL_VALID_FLAGS) {
+        return Err(SystemError::EINVAL);
+    }
+
+    let current_pcb = ProcessManager::current_pcb();
+
+    // 如果请求 unshare CLONE_THREAD, CLONE_SIGHAND 或 CLONE_VM,
+    // 必须确保线程组为空(即只有一个线程)
+    if flags.intersects(CloneFlags::CLONE_THREAD | CloneFlags::CLONE_SIGHAND | CloneFlags::CLONE_VM)
+        && !current_pcb.threads_read_irqsave().thread_group_empty()
+    {
+        return Err(SystemError::EINVAL);
+    }
+
+    // 如果请求 unshare CLONE_SIGHAND 或 CLONE_VM,
+    // 必须确保信号处理结构的引用计数为1
+    if flags.intersects(CloneFlags::CLONE_SIGHAND | CloneFlags::CLONE_VM) {
+        let sighand_count = current_pcb
+            .sig_struct_irqsave()
+            .cnt
+            .load(core::sync::atomic::Ordering::SeqCst);
+        if sighand_count > 1 {
+            return Err(SystemError::EINVAL);
+        }
+    }
+
+    // TODO: 如果请求 unshare CLONE_VM,
+    // 必须确保当前进程是单线程进程
+    // if flags.contains(CloneFlags::CLONE_VM) {
+    //     if !current_pcb.thread_group_empty() {
+    //         return Err(SystemError::EINVAL);
+    //     }
+    // }
+
+    Ok(())
+}

+ 12 - 0
kernel/src/process/namespace/user_namespace.rs

@@ -3,6 +3,7 @@ use core::cmp::Ordering;
 use core::fmt::Debug;
 use core::fmt::Debug;
 
 
 use crate::libs::spinlock::SpinLock;
 use crate::libs::spinlock::SpinLock;
+use crate::process::ProcessManager;
 
 
 use super::nsproxy::NsCommon;
 use super::nsproxy::NsCommon;
 use super::{NamespaceOps, NamespaceType};
 use super::{NamespaceOps, NamespaceType};
@@ -86,3 +87,14 @@ impl Debug for UserNamespace {
         f.debug_struct("UserNamespace").finish()
         f.debug_struct("UserNamespace").finish()
     }
     }
 }
 }
+
+impl ProcessManager {
+    /// 获取当前进程的 user_ns
+    pub fn current_user_ns() -> Arc<UserNamespace> {
+        if Self::initialized() {
+            ProcessManager::current_pcb().cred().user_ns.clone()
+        } else {
+            INIT_USER_NAMESPACE.clone()
+        }
+    }
+}

+ 2 - 0
kernel/src/process/syscall/mod.rs

@@ -13,6 +13,7 @@ mod sys_getppid;
 mod sys_getsid;
 mod sys_getsid;
 mod sys_gettid;
 mod sys_gettid;
 mod sys_getuid;
 mod sys_getuid;
+mod sys_groups;
 mod sys_prlimit64;
 mod sys_prlimit64;
 mod sys_set_tid_address;
 mod sys_set_tid_address;
 mod sys_setfsgid;
 mod sys_setfsgid;
@@ -24,6 +25,7 @@ mod sys_setresuid;
 mod sys_setsid;
 mod sys_setsid;
 mod sys_setuid;
 mod sys_setuid;
 mod sys_uname;
 mod sys_uname;
+mod sys_unshare;
 mod sys_wait4;
 mod sys_wait4;
 
 
 #[cfg(target_arch = "x86_64")]
 #[cfg(target_arch = "x86_64")]

+ 93 - 0
kernel/src/process/syscall/sys_groups.rs

@@ -0,0 +1,93 @@
+use crate::arch::interrupt::TrapFrame;
+use crate::arch::syscall::nr::SYS_GETGROUPS;
+use crate::arch::syscall::nr::SYS_SETGROUPS;
+use crate::process::cred::Cred;
+use crate::process::cred::Kgid;
+use crate::process::ProcessManager;
+use crate::syscall::table::FormattedSyscallParam;
+use crate::syscall::table::Syscall;
+use crate::syscall::user_access::UserBufferReader;
+use crate::syscall::user_access::UserBufferWriter;
+use alloc::vec::Vec;
+use system_error::SystemError;
+
+const NGROUPS_MAX: usize = 65536;
+
+/// See https://man7.org/linux/man-pages/man2/setgroups.2.html
+pub struct SysGetGroups;
+
+impl Syscall for SysGetGroups {
+    fn num_args(&self) -> usize {
+        2
+    }
+
+    fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let cred = pcb.cred.lock();
+        let size = args[0];
+        if size == 0 {
+            return Ok(cred.getgroups().len());
+        }
+        if size < cred.getgroups().len() || size > NGROUPS_MAX {
+            return Err(SystemError::EINVAL);
+        }
+        let mut user_buffer = UserBufferWriter::new(
+            args[1] as *mut Kgid,
+            size * core::mem::size_of::<Kgid>(),
+            true,
+        )?;
+        user_buffer.copy_to_user(cred.getgroups(), 0)?;
+        Ok(size)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("size", format!("{}", args[0])),
+            FormattedSyscallParam::new("list", format!("{:#x}", args[1])),
+        ]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_GETGROUPS, SysGetGroups);
+
+pub struct SysSetGroups;
+
+impl Syscall for SysSetGroups {
+    fn num_args(&self) -> usize {
+        2
+    }
+
+    fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let mut cred = (**pcb.cred.lock()).clone();
+        let size = args[0];
+        if size == 0 {
+            // clear all supplementary groups
+            cred.setgroups(Vec::new());
+            return Ok(0);
+        }
+        if size > NGROUPS_MAX {
+            return Err(SystemError::EINVAL);
+        }
+        let user_buffer = UserBufferReader::new(
+            args[1] as *const Kgid,
+            size * core::mem::size_of::<Kgid>(),
+            true,
+        )?;
+        let mut groups = vec![Kgid::from(0); size];
+        user_buffer.copy_from_user(&mut groups, 0).unwrap();
+        // log::info!("set supplementary groups: {:?}", groups);
+        cred.setgroups(groups);
+        *pcb.cred.lock() = Cred::new_arc(cred);
+        Ok(0)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("size", format!("{}", args[0])),
+            FormattedSyscallParam::new("list", format!("{:#x}", args[1])),
+        ]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_SETGROUPS, SysSetGroups);

+ 44 - 0
kernel/src/process/syscall/sys_unshare.rs

@@ -0,0 +1,44 @@
+use crate::arch::interrupt::TrapFrame;
+use crate::arch::syscall::nr::SYS_UNSHARE;
+use crate::process::fork::CloneFlags;
+use crate::process::namespace::unshare::ksys_unshare;
+use crate::syscall::table::{FormattedSyscallParam, Syscall};
+use alloc::vec::Vec;
+use system_error::SystemError;
+
+pub struct SysUnshare;
+
+impl SysUnshare {
+    fn flags(args: &[usize]) -> CloneFlags {
+        CloneFlags::from_bits_truncate(args[0] as u64)
+    }
+}
+
+impl Syscall for SysUnshare {
+    fn num_args(&self) -> usize {
+        1
+    }
+
+    /// # 函数的功能
+    /// unshare系统调用允许进程将其部分执行上下文与其他进程解耦
+    ///
+    /// ## 参数
+    /// - flags: 指定要解耦的资源类型
+    ///
+    /// ## 返回值
+    /// - 成功时返回0
+    /// - 失败时返回错误码
+    fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
+        let flags = Self::flags(args);
+        ksys_unshare(flags).map(|_| 0)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![FormattedSyscallParam::new(
+            "flags",
+            format!("{:#x}", Self::flags(args).bits()),
+        )]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_UNSHARE, SysUnshare);

+ 408 - 67
kernel/src/syscall/user_access.rs

@@ -1,4 +1,4 @@
-//! 这个文件用于放置一些内核态访问用户态数据的函数
+//! This file contains functions for kernel-space access to user-space data
 
 
 use core::{
 use core::{
     mem::size_of,
     mem::size_of,
@@ -12,29 +12,30 @@ use defer::defer;
 use crate::{
 use crate::{
     arch::MMArch,
     arch::MMArch,
     mm::{verify_area, MemoryManagementArch, VirtAddr},
     mm::{verify_area, MemoryManagementArch, VirtAddr},
+    process::ProcessManager,
 };
 };
 
 
 use super::SystemError;
 use super::SystemError;
 
 
-/// 清空用户空间指定范围内的数据
+/// Clear data in the specified range of user space
 ///
 ///
-/// ## 参数
+/// ## Arguments
 ///
 ///
-/// - `dest`:用户空间的目标地址
-/// - `len`:要清空的数据长度
+/// - `dest`: Destination address in user space
+/// - `len`: Length of data to clear
 ///
 ///
-/// ## 返回值
+/// ## Returns
 ///
 ///
-/// 返回清空的数据长度
+/// Returns the length of cleared data
 ///
 ///
-/// ## 错误
+/// ## Errors
 ///
 ///
-/// - `EFAULT`:目标地址不合法
+/// - `EFAULT`: Destination address is invalid
 pub unsafe fn clear_user(dest: VirtAddr, len: usize) -> Result<usize, SystemError> {
 pub unsafe fn clear_user(dest: VirtAddr, len: usize) -> Result<usize, SystemError> {
     verify_area(dest, len).map_err(|_| SystemError::EFAULT)?;
     verify_area(dest, len).map_err(|_| SystemError::EFAULT)?;
 
 
     let p = dest.data() as *mut u8;
     let p = dest.data() as *mut u8;
-    // 清空用户空间的数据
+    // Clear user space data
     p.write_bytes(0, len);
     p.write_bytes(0, len);
     return Ok(len);
     return Ok(len);
 }
 }
@@ -52,7 +53,7 @@ pub unsafe fn copy_to_user(dest: VirtAddr, src: &[u8]) -> Result<usize, SystemEr
     return Ok(src.len());
     return Ok(src.len());
 }
 }
 
 
-/// 从用户空间拷贝数据到内核空间
+/// Copy data from user space to kernel space
 pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result<usize, SystemError> {
 pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result<usize, SystemError> {
     verify_area(src, dst.len()).map_err(|_| SystemError::EFAULT)?;
     verify_area(src, dst.len()).map_err(|_| SystemError::EFAULT)?;
 
 
@@ -63,23 +64,23 @@ pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result<usize, Sys
     return Ok(dst.len());
     return Ok(dst.len());
 }
 }
 
 
-/// 检查并从用户态拷贝一个 C 字符串。
+/// Check and copy a C string from user space.
 ///
 ///
-/// 一旦遇到非法地址,就会返回错误
+/// Returns an error when encountering an invalid address.
 ///
 ///
-/// ## 参数
+/// ## Arguments
 ///
 ///
-/// - `user`:用户态的 C 字符串指针
-/// - `max_length`:最大拷贝长度
+/// - `user`: Pointer to the C string in user space
+/// - `max_length`: Maximum copy length
 ///
 ///
-/// ## 返回值
+/// ## Returns
 ///
 ///
-/// 返回拷贝的 C 字符串
+/// Returns the copied C string
 ///
 ///
-/// ## 错误
+/// ## Errors
 ///
 ///
-/// - `EFAULT`:用户态地址不合法
-/// - `EINVAL`:字符串不是合法的 C 字符串
+/// - `EFAULT`: User space address is invalid
+/// - `EINVAL`: String is not a valid C string
 pub fn check_and_clone_cstr(
 pub fn check_and_clone_cstr(
     user: *const u8,
     user: *const u8,
     max_length: Option<usize>,
     max_length: Option<usize>,
@@ -88,7 +89,7 @@ pub fn check_and_clone_cstr(
         return Err(SystemError::EFAULT);
         return Err(SystemError::EFAULT);
     }
     }
 
 
-    // 从用户态读取,直到遇到空字符 '\0' 或者达到最大长度
+    // Read from user space until null character '\0' or maximum length is reached
     let mut buffer = Vec::new();
     let mut buffer = Vec::new();
     for i in 0.. {
     for i in 0.. {
         if max_length.is_some() && max_length.as_ref().unwrap() <= &i {
         if max_length.is_some() && max_length.as_ref().unwrap() <= &i {
@@ -111,20 +112,20 @@ pub fn check_and_clone_cstr(
     return Ok(cstr);
     return Ok(cstr);
 }
 }
 
 
-/// 检查并从用户态拷贝一个 C 字符串数组
+/// Check and copy a C string array from user space
 ///
 ///
-/// 一旦遇到空指针,就会停止拷贝. 一旦遇到非法地址,就会返回错误
-/// ## 参数
+/// Stops copying when encountering a null pointer. Returns an error when encountering an invalid address.
+/// ## Arguments
 ///
 ///
-/// - `user`:用户态的 C 字符串指针数组
+/// - `user`: Pointer array to C strings in user space
 ///
 ///
-/// ## 返回值
+/// ## Returns
 ///
 ///
-/// 返回拷贝的 C 字符串数组
+/// Returns the copied C string array
 ///
 ///
-/// ## 错误
+/// ## Errors
 ///
 ///
-/// - `EFAULT`:用户态地址不合法
+/// - `EFAULT`: User space address is invalid
 pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<CString>, SystemError> {
 pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<CString>, SystemError> {
     if user.is_null() {
     if user.is_null() {
         Ok(Vec::new())
         Ok(Vec::new())
@@ -134,7 +135,7 @@ pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<CString>
         for i in 0.. {
         for i in 0.. {
             let addr = unsafe { user.add(i) };
             let addr = unsafe { user.add(i) };
             let str_ptr: *const u8;
             let str_ptr: *const u8;
-            // 读取这个地址的值(这个值也是一个指针)
+            // Read the value at this address (which is also a pointer)
             unsafe {
             unsafe {
                 let dst = [0usize; 1];
                 let dst = [0usize; 1];
                 let mut dst = core::mem::transmute::<[usize; 1], [u8; size_of::<usize>()]>(dst);
                 let mut dst = core::mem::transmute::<[usize; 1], [u8; size_of::<usize>()]>(dst);
@@ -148,9 +149,9 @@ pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<CString>
             if str_ptr.is_null() {
             if str_ptr.is_null() {
                 break;
                 break;
             }
             }
-            // 读取这个指针指向的字符串
+            // Read the string pointed to by this pointer
             let string = check_and_clone_cstr(str_ptr, None)?;
             let string = check_and_clone_cstr(str_ptr, None)?;
-            // 将字符串放入 buffer 中
+            // Put the string into the buffer
             buffer.push(string);
             buffer.push(string);
         }
         }
         return Ok(buffer);
         return Ok(buffer);
@@ -167,14 +168,17 @@ pub struct UserBufferReader<'a> {
     buffer: &'a [u8],
     buffer: &'a [u8],
 }
 }
 
 
-#[allow(dead_code)]
 impl UserBufferReader<'_> {
 impl UserBufferReader<'_> {
-    /// 构造一个指向用户空间位置的BufferReader,为了兼容类似传入 *const u8 的情况,使用单独的泛型来进行初始化
+    /// Construct a BufferReader pointing to a user space location.
+    /// Uses a separate generic for initialization to support cases like passing *const u8.
+    ///
+    /// # Arguments
+    /// * `addr` - User space pointer
+    /// * `len` - Byte length of the buffer
+    /// * `from_user` - Whether to verify the address is from user space
     ///
     ///
-    /// @param addr 用户空间指针
-    /// @param len 缓冲区的字节长度
-    /// @param frm_user 代表是否要检验地址来自用户空间
-    /// @return 构造成功返回UserbufferReader实例,否则返回错误码
+    /// # Returns
+    /// * Returns UserBufferReader instance on success, error code otherwise
     ///
     ///
     pub fn new<U>(addr: *const U, len: usize, from_user: bool) -> Result<Self, SystemError> {
     pub fn new<U>(addr: *const U, len: usize, from_user: bool) -> Result<Self, SystemError> {
         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
@@ -185,31 +189,86 @@ impl UserBufferReader<'_> {
         });
         });
     }
     }
 
 
+    pub fn new_checked<U>(
+        addr: *const U,
+        len: usize,
+        from_user: bool,
+    ) -> Result<Self, SystemError> {
+        if !check_user_access_by_page_table(VirtAddr::new(addr as usize), len, false) {
+            return Err(SystemError::EFAULT);
+        }
+
+        return Self::new(addr, len, from_user);
+    }
+
     pub fn size(&self) -> usize {
     pub fn size(&self) -> usize {
         return self.buffer.len();
         return self.buffer.len();
     }
     }
 
 
-    /// 从用户空间读取数据(到变量中)
+    /// Read data from user space with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `offset` - Byte offset
     ///
     ///
-    /// @param offset 字节偏移量
-    /// @return 返回用户空间数据的切片(对单个结构体就返回长度为一的切片)
+    /// # Returns
+    /// * Returns a slice of user space data (returns a slice of length 1 for a single struct)
+    ///
+    /// # Errors
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn read_from_user_checked<T>(&self, offset: usize) -> Result<&[T], SystemError> {
+        return self.convert_with_offset_checked(self.buffer, offset);
+    }
+
+    /// Read data from user space (into variables)
+    ///
+    /// # Arguments
+    /// * `offset` - Byte offset
+    ///
+    /// # Returns
+    /// * Returns a slice of user space data (returns a slice of length 1 for a single struct)
     ///
     ///
     pub fn read_from_user<T>(&self, offset: usize) -> Result<&[T], SystemError> {
     pub fn read_from_user<T>(&self, offset: usize) -> Result<&[T], SystemError> {
         return self.convert_with_offset(self.buffer, offset);
         return self.convert_with_offset(self.buffer, offset);
     }
     }
-    /// 从用户空间读取一个指定偏移量的数据(到变量中)
+    /// Read one data item with specified offset from user space (into variable)
+    ///
+    /// # Arguments
+    /// * `offset` - Byte offset
+    ///
+    /// # Returns
+    /// * Returns a reference to the user space data
     ///
     ///
-    /// @param offset 字节偏移量
-    /// @return 返回用户空间数据的引用
-    ///    
     pub fn read_one_from_user<T>(&self, offset: usize) -> Result<&T, SystemError> {
     pub fn read_one_from_user<T>(&self, offset: usize) -> Result<&T, SystemError> {
         return self.convert_one_with_offset(self.buffer, offset);
         return self.convert_one_with_offset(self.buffer, offset);
     }
     }
 
 
-    /// 从用户空间拷贝数据(到指定地址中)
+    /// Read one data item from user space with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `offset` - Byte offset
+    ///
+    /// # Returns
+    /// * Returns a reference to the user space data
+    ///
+    /// # Errors
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn read_one_from_user_checked<T>(&self, offset: usize) -> Result<&T, SystemError> {
+        return self.convert_one_with_offset_checked(self.buffer, offset);
+    }
+
+    /// Copy data from user space (to specified address)
     ///
     ///
-    /// @param dst 目标地址指针
-    /// @return 拷贝成功的话返回拷贝的元素数量
+    /// # Arguments
+    /// * `dst` - Destination address pointer
+    ///
+    /// # Returns
+    /// * Returns number of elements copied on success
     ///
     ///
     pub fn copy_from_user<T: core::marker::Copy>(
     pub fn copy_from_user<T: core::marker::Copy>(
         &self,
         &self,
@@ -221,10 +280,37 @@ impl UserBufferReader<'_> {
         return Ok(dst.len());
         return Ok(dst.len());
     }
     }
 
 
-    /// 从用户空间拷贝数据(到指定地址中)
+    /// Copy data from user space with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `dst` - Destination address pointer
+    /// * `offset` - Byte offset
+    ///
+    /// # Returns
+    /// * Returns number of elements copied on success
     ///
     ///
-    /// @param dst 目标地址指针
-    /// @return 拷贝成功的话返回拷贝的元素数量
+    /// # Errors
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn copy_from_user_checked<T: core::marker::Copy>(
+        &self,
+        dst: &mut [T],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        let data = self.convert_with_offset_checked(self.buffer, offset)?;
+        dst.copy_from_slice(data);
+        return Ok(dst.len());
+    }
+
+    /// Copy one data item from user space (to specified address)
+    ///
+    /// # Arguments
+    /// * `dst` - Destination address pointer
+    ///
+    /// # Returns
+    /// * Ok(()) on success
     ///
     ///
     pub fn copy_one_from_user<T: core::marker::Copy>(
     pub fn copy_one_from_user<T: core::marker::Copy>(
         &self,
         &self,
@@ -236,16 +322,59 @@ impl UserBufferReader<'_> {
         return Ok(());
         return Ok(());
     }
     }
 
 
-    /// 把用户空间的数据转换成指定类型的切片
+    /// Copy one data item from user space with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
     ///
     ///
-    /// ## 参数
+    /// # Arguments
+    /// * `dst` - Destination address pointer
+    /// * `offset` - Byte offset
     ///
     ///
-    /// - `offset`:字节偏移量
+    /// # Returns
+    /// * Ok(()) on success
+    ///
+    /// # Errors
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn copy_one_from_user_checked<T: core::marker::Copy>(
+        &self,
+        dst: &mut T,
+        offset: usize,
+    ) -> Result<(), SystemError> {
+        let data = self.convert_one_with_offset_checked::<T>(self.buffer, offset)?;
+        dst.clone_from(data);
+        return Ok(());
+    }
+
+    /// Convert user space data to a slice of specified type
+    ///
+    /// # Arguments
+    ///
+    /// * `offset` - Byte offset
     pub fn buffer<T>(&self, offset: usize) -> Result<&[T], SystemError> {
     pub fn buffer<T>(&self, offset: usize) -> Result<&[T], SystemError> {
         self.convert_with_offset::<T>(self.buffer, offset)
         self.convert_with_offset::<T>(self.buffer, offset)
             .map_err(|_| SystemError::EINVAL)
             .map_err(|_| SystemError::EINVAL)
     }
     }
 
 
+    /// Convert user space data to a slice of specified type with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `offset` - Byte offset
+    ///
+    /// # Returns
+    /// * Returns a slice of the specified type
+    ///
+    /// # Errors
+    /// * `EINVAL` - Invalid offset or alignment
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn buffer_checked<T>(&self, offset: usize) -> Result<&[T], SystemError> {
+        self.convert_with_offset_checked(self.buffer, offset)
+            .map_err(|_| SystemError::EINVAL)
+    }
+
     fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
     fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
         if offset >= src.len() {
         if offset >= src.len() {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
@@ -264,6 +393,24 @@ impl UserBufferReader<'_> {
         return Ok(chunks);
         return Ok(chunks);
     }
     }
 
 
+    fn convert_with_offset_checked<T>(
+        &self,
+        src: &[u8],
+        offset: usize,
+    ) -> Result<&[T], SystemError> {
+        let size = src.len().saturating_sub(offset);
+        if size > 0
+            && !check_user_access_by_page_table(
+                VirtAddr::new(src.as_ptr() as usize + offset),
+                size,
+                false,
+            )
+        {
+            return Err(SystemError::EFAULT);
+        }
+        self.convert_with_offset(src, offset)
+    }
+
     fn convert_one_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&T, SystemError> {
     fn convert_one_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&T, SystemError> {
         if offset + core::mem::size_of::<T>() > src.len() {
         if offset + core::mem::size_of::<T>() > src.len() {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
@@ -274,15 +421,37 @@ impl UserBufferReader<'_> {
         let data = &chunks[0];
         let data = &chunks[0];
         return Ok(data);
         return Ok(data);
     }
     }
+
+    fn convert_one_with_offset_checked<T>(
+        &self,
+        src: &[u8],
+        offset: usize,
+    ) -> Result<&T, SystemError> {
+        let size = core::mem::size_of::<T>();
+        if offset + size > src.len() {
+            return Err(SystemError::EINVAL);
+        }
+        if !check_user_access_by_page_table(
+            VirtAddr::new(src.as_ptr() as usize + offset),
+            size,
+            false,
+        ) {
+            return Err(SystemError::EFAULT);
+        }
+        self.convert_one_with_offset(src, offset)
+    }
 }
 }
 
 
 #[allow(dead_code)]
 #[allow(dead_code)]
 impl<'a> UserBufferWriter<'a> {
 impl<'a> UserBufferWriter<'a> {
-    /// 构造一个指向用户空间位置的BufferWriter
+    /// Construct a BufferWriter pointing to a user space location
     ///
     ///
-    /// @param addr 用户空间指针
-    /// @param len 缓冲区的字节长度
-    /// @return 构造成功返回UserbufferWriter实例,否则返回错误码
+    /// # Arguments
+    /// * `addr` - User space pointer
+    /// * `len` - Byte length of the buffer
+    ///
+    /// # Returns
+    /// * Returns UserBufferWriter instance on success, error code otherwise
     ///
     ///
     pub fn new<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
     pub fn new<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
@@ -293,15 +462,26 @@ impl<'a> UserBufferWriter<'a> {
         });
         });
     }
     }
 
 
+    pub fn new_checked<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
+        if !check_user_access_by_page_table(VirtAddr::new(addr as usize), len, true) {
+            return Err(SystemError::EFAULT);
+        }
+
+        return Self::new(addr, len, from_user);
+    }
+
     pub fn size(&self) -> usize {
     pub fn size(&self) -> usize {
         return self.buffer.len();
         return self.buffer.len();
     }
     }
 
 
-    /// 从指定地址写入数据到用户空间
+    /// Write data from specified address to user space
     ///
     ///
-    /// @param data 要写入的数据地址
-    /// @param offset 在UserBuffer中的字节偏移量
-    /// @return 返回写入元素的数量
+    /// # Arguments
+    /// * `src` - Source data address
+    /// * `offset` - Byte offset in UserBuffer
+    ///
+    /// # Returns
+    /// * Returns number of elements written
     ///
     ///
     pub fn copy_to_user<T: core::marker::Copy>(
     pub fn copy_to_user<T: core::marker::Copy>(
         &'a mut self,
         &'a mut self,
@@ -313,11 +493,38 @@ impl<'a> UserBufferWriter<'a> {
         return Ok(src.len());
         return Ok(src.len());
     }
     }
 
 
-    /// 从指定地址写入一个数据到用户空间
+    /// Write data from specified address to user space with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `src` - Source data address
+    /// * `offset` - Byte offset in UserBuffer
+    ///
+    /// # Returns
+    /// * Returns number of elements written
+    ///
+    /// # Errors
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn copy_to_user_checked<T: core::marker::Copy>(
+        &'a mut self,
+        src: &[T],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        let dst = Self::convert_with_offset_checked(self.buffer, offset)?;
+        dst.copy_from_slice(src);
+        return Ok(src.len());
+    }
+
+    /// Write one data item from specified address to user space
     ///
     ///
-    /// @param data 要写入的数据地址
-    /// @param offset 在UserBuffer中的字节偏移量
-    /// @return Ok/Err
+    /// # Arguments
+    /// * `src` - Source data address
+    /// * `offset` - Byte offset in UserBuffer
+    ///
+    /// # Returns
+    /// * Ok(()) on success
     ///
     ///
     pub fn copy_one_to_user<T: core::marker::Copy>(
     pub fn copy_one_to_user<T: core::marker::Copy>(
         &'a mut self,
         &'a mut self,
@@ -329,10 +536,52 @@ impl<'a> UserBufferWriter<'a> {
         return Ok(());
         return Ok(());
     }
     }
 
 
+    /// Write one data item from specified address to user space with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `src` - Source data address
+    /// * `offset` - Byte offset in UserBuffer
+    ///
+    /// # Returns
+    /// * Ok(()) on success
+    ///
+    /// # Errors
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn copy_one_to_user_checked<T: core::marker::Copy>(
+        &'a mut self,
+        src: &T,
+        offset: usize,
+    ) -> Result<(), SystemError> {
+        let dst = Self::convert_one_with_offset_checked::<T>(self.buffer, offset)?;
+        dst.clone_from(src);
+        return Ok(());
+    }
+
     pub fn buffer<T>(&'a mut self, offset: usize) -> Result<&'a mut [T], SystemError> {
     pub fn buffer<T>(&'a mut self, offset: usize) -> Result<&'a mut [T], SystemError> {
         Self::convert_with_offset::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)
         Self::convert_with_offset::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)
     }
     }
 
 
+    /// Convert to a mutable slice of specified type with page mapping and permission verification
+    ///
+    /// This function verifies that the pages are mapped AND have the required permissions,
+    /// not just performing permission checks.
+    ///
+    /// # Arguments
+    /// * `offset` - Byte offset
+    ///
+    /// # Returns
+    /// * Returns a mutable slice of the specified type
+    ///
+    /// # Errors
+    /// * `EINVAL` - Invalid offset or alignment
+    /// * `EFAULT` - Pages are not mapped or lack required permissions
+    pub fn buffer_checked<T>(&'a mut self, offset: usize) -> Result<&'a mut [T], SystemError> {
+        Self::convert_with_offset_checked::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)
+    }
+
     fn convert_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut [T], SystemError> {
     fn convert_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut [T], SystemError> {
         if offset > src.len() {
         if offset > src.len() {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
@@ -351,6 +600,23 @@ impl<'a> UserBufferWriter<'a> {
         return Ok(chunks);
         return Ok(chunks);
     }
     }
 
 
+    fn convert_with_offset_checked<T>(
+        src: &mut [u8],
+        offset: usize,
+    ) -> Result<&mut [T], SystemError> {
+        let size = src.len().saturating_sub(offset);
+        if size > 0
+            && !check_user_access_by_page_table(
+                VirtAddr::new(src.as_ptr() as usize + offset),
+                size,
+                true,
+            )
+        {
+            return Err(SystemError::EFAULT);
+        }
+        Self::convert_with_offset(src, offset)
+    }
+
     fn convert_one_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut T, SystemError> {
     fn convert_one_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut T, SystemError> {
         if offset + core::mem::size_of::<T>() > src.len() {
         if offset + core::mem::size_of::<T>() > src.len() {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
@@ -361,4 +627,79 @@ impl<'a> UserBufferWriter<'a> {
         let data = &mut chunks[0];
         let data = &mut chunks[0];
         return Ok(data);
         return Ok(data);
     }
     }
+
+    fn convert_one_with_offset_checked<T>(
+        src: &mut [u8],
+        offset: usize,
+    ) -> Result<&mut T, SystemError> {
+        let size = core::mem::size_of::<T>();
+        if offset + size > src.len() {
+            return Err(SystemError::EINVAL);
+        }
+        if !check_user_access_by_page_table(
+            VirtAddr::new(src.as_ptr() as usize + offset),
+            size,
+            true,
+        ) {
+            return Err(SystemError::EFAULT);
+        }
+        Self::convert_one_with_offset(src, offset)
+    }
+}
+
+/// Check user access by page table - verifies both page mapping AND permissions
+///
+/// This function checks if pages are mapped in the page table AND verifies
+/// the required permissions (user access, and write access if requested).
+/// It returns false if pages are not mapped or lack required permissions.
+///
+/// # Arguments
+/// * `addr` - Virtual address to check
+/// * `size` - Size of the memory region to check
+/// * `check_write` - Whether to check for write permission
+///
+/// # Returns
+/// * `true` if all pages are mapped and have required permissions
+/// * `false` if any page is not mapped or lacks required permissions
+fn check_user_access_by_page_table(addr: VirtAddr, size: usize, check_write: bool) -> bool {
+    // Check if address is valid
+    if addr.is_null() {
+        return false;
+    }
+    // Get address space and check mapping
+    let vm = match ProcessManager::current_pcb().basic().user_vm() {
+        Some(vm) => vm,
+        None => return false,
+    };
+
+    // Calculate page-aligned address and size
+    let page_mask = MMArch::PAGE_SIZE - 1;
+    let aligned_addr = addr.data() & (!page_mask); // Align down to page boundary
+    let offset = (addr - aligned_addr).data();
+    let aligned_size = (offset + size).next_multiple_of(MMArch::PAGE_SIZE);
+
+    // Calculate number of pages to check (rounded up)
+    let pages = aligned_size / MMArch::PAGE_SIZE;
+
+    let guard = vm.read_irqsave();
+    for i in 0..pages {
+        let page_addr = aligned_addr + i * MMArch::PAGE_SIZE;
+        let flags = match guard.user_mapper.utable.translate(VirtAddr::new(page_addr)) {
+            Some((_, flags)) => flags,
+            None => return false,
+        };
+
+        if !flags.has_user() {
+            // If no user access permission, return false
+            return false;
+        }
+
+        if check_write && !flags.has_write() {
+            // If write permission check is required but no write permission, return false
+            return false;
+        }
+    }
+    drop(guard);
+
+    return true;
 }
 }

+ 14 - 0
kernel/src/virt/vm/kvm_dev.rs

@@ -35,6 +35,7 @@ pub struct KvmInode {
     self_ref: Weak<LockedKvmInode>,
     self_ref: Weak<LockedKvmInode>,
     /// 指向inode所在的文件系统对象的指针
     /// 指向inode所在的文件系统对象的指针
     fs: Weak<DevFS>,
     fs: Weak<DevFS>,
+    parent: Weak<crate::filesystem::devfs::LockedDevFSInode>,
     /// INode 元数据
     /// INode 元数据
     metadata: Metadata,
     metadata: Metadata,
 }
 }
@@ -52,6 +53,7 @@ impl LockedKvmInode {
         let inode = KvmInode {
         let inode = KvmInode {
             self_ref: Weak::default(),
             self_ref: Weak::default(),
             fs: Weak::default(),
             fs: Weak::default(),
+            parent: Weak::default(),
             metadata: Metadata {
             metadata: Metadata {
                 dev_id: 1,
                 dev_id: 1,
                 inode_id: generate_inode_id(),
                 inode_id: generate_inode_id(),
@@ -96,6 +98,10 @@ impl DeviceINode for LockedKvmInode {
     fn set_fs(&self, fs: Weak<DevFS>) {
     fn set_fs(&self, fs: Weak<DevFS>) {
         self.inner.lock().fs = fs;
         self.inner.lock().fs = fs;
     }
     }
+
+    fn set_parent(&self, parent: Weak<crate::filesystem::devfs::LockedDevFSInode>) {
+        self.inner.lock().parent = parent;
+    }
 }
 }
 
 
 impl IndexNode for LockedKvmInode {
 impl IndexNode for LockedKvmInode {
@@ -179,6 +185,14 @@ impl IndexNode for LockedKvmInode {
     ) -> Result<(), SystemError> {
     ) -> Result<(), SystemError> {
         Ok(())
         Ok(())
     }
     }
+
+    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
+        let parent = self.inner.lock().parent.upgrade();
+        if let Some(parent) = parent {
+            return Ok(parent);
+        }
+        Err(SystemError::ENOENT)
+    }
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]

+ 0 - 3
tools/debugging/logmonitor/src/lib.rs

@@ -1,6 +1,3 @@
-#![allow(incomplete_features)]
-#![feature(generic_const_exprs)]
-
 extern crate clap;
 extern crate clap;
 
 
 extern crate lazy_static;
 extern crate lazy_static;

+ 1 - 0
user/apps/test_bind/.gitignore → user/apps/c_unitest/.gitignore

@@ -1 +1,2 @@
 test_bind
 test_bind
+test_cred

+ 35 - 0
user/apps/c_unitest/Makefile

@@ -0,0 +1,35 @@
+ifeq ($(ARCH), x86_64)
+	CROSS_COMPILE=x86_64-linux-musl-
+else ifeq ($(ARCH), riscv64)
+	CROSS_COMPILE=riscv64-linux-musl-
+endif
+
+CC=$(CROSS_COMPILE)gcc
+CFLAGS := -Wall -O2 -static
+
+SRCS := $(wildcard *.c)
+BINS := $(SRCS:.c=)
+
+
+
+$(C_TARGETS): %.o: %.c
+	$(CC) -c $< -o $@
+
+all: $(BINS)
+# 	@echo "src: $(SRCS)"
+	@echo "bins: $(BINS)"
+
+%: %.c
+	$(CC) $(CFLAGS)  $< -o $@
+
+
+install: all
+	@echo "Installing binaries to $(DADK_CURRENT_BUILD_DIR)/"
+	mv $(BINS) $(DADK_CURRENT_BUILD_DIR)/
+
+
+clean:
+	rm -f $(BINS)
+
+
+.PHONY: all install clean

+ 179 - 0
user/apps/c_unitest/dmesg.c

@@ -0,0 +1,179 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/klog.h>
+#include <unistd.h>
+/**
+ * @brief 识别dmesg程序的第一个选项参数
+ *
+ * @param arg dmesg命令第一个选项参数
+ * @return int 有效时返回对应选项码,无效时返回 -1
+ */
+int getoption(char *arg) {
+  if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
+    return 0;
+  else if (!strcmp(arg, "-c") || !strcmp(arg, "--read-clear"))
+    return 4;
+  else if (!strcmp(arg, "-C") || !strcmp(arg, "--clear"))
+    return 5;
+  else if (!strcmp(arg, "-l") || !strcmp(arg, "--level"))
+    return 8;
+
+  return -1;
+}
+
+/**
+ * @brief 识别dmesg程序的第二个选项参数
+ *
+ * @param arg dmesg命令第一个选项参数
+ * @return int 有效时返回设置的日志级别,无效时返回 -1
+ */
+int getlevel(char *arg) {
+  if (!strcmp(arg, "EMERG") || !strcmp(arg, "emerg"))
+    return 0;
+  else if (!strcmp(arg, "ALERT") || !strcmp(arg, "alert"))
+    return 1;
+  else if (!strcmp(arg, "CRIT") || !strcmp(arg, "crit"))
+    return 2;
+  else if (!strcmp(arg, "ERR") || !strcmp(arg, "err"))
+    return 3;
+  else if (!strcmp(arg, "WARN") || !strcmp(arg, "warn"))
+    return 4;
+  else if (!strcmp(arg, "NOTICE") || !strcmp(arg, "notice"))
+    return 5;
+  else if (!strcmp(arg, "INFO") || !strcmp(arg, "info"))
+    return 6;
+  else if (!strcmp(arg, "DEBUG") || !strcmp(arg, "debug"))
+    return 7;
+  else {
+    printf("dmesg: unknown level '%s'\n", arg);
+  }
+  return -2;
+}
+
+/**
+ * @brief 打印dmesg手册
+ */
+void print_help_msg() {
+  const char *help_msg =
+      "Usage:\n"
+      " dmesg [options]\n\n"
+      "Display or control the kernel ring buffer.\n\n"
+      "Options:\n"
+      " -C, --clear                 clear the kernel ring buffer\n"
+      " -c, --read-clear            read and clear all messages\n"
+      " -l, --level <list>          restrict output to defined levels\n"
+      " -h, --help                  display this help\n\n"
+      "Supported log levels (priorities):\n"
+      "   emerg - system is unusable\n"
+      "   alert - action must be taken immediately\n"
+      "    crit - critical conditions\n"
+      "     err - error conditions\n"
+      "    warn - warning conditions\n"
+      "  notice - normal but significant condition\n"
+      "    info - informational\n"
+      "   debug - debug-level messages\n";
+  printf("%s\n", help_msg);
+}
+
+/**
+ * @brief 打印dmesg错误使用的信息
+ */
+void print_bad_usage_msg() {
+  const char *bad_usage_msg =
+      "dmesg: bad usage\nTry 'dmesg --help' for more information.";
+  printf("%s\n", bad_usage_msg);
+}
+int main(int argc, char **argv) {
+  unsigned int len = 1;
+  char *buf = NULL;
+  int opt;
+  unsigned int color = 65280;
+
+  // 获取内核缓冲区大小
+  len = klogctl(10, buf, len);
+
+  if (len < 16 * 1024)
+    len = 16 * 1024;
+  if (len > 16 * 1024 * 1024)
+    len = 16 * 1024 * 1024;
+
+  buf = malloc(len);
+  if (buf == NULL) {
+    perror("");
+    return -1;
+  }
+
+  if (argc == 1) {
+    // 无选项参数,默认打印所有日志消息
+    len = klogctl(2, buf, len);
+  } else {
+    // 获取第一个选项参数
+    opt = getoption(argv[1]);
+
+    // 无效参数
+    if (opt == -1) {
+      print_bad_usage_msg();
+      return -1;
+    }
+    // 打印帮助手册
+    else if (opt == 0) {
+      print_help_msg();
+      return 0;
+    }
+    // 4 -> 读取内核缓冲区后,清空缓冲区
+    // 5 -> 清空内核缓冲区
+    else if (opt == 4 || opt == 5) {
+      len = klogctl(opt, buf, len);
+    }
+    // 读取特定日志级别的消息
+    else if (opt == 8) {
+      // 无指定日志级别参数,打印错误使用信息
+      if (argc < 3) {
+        print_bad_usage_msg();
+        return -1;
+      }
+
+      int level = -1;
+
+      // 获取日志级别
+      // 这里加1的原因是:如果klogctl的第三个参数是0,不会发生系统调用
+      level = getlevel(argv[2]) + 1;
+
+      if (level == -1)
+        return -1;
+
+      klogctl(8, buf, level);
+      len = klogctl(2, buf, len);
+    }
+  }
+
+  // 当前打印内容
+  // 0: 日志级别
+  // 1: 时间戳
+  // 2: 代码行号
+  // 3: 日志消息
+  unsigned int content = 0;
+  for (int i = 0; i < len; i++) {
+    char c[2];
+    c[0] = buf[i];
+    c[1] = '\0';
+    syscall(100000, &c[0], color, 0);
+    if (content == 0 && buf[i] == '>') {
+      content++;
+    } else if (content == 1 && buf[i] == ']') {
+      color = 16744448;
+      content++;
+    } else if (content == 2 && buf[i] == ')') {
+      color = 16777215;
+      content++;
+    } else if (content == 3 && buf[i] == '\n') {
+      color = 65280;
+      content = 0;
+    }
+  }
+
+  free(buf);
+
+  return 0;
+}

+ 215 - 0
user/apps/c_unitest/http_server.c

@@ -0,0 +1,215 @@
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define PORT 12580
+#define MAX_REQUEST_SIZE 1500
+#define MAX_RESPONSE_SIZE 1500
+// 网页根目录
+#define WEB_ROOT "/var/www/html/"
+#define EXIT_CODE 1
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#define DEFAULT_PAGE "/index.html"
+
+static int request_counter = 0;
+
+int security_check(char *path) {
+  // 检查路径是否包含 ..
+  if (strstr(path, "..")) {
+    return 0;
+  }
+  return 1;
+}
+
+ssize_t send_response(int sockfd, char *response) {
+  return write(sockfd, response, strlen(response));
+}
+
+void send_header(int sockfd, int content_length, char *path) {
+  char buffer[MAX_RESPONSE_SIZE];
+  // 获取文件类型
+  char *content_type;
+  if (strstr(path, ".html")) {
+    content_type = "text/html";
+  } else if (strstr(path, ".css")) {
+    content_type = "text/css";
+  } else if (strstr(path, ".js")) {
+    content_type = "application/javascript";
+  } else if (strstr(path, ".png")) {
+    content_type = "image/png";
+  } else if (strstr(path, ".jpg")) {
+    content_type = "image/jpeg";
+  } else if (strstr(path, ".gif")) {
+    content_type = "image/gif";
+  } else {
+    content_type = "text/plain;charset=utf-8";
+  }
+  sprintf(buffer, "HTTP/1.1 200 OK\nContent-Type: %s\nContent-Length: %d\n\n",
+          content_type, content_length);
+  send_response(sockfd, buffer);
+}
+
+void send_file(int sockfd, char *path) {
+  printf("send_file: path: %s\n", path);
+
+  int fd = open(path, 0);
+  if (fd == -1) {
+    send_response(sockfd,
+                  "HTTP/1.1 404 Not Found\nContent-Type: "
+                  "text/html\n\n<html><body><h1>404 Not Found</h1><p>DragonOS "
+                  "Http Server</p></body></html>");
+    return;
+  }
+
+  int content_length = lseek(fd, 0, SEEK_END);
+  int remaining = content_length;
+  printf("send_file: content_length: %d\n", content_length);
+  lseek(fd, 0, SEEK_SET);
+  send_header(sockfd, content_length, path);
+
+  char buffer[1048576];
+  int readSize;
+  while (remaining) {
+    // 由于磁盘IO耗时较长,所以每次读取1MB,然后再分批发送
+    int to_read = min(1048576, remaining);
+    readSize = read(fd, &buffer, to_read);
+
+    remaining -= readSize;
+    void *p = buffer;
+    while (readSize > 0) {
+      int wsize = write(sockfd, p, min(readSize, MAX_RESPONSE_SIZE));
+      if (wsize <= 0) {
+        printf("send_file failed: wsize: %d\n", wsize);
+        close(fd);
+        return;
+      }
+      p += wsize;
+      readSize -= wsize;
+    }
+  }
+
+  close(fd);
+}
+
+void handle_request(int sockfd, char *request) {
+  char *method, *url, *http_version;
+  char path[MAX_REQUEST_SIZE];
+
+  method = strtok(request, " ");
+  url = strtok(NULL, " ");
+  http_version = strtok(NULL, "\r\n");
+
+  printf("handle_request: method: %s, url: %s, http_version: %s\n", method, url,
+         http_version);
+  // 检查空指针等异常情况
+  if (method == NULL || url == NULL || http_version == NULL) {
+    send_response(sockfd,
+                  "HTTP/1.1 400 Bad Request\nContent-Type: "
+                  "text/html\n\n<html><body><h1>400 Bad "
+                  "Request</h1><p>DragonOS Http Server</p></body></html>");
+    return;
+  }
+  // 检查url是否为空
+  if (strlen(url) == 0) {
+    send_response(sockfd,
+                  "HTTP/1.1 400 Bad Request\nContent-Type: "
+                  "text/html\n\n<html><body><h1>400 Bad "
+                  "Request</h1><p>DragonOS Http Server</p></body></html>");
+    return;
+  }
+  int default_page = 0;
+  if (url[strlen(url) - 1] == '/') {
+    default_page = 1;
+  }
+
+  if (strcmp(method, "GET") == 0) {
+    if (default_page) {
+      sprintf(path, "%s%s%s", WEB_ROOT, url, DEFAULT_PAGE);
+    } else {
+      sprintf(path, "%s%s", WEB_ROOT, url);
+    }
+    if (!security_check(path)) {
+      send_response(sockfd,
+                    "HTTP/1.1 403 Forbidden\nContent-Type: "
+                    "text/html\n\n<html><body><h1>403 "
+                    "Forbidden</h1><p>DragonOS Http Server</p></body></html>");
+      return;
+    }
+    send_file(sockfd, path);
+  } else {
+    send_response(sockfd,
+                  "HTTP/1.1 501 Not Implemented\nContent-Type: "
+                  "text/html\n\n<html><body><h1>501 Not "
+                  "Implemented</h1><p>DragonOS Http Server</p></body></html>");
+  }
+}
+
+int main(int argc, char const *argv[]) {
+  int server_fd, new_socket, valread;
+  struct sockaddr_in address;
+  int addrlen = sizeof(address);
+  char buffer[MAX_REQUEST_SIZE] = {0};
+  int opt = 1;
+
+  // 创建socket
+  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("socket failed");
+    exit(EXIT_CODE);
+  }
+
+  // 设置socket选项,允许地址重用
+  // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
+  // sizeof(opt)))
+  // {
+  //     perror("setsockopt failed");
+  //     exit(EXIT_CODE);
+  // }
+
+  // 设置地址和端口
+  address.sin_family = AF_INET;
+  address.sin_addr.s_addr = INADDR_ANY;
+  address.sin_port = htons(PORT);
+
+  // 把socket绑定到地址和端口上
+  if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("bind failed");
+    exit(EXIT_CODE);
+  }
+
+  // 监听socket
+  if (listen(server_fd, 3) < 0) {
+    perror("listen failed");
+    exit(EXIT_CODE);
+  }
+
+  while (1) {
+    printf("[#%d] Waiting for a client...\n", request_counter++);
+
+    // 等待并接受客户端连接
+    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
+                             (socklen_t *)&addrlen)) < 0) {
+      perror("accept failed");
+      exit(EXIT_CODE);
+    }
+
+    // 接收客户端消息
+    valread = read(new_socket, buffer, MAX_REQUEST_SIZE);
+    printf("%s\n", buffer);
+
+    // 处理请求
+    handle_request(new_socket, buffer);
+
+    // 关闭客户端连接
+    close(new_socket);
+  }
+  // 关闭tcp socket
+  close(server_fd);
+
+  return 0;
+}

+ 202 - 0
user/apps/c_unitest/test_bind.c

@@ -0,0 +1,202 @@
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define PORT 12580
+#define MAX_REQUEST_SIZE 1500
+#define MAX_RESPONSE_SIZE 1500
+#define EXIT_CODE 1
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+struct sockaddr_in address;
+int addrlen = sizeof(address);
+char buffer[MAX_REQUEST_SIZE] = {0};
+int opt = 1;
+
+void test_tcp_bind() {
+  int tcp_sk_fd1, tcp_sk_fd2, tcp_sk_fd3;
+
+  // create tcp sockets
+  if ((tcp_sk_fd1 = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket (1) failed");
+    exit(EXIT_CODE);
+  }
+  if ((tcp_sk_fd2 = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket (2) failed");
+    exit(EXIT_CODE);
+  }
+  if ((tcp_sk_fd3 = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket (3) failed");
+    exit(EXIT_CODE);
+  }
+
+  // TEST tcp bind diff ports
+  if (bind(tcp_sk_fd1, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind (1) failed");
+    exit(EXIT_CODE);
+  }
+  address.sin_port = htons(PORT + 1);
+  if (bind(tcp_sk_fd2, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind (2) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 4 PASSED===\n");
+
+  // TEST tcp bind same ports
+  address.sin_port = htons(PORT);
+  if (bind(tcp_sk_fd3, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind (3) failed");
+    // exit(EXIT_CODE);
+  }
+  printf("===TEST 5 PASSED===\n");
+
+  if (close(tcp_sk_fd1) < 0) {
+    perror("tcp close (1) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(tcp_sk_fd2) < 0) {
+    perror("tcp close (2) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(tcp_sk_fd3) < 0) {
+    perror("tcp close (3) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 6 PASSED===\n");
+}
+
+void test_udp_bind() {
+  int udp_sk_fd1, udp_sk_fd2, udp_sk_fd3;
+
+  // create tcp sockets
+  if ((udp_sk_fd1 = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket (1) failed");
+    exit(EXIT_CODE);
+  }
+  if ((udp_sk_fd2 = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket (2) failed");
+    exit(EXIT_CODE);
+  }
+  if ((udp_sk_fd3 = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket (3) failed");
+    exit(EXIT_CODE);
+  }
+
+  // TEST udp bind diff ports
+  if (bind(udp_sk_fd1, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind (1) failed");
+    exit(EXIT_CODE);
+  }
+  address.sin_port = htons(PORT + 1);
+  if (bind(udp_sk_fd2, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind (2) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 7 PASSED===\n");
+
+  // TEST udp bind same ports
+  address.sin_port = htons(PORT);
+  if (bind(udp_sk_fd3, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind (3) failed");
+    // exit(EXIT_CODE);
+  }
+  printf("===TEST 8 PASSED===\n");
+
+  if (close(udp_sk_fd1) < 0) {
+    perror("udp close (1) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(udp_sk_fd2) < 0) {
+    perror("udp close (2) failed");
+    exit(EXIT_CODE);
+  }
+  if (close(udp_sk_fd3) < 0) {
+    perror("udp close (3) failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 9 PASSED===\n");
+}
+
+void test_all_ports() {
+  int count = 0;
+
+  while (1) {
+    int tcp_fd;
+    if ((tcp_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+      perror("socket failed");
+      exit(EXIT_CODE);
+    }
+
+    address.sin_port = htons(0);
+    if (bind(tcp_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+      perror("bind failed");
+      // exit(EXIT_CODE);
+      break;
+    }
+
+    count++;
+  }
+  printf("===TEST 10===\n");
+  printf("count: %d\n", count);
+}
+
+int main(int argc, char const *argv[]) {
+  int server_fd;
+  int udp_sk_fd;
+
+  // 创建socket
+  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
+    perror("tcp socket failed");
+    exit(EXIT_CODE);
+  }
+
+  if ((udp_sk_fd = socket(AF_INET, SOCK_DGRAM, 0)) == 0) {
+    perror("udp socket failed");
+    exit(EXIT_CODE);
+  }
+
+  // 设置地址和端口
+  address.sin_family = AF_INET;
+  address.sin_addr.s_addr = INADDR_ANY;
+  address.sin_port = htons(PORT);
+
+  // TEST socket's bind
+  if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("tcp bind failed");
+    exit(EXIT_CODE);
+  }
+  address.sin_port = htons(PORT);
+  if (bind(udp_sk_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
+    perror("udp bind failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 1 PASSED===\n");
+
+  // TEST socket's listen
+  if (listen(server_fd, 3) < 0) {
+    perror("listen failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 2 PASSED===\n");
+
+  // TEST socket's close
+  if (close(server_fd) < 0) {
+    perror("tcp close failed");
+    exit(EXIT_CODE);
+  }
+  if (close(udp_sk_fd) < 0) {
+    perror("udp close failed");
+    exit(EXIT_CODE);
+  }
+  printf("===TEST 3 PASSED===\n");
+
+  test_tcp_bind();
+  test_udp_bind();
+  test_all_ports();
+
+  return 0;
+}

+ 43 - 0
user/apps/c_unitest/test_cred.c

@@ -0,0 +1,43 @@
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+  printf("Current uid: %d, euid: %d, gid: %d, egid: %d\n\n", getuid(),
+         geteuid(), getgid(), getegid());
+
+  // 测试uid
+  printf("Set uid 1000\n");
+  setuid(1000);
+  int uid = getuid();
+  assert(uid == 1000);
+  printf("Current uid:%d\n\n", uid);
+
+  // 测试gid
+  printf("Set gid 1000\n");
+  setgid(1000);
+  int gid = getgid();
+  assert(gid == 1000);
+  printf("Current gid:%d\n\n", gid);
+
+  // 测试euid
+  printf("Setg euid 1000\n");
+  seteuid(1000);
+  int euid = geteuid();
+  assert(euid == 1000);
+  printf("Current euid:%d\n\n", euid);
+
+  // 测试egid
+  printf("Set egid 1000\n");
+  setegid(1000);
+  int egid = getegid();
+  assert(egid == 1000);
+  printf("Current egid:%d\n\n", egid);
+
+  // 测试uid在非root用户下无法修改
+  printf("Try to setuid for non_root.\n");
+  assert(setuid(0) < 0); // 非root用户无法修改uid
+  printf("Current uid: %d, euid: %d, gid: %d, egid: %d\n", getuid(), geteuid(),
+         getgid(), getegid());
+}

+ 103 - 0
user/apps/c_unitest/test_cross_process_futex.c

@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+
+static long futex(uint32_t *uaddr, int futex_op, uint32_t val, const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3) {
+    return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
+}
+
+int main() {
+    // 创建共享内存区域
+    uint32_t *shared_futex = mmap(NULL, sizeof(uint32_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (shared_futex == MAP_FAILED) {
+        perror("mmap");
+        exit(1);
+    }
+
+    // 初始化futex
+    *shared_futex = 0;
+
+    printf("Parent: Setting up robust futex list...\n");
+    
+    // 设置robust futex列表
+    struct robust_list_head {
+        struct robust_list *list;
+        long futex_offset;
+        struct robust_list *list_op_pending;
+    };
+    
+    struct robust_list_head robust_head = {
+        .list = (struct robust_list *)shared_futex,
+        .futex_offset = 0,
+        .list_op_pending = NULL
+    };
+    
+    // 设置当前进程的robust list
+    if (syscall(SYS_set_robust_list, &robust_head, sizeof(robust_head)) != 0) {
+        perror("set_robust_list");
+        exit(1);
+    }
+
+    pid_t pid = fork();
+    
+    if (pid == 0) {
+        // 子进程
+        printf("Child: Waiting for futex...\n");
+        
+        // 子进程也设置自己的robust list
+        struct robust_list_head child_robust_head = {
+            .list = (struct robust_list *)shared_futex,
+            .futex_offset = 0,
+            .list_op_pending = NULL
+        };
+        
+        if (syscall(SYS_set_robust_list, &child_robust_head, sizeof(child_robust_head)) != 0) {
+            perror("child set_robust_list");
+            exit(1);
+        }
+        
+        // 锁定futex
+        __sync_lock_test_and_set(shared_futex, getpid());
+        
+        printf("Child: Acquired futex, sleeping for 1 second...\n");
+        sleep(1);
+        
+        // 释放futex
+        __sync_lock_release(shared_futex);
+        
+        printf("Child: Released futex, exiting...\n");
+        exit(0);
+    } else if (pid > 0) {
+        // 父进程
+        printf("Parent: Child PID = %d\n", pid);
+        
+        // 等待子进程
+        int status;
+        waitpid(pid, &status, 0);
+        
+        printf("Parent: Child exited, cleaning up...\n");
+        
+        // 尝试访问futex(这可能会触发VMA not mapped错误)
+        printf("Parent: Futex value = %u\n", *shared_futex);
+        
+        // 清理
+        munmap(shared_futex, sizeof(uint32_t));
+        
+        printf("Parent: Done\n");
+    } else {
+        perror("fork");
+        exit(1);
+    }
+    
+    return 0;
+}

+ 30 - 0
user/apps/c_unitest/test_dup3.c

@@ -0,0 +1,30 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+  int fd = open("/history_commands.txt", O_RDONLY);
+  if (fd < 0) {
+    perror("Failed to open file");
+    return 1;
+  }
+
+  int new_fd = 777;
+  int rt = dup3(fd, new_fd, O_CLOEXEC);
+  if (rt < 0) {
+    perror("Failed to duplicate file descriptor with flags");
+  }
+
+  char buffer[100];
+  int bytes_read = read(new_fd, buffer, sizeof(buffer));
+  if (bytes_read < 0) {
+    perror("Failed to read data");
+    return 1;
+  }
+
+  printf("Data:\n %.*s\n", bytes_read, buffer);
+
+  close(fd);
+  close(new_fd);
+  return 0;
+}

+ 0 - 0
user/apps/test_epoll/main.c → user/apps/c_unitest/test_epoll.c


+ 50 - 0
user/apps/c_unitest/test_eventfd.c

@@ -0,0 +1,50 @@
+#include <err.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[]) {
+  int efd;
+  uint64_t u;
+  ssize_t s;
+
+  if (argc < 2) {
+    fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
+    exit(EXIT_FAILURE);
+  }
+
+  efd = eventfd(0, 0);
+  if (efd == -1)
+    err(EXIT_FAILURE, "eventfd");
+
+  switch (fork()) {
+  case 0:
+    for (size_t j = 1; j < argc; j++) {
+      printf("Child writing %s to efd\n", argv[j]);
+      u = strtoull(argv[j], NULL, 0);
+      /* strtoull() allows various bases */
+      s = write(efd, &u, sizeof(uint64_t));
+      if (s != sizeof(uint64_t))
+        err(EXIT_FAILURE, "write");
+    }
+    printf("Child completed write loop\n");
+
+    exit(EXIT_SUCCESS);
+
+  default:
+    sleep(2);
+
+    printf("Parent about to read\n");
+    s = read(efd, &u, sizeof(uint64_t));
+    if (s != sizeof(uint64_t))
+      err(EXIT_FAILURE, "read");
+    printf("Parent read %" PRIu64 " (%#" PRIx64 ") from efd\n", u, u);
+    exit(EXIT_SUCCESS);
+
+  case -1:
+    err(EXIT_FAILURE, "fork");
+  }
+}

+ 3 - 3
user/apps/test_fifo_write/main.c → user/apps/c_unitest/test_fifo_write.c

@@ -159,13 +159,13 @@ void run_tests(int nonblocking) {
            nonblocking);
            nonblocking);
     switch (i) {
     switch (i) {
     case 0:
     case 0:
-    //   test_case1(nonblocking);
+      //   test_case1(nonblocking);
       break;
       break;
     case 1:
     case 1:
       test_case2(nonblocking);
       test_case2(nonblocking);
       break;
       break;
     case 2:
     case 2:
-    //   test_case3(nonblocking);
+      //   test_case3(nonblocking);
       break;
       break;
     }
     }
   }
   }
@@ -202,7 +202,7 @@ int main() {
   // 设置 SIGPIPE 信号处理
   // 设置 SIGPIPE 信号处理
   signal(SIGPIPE, sigpipe_handler);
   signal(SIGPIPE, sigpipe_handler);
 
 
-//   test_blocking();
+  //   test_blocking();
   test_non_blocking();
   test_non_blocking();
 
 
   printf("\nAll tests completed.\n");
   printf("\nAll tests completed.\n");

+ 57 - 0
user/apps/c_unitest/test_filemap.c

@@ -0,0 +1,57 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+  // 打开文件
+  int fd = open("example.txt", O_RDWR | O_CREAT | O_TRUNC, 0777);
+
+  if (fd == -1) {
+    perror("open");
+    exit(EXIT_FAILURE);
+  }
+
+  write(fd, "HelloWorld!", 11);
+  char buf[12];
+  buf[11] = '\0';
+  close(fd);
+
+  fd = open("example.txt", O_RDWR);
+  read(fd, buf, 11);
+  printf("File content: %s\n", buf);
+
+  // 将文件映射到内存
+  void *map = mmap(NULL, 11, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (map == MAP_FAILED) {
+    perror("mmap");
+    close(fd);
+    exit(EXIT_FAILURE);
+  }
+  printf("mmap address: %p\n", map);
+
+  // 关闭文件描述符
+  // close(fd);
+
+  // 访问和修改文件内容
+  char *fileContent = (char *)map;
+  printf("change 'H' to 'G'\n");
+  fileContent[0] = 'G'; // 修改第一个字符为 'G'
+  printf("mmap content: %s\n", fileContent);
+
+  // 解除映射
+  printf("unmap\n");
+  if (munmap(map, 11) == -1) {
+    perror("munmap");
+    exit(EXIT_FAILURE);
+  }
+
+  fd = open("example.txt", O_RDWR);
+  read(fd, buf, 11);
+  printf("File content: %s\n", buf);
+
+  return 0;
+}

+ 2 - 3
user/apps/test-fork-wait/main.c → user/apps/c_unitest/test_fork_wait.c

@@ -10,17 +10,16 @@
 #include <time.h>
 #include <time.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
-
 // 子线程或子进程模拟事件发生
 // 子线程或子进程模拟事件发生
 void trigger_event(unsigned int delay_sec) {
 void trigger_event(unsigned int delay_sec) {
   printf("[child] triggere event after %u seconds...\n", delay_sec);
   printf("[child] triggere event after %u seconds...\n", delay_sec);
   sleep(delay_sec);
   sleep(delay_sec);
- 
+
   printf("[child] Event triggered.\n");
   printf("[child] Event triggered.\n");
 }
 }
 
 
 int main() {
 int main() {
- 
+
   pid_t pid = fork();
   pid_t pid = fork();
   if (pid < 0) {
   if (pid < 0) {
     perror("fork");
     perror("fork");

+ 0 - 0
user/apps/test_fstat/main.c → user/apps/c_unitest/test_fstat.c


+ 41 - 0
user/apps/c_unitest/test_fstatfs.c

@@ -0,0 +1,41 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/statfs.h>
+
+int main(int argc, char **argv) {
+  int fd = open("/bin/about.elf", O_RDONLY);
+  if (fd == -1)
+    return 0;
+  printf("fd = %d\n", fd);
+  struct statfs diskInfo;
+
+  fstatfs(fd, &diskInfo);
+  unsigned long long blocksize1 = diskInfo.f_bsize; //每个block里包含的字节数
+  unsigned long long totalsize =
+      blocksize1 * diskInfo.f_blocks; //总的字节数,f_blocks为block的数目
+  printf("Total_size=%llu B =%llu KB =%llu MB = %llu GB\n", totalsize,
+         totalsize >> 10, totalsize >> 20, totalsize >> 30);
+
+  /* 2.获取一下剩余空间和可用空间的大小 */
+  unsigned long long freeDisk = diskInfo.f_bfree * blocksize1; //剩余空间的大小
+  unsigned long long availableDisk =
+      diskInfo.f_bavail * blocksize1; //可用空间大小
+  printf("Disk_free=%llu MB =%llu GB Disk_available=%llu MB = %llu GB\n",
+         freeDisk >> 20, freeDisk >> 30, availableDisk >> 20,
+         availableDisk >> 30);
+
+  printf("====================\n");
+  printf("diskInfo address: %p\n", diskInfo);
+  printf("f_type= %lu\n", diskInfo.f_type);
+  printf("f_bsize = %lu\n", diskInfo.f_bsize);
+  printf("f_blocks = %d\n", diskInfo.f_blocks);
+  printf("f_bfree = %lu\n", diskInfo.f_bfree);
+  printf("b_avail = %d\n", diskInfo.f_bavail);
+  printf("f_files = %d\n", diskInfo.f_files);
+  printf("f_ffree = %lu\n", diskInfo.f_ffree);
+  printf("f_fsid = %ld\n", diskInfo.f_fsid);
+  printf("f_namelen = %ld\n", diskInfo.f_namelen);
+  printf("f_frsize = %ld\n", diskInfo.f_frsize);
+  printf("f_flags = %ld\n", diskInfo.f_flags);
+  return 0;
+}

+ 22 - 0
user/apps/c_unitest/test_gettimeofday.c

@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+int main() {
+  struct timeval *tv = malloc(sizeof(struct timeval));
+  struct timezone *tz = malloc(sizeof(struct timezone));
+  for (int i = 0; i < 15; i++) {
+    gettimeofday(tv, NULL);
+    printf("%ld.%06ld\n", tv->tv_sec, tv->tv_usec);
+    for (int i = 0; i < 10; i++) {
+      usleep(500000);
+    }
+  }
+  gettimeofday(tv, NULL);
+  printf("tv = %ld.%06ld\n", tv->tv_sec, tv->tv_usec);
+  // printf("tz_minuteswest = %d,tz_dsttime = %d", (*tz).tz_minuteswest,
+  // (*tz).tz_dsttime);
+  return 0;
+}

+ 534 - 0
user/apps/c_unitest/test_kvm.c

@@ -0,0 +1,534 @@
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+//#include <linux/kvm.h>
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#ifdef __GNUC__
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#else
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+// from linux/kvm.h
+#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
+#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
+#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
+
+#define KVM_RUN _IO(KVMIO, 0x80)
+#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs)
+#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs)
+#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs)
+#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs)
+
+#define KVMIO 0xAE
+#define KVM_SET_USER_MEMORY_REGION                                             \
+  _IOW(KVMIO, 0x46, struct kvm_userspace_memory_region)
+/* Architectural interrupt line count. */
+#define KVM_NR_INTERRUPTS 256
+struct kvm_hyperv_exit {
+#define KVM_EXIT_HYPERV_SYNIC 1
+#define KVM_EXIT_HYPERV_HCALL 2
+#define KVM_EXIT_HYPERV_SYNDBG 3
+  __u32 type;
+  __u32 pad1;
+  union {
+    struct {
+      __u32 msr;
+      __u32 pad2;
+      __u64 control;
+      __u64 evt_page;
+      __u64 msg_page;
+    } synic;
+    struct {
+      __u64 input;
+      __u64 result;
+      __u64 params[2];
+    } hcall;
+    struct {
+      __u32 msr;
+      __u32 pad2;
+      __u64 control;
+      __u64 status;
+      __u64 send_page;
+      __u64 recv_page;
+      __u64 pending_page;
+    } syndbg;
+  } u;
+};
+struct kvm_debug_exit_arch {
+  __u32 exception;
+  __u32 pad;
+  __u64 pc;
+  __u64 dr6;
+  __u64 dr7;
+};
+/* for KVM_SET_USER_MEMORY_REGION */
+struct kvm_userspace_memory_region {
+  __u32 slot;
+  __u32 flags;
+  __u64 guest_phys_addr;
+  __u64 memory_size;    /* bytes */
+  __u64 userspace_addr; /* start of the userspace allocated memory */
+};
+struct kvm_xen_exit {
+#define KVM_EXIT_XEN_HCALL 1
+  __u32 type;
+  union {
+    struct {
+      __u32 longmode;
+      __u32 cpl;
+      __u64 input;
+      __u64 result;
+      __u64 params[6];
+    } hcall;
+  } u;
+};
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+  /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+  __u64 rax, rbx, rcx, rdx;
+  __u64 rsi, rdi, rsp, rbp;
+  __u64 r8, r9, r10, r11;
+  __u64 r12, r13, r14, r15;
+  __u64 rip, rflags;
+};
+struct my_kvm_segment {
+  __u64 base;
+  __u32 limit;
+  __u16 selector;
+  __u8 type;
+  __u8 present, dpl, db, s, l, g, avl;
+  __u8 unusable;
+  __u8 padding;
+};
+struct kvm_dtable {
+  __u64 base;
+  __u16 limit;
+  __u16 padding[3];
+};
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+  /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
+  struct my_kvm_segment cs, ds, es, fs, gs, ss;
+  struct my_kvm_segment tr, ldt;
+  struct kvm_dtable gdt, idt;
+  __u64 cr0, cr2, cr3, cr4, cr8;
+  __u64 efer;
+  __u64 apic_base;
+  __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
+};
+
+/* for KVM_GET/SET_VCPU_EVENTS */
+struct kvm_vcpu_events {
+  struct {
+    __u8 injected;
+    __u8 nr;
+    __u8 has_error_code;
+    __u8 pending;
+    __u32 error_code;
+  } exception;
+  struct {
+    __u8 injected;
+    __u8 nr;
+    __u8 soft;
+    __u8 shadow;
+  } interrupt;
+  struct {
+    __u8 injected;
+    __u8 pending;
+    __u8 masked;
+    __u8 pad;
+  } nmi;
+  __u32 sipi_vector;
+  __u32 flags;
+  struct {
+    __u8 smm;
+    __u8 pending;
+    __u8 smm_inside_nmi;
+    __u8 latched_init;
+  } smi;
+  __u8 reserved[27];
+  __u8 exception_has_payload;
+  __u64 exception_payload;
+};
+/* kvm_sync_regs struct included by kvm_run struct */
+struct kvm_sync_regs {
+  /* Members of this structure are potentially malicious.
+   * Care must be taken by code reading, esp. interpreting,
+   * data fields from them inside KVM to prevent TOCTOU and
+   * double-fetch types of vulnerabilities.
+   */
+  struct kvm_regs regs;
+  struct kvm_sregs sregs;
+  struct kvm_vcpu_events events;
+};
+
+/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
+struct kvm_run {
+  /* in */
+  __u8 request_interrupt_window;
+  __u8 immediate_exit;
+  __u8 padding1[6];
+
+  /* out */
+  __u32 exit_reason;
+  __u8 ready_for_interrupt_injection;
+  __u8 if_flag;
+  __u16 flags;
+
+  /* in (pre_kvm_run), out (post_kvm_run) */
+  __u64 cr8;
+  __u64 apic_base;
+
+#ifdef __KVM_S390
+  /* the processor status word for s390 */
+  __u64 psw_mask; /* psw upper half */
+  __u64 psw_addr; /* psw lower half */
+#endif
+  union {
+    /* KVM_EXIT_UNKNOWN */
+    struct {
+      __u64 hardware_exit_reason;
+    } hw;
+    /* KVM_EXIT_FAIL_ENTRY */
+    struct {
+      __u64 hardware_entry_failure_reason;
+      __u32 cpu;
+    } fail_entry;
+    /* KVM_EXIT_EXCEPTION */
+    struct {
+      __u32 exception;
+      __u32 error_code;
+    } ex;
+    /* KVM_EXIT_IO */
+    struct {
+#define KVM_EXIT_IO_IN 0
+#define KVM_EXIT_IO_OUT 1
+      __u8 direction;
+      __u8 size; /* bytes */
+      __u16 port;
+      __u32 count;
+      __u64 data_offset; /* relative to kvm_run start */
+    } io;
+    /* KVM_EXIT_DEBUG */
+    struct {
+      struct kvm_debug_exit_arch arch;
+    } debug;
+    /* KVM_EXIT_MMIO */
+    struct {
+      __u64 phys_addr;
+      __u8 data[8];
+      __u32 len;
+      __u8 is_write;
+    } mmio;
+    /* KVM_EXIT_HYPERCALL */
+    struct {
+      __u64 nr;
+      __u64 args[6];
+      __u64 ret;
+      __u32 longmode;
+      __u32 pad;
+    } hypercall;
+    /* KVM_EXIT_TPR_ACCESS */
+    struct {
+      __u64 rip;
+      __u32 is_write;
+      __u32 pad;
+    } tpr_access;
+    /* KVM_EXIT_S390_SIEIC */
+    struct {
+      __u8 icptcode;
+      __u16 ipa;
+      __u32 ipb;
+    } s390_sieic;
+    /* KVM_EXIT_S390_RESET */
+#define KVM_S390_RESET_POR 1
+#define KVM_S390_RESET_CLEAR 2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT 8
+#define KVM_S390_RESET_IPL 16
+    __u64 s390_reset_flags;
+    /* KVM_EXIT_S390_UCONTROL */
+    struct {
+      __u64 trans_exc_code;
+      __u32 pgm_code;
+    } s390_ucontrol;
+    /* KVM_EXIT_DCR (deprecated) */
+    struct {
+      __u32 dcrn;
+      __u32 data;
+      __u8 is_write;
+    } dcr;
+    /* KVM_EXIT_INTERNAL_ERROR */
+    struct {
+      __u32 suberror;
+      /* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
+      __u32 ndata;
+      __u64 data[16];
+    } internal;
+    /*
+     * KVM_INTERNAL_ERROR_EMULATION
+     *
+     * "struct emulation_failure" is an overlay of "struct internal"
+     * that is used for the KVM_INTERNAL_ERROR_EMULATION sub-type of
+     * KVM_EXIT_INTERNAL_ERROR.  Note, unlike other internal error
+     * sub-types, this struct is ABI!  It also needs to be backwards
+     * compatible with "struct internal".  Take special care that
+     * "ndata" is correct, that new fields are enumerated in "flags",
+     * and that each flag enumerates fields that are 64-bit aligned
+     * and sized (so that ndata+internal.data[] is valid/accurate).
+     */
+    struct {
+      __u32 suberror;
+      __u32 ndata;
+      __u64 flags;
+      __u8 insn_size;
+      __u8 insn_bytes[15];
+    } emulation_failure;
+    /* KVM_EXIT_OSI */
+    struct {
+      __u64 gprs[32];
+    } osi;
+    /* KVM_EXIT_PAPR_HCALL */
+    struct {
+      __u64 nr;
+      __u64 ret;
+      __u64 args[9];
+    } papr_hcall;
+    /* KVM_EXIT_S390_TSCH */
+    struct {
+      __u16 subchannel_id;
+      __u16 subchannel_nr;
+      __u32 io_int_parm;
+      __u32 io_int_word;
+      __u32 ipb;
+      __u8 dequeued;
+    } s390_tsch;
+    /* KVM_EXIT_EPR */
+    struct {
+      __u32 epr;
+    } epr;
+    /* KVM_EXIT_SYSTEM_EVENT */
+    struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN 1
+#define KVM_SYSTEM_EVENT_RESET 2
+#define KVM_SYSTEM_EVENT_CRASH 3
+      __u32 type;
+      __u64 flags;
+    } system_event;
+    /* KVM_EXIT_S390_STSI */
+    struct {
+      __u64 addr;
+      __u8 ar;
+      __u8 reserved;
+      __u8 fc;
+      __u8 sel1;
+      __u16 sel2;
+    } s390_stsi;
+    /* KVM_EXIT_IOAPIC_EOI */
+    struct {
+      __u8 vector;
+    } eoi;
+    /* KVM_EXIT_HYPERV */
+    struct kvm_hyperv_exit hyperv;
+    /* KVM_EXIT_ARM_NISV */
+    struct {
+      __u64 esr_iss;
+      __u64 fault_ipa;
+    } arm_nisv;
+    /* KVM_EXIT_X86_RDMSR / KVM_EXIT_X86_WRMSR */
+    struct {
+      __u8 error; /* user -> kernel */
+      __u8 pad[7];
+#define KVM_MSR_EXIT_REASON_INVAL (1 << 0)
+#define KVM_MSR_EXIT_REASON_UNKNOWN (1 << 1)
+#define KVM_MSR_EXIT_REASON_FILTER (1 << 2)
+      __u32 reason; /* kernel -> user */
+      __u32 index;  /* kernel -> user */
+      __u64 data;   /* kernel <-> user */
+    } msr;
+    /* KVM_EXIT_XEN */
+    struct kvm_xen_exit xen;
+    /* Fix the size of the union. */
+    char padding[256];
+  };
+
+/* 2048 is the size of the char array used to bound/pad the size
+ * of the union that holds sync regs.
+ */
+#define SYNC_REGS_SIZE_BYTES 2048
+  /*
+   * shared registers between kvm and userspace.
+   * kvm_valid_regs specifies the register classes set by the host
+   * kvm_dirty_regs specified the register classes dirtied by userspace
+   * struct kvm_sync_regs is architecture specific, as well as the
+   * bits for kvm_valid_regs and kvm_dirty_regs
+   */
+  __u64 kvm_valid_regs;
+  __u64 kvm_dirty_regs;
+  union {
+    struct kvm_sync_regs regs;
+    char padding[SYNC_REGS_SIZE_BYTES];
+  } s;
+};
+
+int kvm(uint8_t code[], size_t code_len) {
+  // step 1, open /dev/kvm
+  int kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC);
+  if (kvmfd == -1) {
+    printf("failed to open /dev/kvm\n");
+    return 0;
+  }
+
+  // step 2, create VM
+  int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
+  printf("vmfd %d\n", vmfd);
+  // step 3, set up user memory region
+  size_t mem_size = 0x100000; // size of user memory you want to assign
+  void *mem = mmap(0, mem_size, PROT_READ | PROT_WRITE,
+                   MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
+  printf("map mem %p\n", mem);
+  int user_entry = 0x0;
+  memcpy((void *)((size_t)mem + user_entry), code, code_len);
+  struct kvm_userspace_memory_region region = {.slot = 0,
+                                               .flags = 0,
+                                               .guest_phys_addr = 0,
+                                               .memory_size = mem_size,
+                                               .userspace_addr = (size_t)mem};
+  ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region);
+  /* end of step 3 */
+
+  // step 4, create vCPU
+  int vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
+  printf("create vcpu,fd: %p\n", vcpufd);
+  // step 5, set up memory for vCPU
+  size_t vcpu_mmap_size = ioctl(kvmfd, KVM_GET_VCPU_MMAP_SIZE, NULL);
+  struct kvm_run *run = (struct kvm_run *)mmap(
+      0, vcpu_mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);
+
+  // step 6, set up vCPU's registers
+  /* standard registers include general-purpose registers and flags */
+  struct kvm_regs regs;
+  ioctl(vcpufd, KVM_GET_REGS, &regs);
+  regs.rip = user_entry;
+  regs.rsp = 0x200000;                // stack address
+  regs.rflags = 0x2;                  // in x86 the 0x2 bit should always be set
+  ioctl(vcpufd, KVM_SET_REGS, &regs); // set registers
+
+  /* special registers include segment registers */
+  struct kvm_sregs sregs;
+  ioctl(vcpufd, KVM_GET_SREGS, &sregs);
+  sregs.cs.base = sregs.cs.selector =
+      0; // let base of code segment equal to zero
+  ioctl(vcpufd, KVM_SET_SREGS, &sregs);
+  ioctl(vcpufd, KVM_GET_SREGS, &sregs);
+// step 7, execute vm and handle exit reason
+#define KVM_EXIT_UNKNOWN 0
+#define KVM_EXIT_EXCEPTION 1
+#define KVM_EXIT_IO 2
+#define KVM_EXIT_HYPERCALL 3
+#define KVM_EXIT_DEBUG 4
+#define KVM_EXIT_HLT 5
+#define KVM_EXIT_MMIO 6
+#define KVM_EXIT_IRQ_WINDOW_OPEN 7
+#define KVM_EXIT_SHUTDOWN 8
+#define KVM_EXIT_FAIL_ENTRY 9
+#define KVM_EXIT_INTR 10
+#define KVM_EXIT_SET_TPR 11
+#define KVM_EXIT_TPR_ACCESS 12
+#define KVM_EXIT_S390_SIEIC 13
+#define KVM_EXIT_S390_RESET 14
+#define KVM_EXIT_DCR 15 /* deprecated */
+#define KVM_EXIT_NMI 16
+#define KVM_EXIT_INTERNAL_ERROR 17
+#define KVM_EXIT_OSI 18
+#define KVM_EXIT_PAPR_HCALL 19
+#define KVM_EXIT_S390_UCONTROL 20
+#define KVM_EXIT_WATCHDOG 21
+#define KVM_EXIT_S390_TSCH 22
+#define KVM_EXIT_EPR 23
+#define KVM_EXIT_SYSTEM_EVENT 24
+#define KVM_EXIT_S390_STSI 25
+#define KVM_EXIT_IOAPIC_EOI 26
+#define KVM_EXIT_HYPERV 27
+#define KVM_EXIT_ARM_NISV 28
+#define KVM_EXIT_X86_RDMSR 29
+#define KVM_EXIT_X86_WRMSR 30
+#define KVM_EXIT_DIRTY_RING_FULL 31
+#define KVM_EXIT_AP_RESET_HOLD 32
+#define KVM_EXIT_X86_BUS_LOCK 33
+#define KVM_EXIT_XEN 34
+  while (1) {
+    ioctl(vcpufd, KVM_RUN, NULL);
+    ioctl(vcpufd, KVM_GET_SREGS, &sregs);
+    printf("Guest CR3: 0x%llx\n", sregs.cr3);
+    switch (run->exit_reason) {
+    case KVM_EXIT_HLT:
+      fputs("KVM_EXIT_HLT \n", stderr);
+      return 0;
+    case KVM_EXIT_IO:
+      /* TODO: check port and direction here */
+      putchar(*(((char *)run) + run->io.data_offset));
+      printf("KVM_EXIT_IO: run->io.port = %lx \n", run->io.port);
+      break;
+    case KVM_EXIT_FAIL_ENTRY:
+      printf("KVM_EXIT_FAIL_ENTRY: hardware_entry_failure_reason = 0x%lx",
+             run->fail_entry.hardware_entry_failure_reason);
+      return 0;
+    case KVM_EXIT_INTERNAL_ERROR:
+      printf("KVM_EXIT_INTERNAL_ERROR: suberror = 0x%x",
+             run->internal.suberror);
+      return 0;
+    case KVM_EXIT_SHUTDOWN:
+      printf("KVM_EXIT_SHUTDOWN");
+      return 0;
+    default:
+      printf("Unhandled reason: %d", run->exit_reason);
+      return 0;
+    }
+  }
+}
+
+/*汇编指令解释
+0xB0 0x61 (mov al, 0x61)
+解释:将立即数 0x61(ASCII 字符 'a')加载到 AL 寄存器中。
+
+0xBA 0x17 0x02 (mov dx, 0x0217)
+Linux: ilen = 3 外中断和EPT_VIOLATION
+解释:将立即数 0x0217 加载到 DX 寄存器中。
+
+0xEE (out dx, al)
+解释:将 AL 寄存器的值输出到 DX 寄存器指定的端口。
+
+0xB0 0x0A (mov al, 0x0A)
+解释:将立即数 0x0A(换行符)加载到 AL 寄存器中。
+
+0xEE (out dx, al)
+解释:将 AL 寄存器的值输出到 DX 寄存器指定的端口。
+
+0xF4 (hlt)
+解释:执行 hlt 指令,使处理器进入休眠状态,直到下一个外部中断到来。*/
+
+int main() {
+  // uint8_t code[] = "\xB0\x61\xBA\x17\x02\xEE\xB0\n\xEE\xF4";
+  // uint8_t code[] = "\xB0\x61\xBA\x17\x02\xEE\xF4";
+  uint8_t code[] = "\xB0\x61\xF4";
+  kvm(code, sizeof(code));
+  return 0;
+}

+ 70 - 0
user/apps/c_unitest/test_mkfifo.c

@@ -0,0 +1,70 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define BUFFER_SIZE 256
+#define PIPE_NAME "/bin/fifo"
+
+int main() {
+  pid_t pid;
+  int pipe_fd;
+  char buffer[BUFFER_SIZE];
+  int bytes_read;
+  int status;
+
+  // 创建命名管道
+  mkfifo(PIPE_NAME, 0666);
+
+  // 创建子进程
+  pid = fork();
+
+  if (pid < 0) {
+    fprintf(stderr, "Fork failed\n");
+    return 1;
+  } else if (pid == 0) {
+    // 子进程
+
+    // 打开管道以供读取
+    pipe_fd = open(PIPE_NAME, O_RDONLY);
+
+    // 从管道中读取数据
+    bytes_read = read(pipe_fd, buffer, BUFFER_SIZE);
+    if (bytes_read > 0) {
+      printf("Child process received message: %s\n", buffer);
+    }
+
+    // 关闭管道文件描述符
+    close(pipe_fd);
+
+    // 删除命名管道
+    unlink(PIPE_NAME);
+
+    exit(0);
+  } else {
+    // 父进程
+
+    // 打开管道以供写入
+    pipe_fd = open(PIPE_NAME, O_WRONLY);
+
+    // 向管道写入数据
+    const char *message = "Hello from parent process";
+    write(pipe_fd, message, strlen(message) + 1);
+
+    // 关闭管道文件描述符
+    close(pipe_fd);
+
+    // 等待子进程结束
+    waitpid(pid, &status, 0);
+
+    if (WIFEXITED(status)) {
+      printf("Child process exited with status: %d\n", WEXITSTATUS(status));
+    }
+  }
+
+  return 0;
+}

+ 64 - 0
user/apps/c_unitest/test_newfstatat.c

@@ -0,0 +1,64 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#define TEST_DIR "test_dir"
+#define TEST_FILE "test_file"
+
+void create_test_files() {
+  mkdir(TEST_DIR, 0755);
+  int fd = open(TEST_FILE, O_CREAT | O_RDWR, 0644);
+  if (fd >= 0)
+    close(fd);
+}
+
+void cleanup_test_files() {
+  unlink(TEST_FILE);
+  rmdir(TEST_DIR);
+}
+
+void run_test(const char *name, int (*test_func)(), int expected) {
+  printf("Testing %s... ", name);
+  int result = test_func();
+  if (result == expected) {
+    printf("[PASS]\n");
+  } else {
+    printf("[FAILED] (expected %d, got %d)\n", expected, result);
+  }
+}
+
+int test_normal_file() {
+  struct stat st;
+  return syscall(__NR_newfstatat, AT_FDCWD, TEST_FILE, &st, 0);
+}
+
+int test_directory() {
+  struct stat st;
+  return syscall(__NR_newfstatat, AT_FDCWD, TEST_DIR, &st, 0);
+}
+
+int test_invalid_fd() {
+  struct stat st;
+  return syscall(__NR_newfstatat, -1, TEST_FILE, &st, 0);
+}
+
+int test_nonexistent_path() {
+  struct stat st;
+  return syscall(__NR_newfstatat, AT_FDCWD, "nonexistent_file", &st, 0);
+}
+
+int main() {
+  create_test_files();
+
+  run_test("normal file stat", test_normal_file, 0);
+  run_test("directory stat", test_directory, 0);
+  run_test("invalid file descriptor", test_invalid_fd, -1);
+  run_test("nonexistent path", test_nonexistent_path, -1);
+
+  cleanup_test_files();
+  return 0;
+}

+ 83 - 0
user/apps/c_unitest/test_overlayfs.c

@@ -0,0 +1,83 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+// #define LOWERDIR "/tmp/overlayfs/lower"
+// #define UPPERDIR "/tmp/overlayfs/upper"
+// #define WORKDIR "/tmp/overlayfs/work"
+// #define MERGEDDIR "/tmp/overlayfs/merged"
+
+// void create_directories()
+// {
+//     mkdir(LOWERDIR, 0755);
+//     mkdir(UPPERDIR, 0755);
+//     mkdir(WORKDIR, 0755);
+//     mkdir(MERGEDDIR, 0755);
+// }
+#define TMPDIR "/tmp"
+#define OVERLAYFSDIR "/tmp/overlayfs"
+#define LOWERDIR "/tmp/overlayfs/lower"
+#define UPPERDIR "/tmp/overlayfs/upper"
+#define WORKDIR "/tmp/overlayfs/work"
+#define MERGEDDIR "/tmp/overlayfs/merged"
+
+void create_directories() {
+  mkdir(TMPDIR, 0755);
+  mkdir(OVERLAYFSDIR, 0755);
+  mkdir(LOWERDIR, 0755);
+  mkdir(UPPERDIR, 0755);
+  mkdir(WORKDIR, 0755);
+  mkdir(MERGEDDIR, 0755);
+  printf("step1 : success\n");
+}
+
+void create_lower_file() {
+  char filepath[256];
+  snprintf(filepath, sizeof(filepath), "%s/lowerfile.txt", LOWERDIR);
+
+  int fd = open(filepath, O_CREAT | O_WRONLY, 0644);
+  if (fd < 0) {
+    perror("Failed to create file in lowerdir");
+    exit(EXIT_FAILURE);
+  }
+  write(fd, "This is a lower layer file.\n", 28);
+  close(fd);
+  printf("step2 : success\n");
+}
+
+void mount_overlayfs() {
+  char options[1024];
+  snprintf(options, sizeof(options), "lowerdir=%s,upperdir=%s,workdir=%s",
+           LOWERDIR, UPPERDIR, WORKDIR);
+
+  if (mount("overlay", MERGEDDIR, "overlay", 0, options) != 0) {
+    perror("Mount failed");
+    exit(EXIT_FAILURE);
+  }
+  printf("OverlayFS mounted successfully.\n");
+  printf("step3 : success\n");
+}
+
+void create_directory_in_merged() {
+  char dirpath[256];
+  snprintf(dirpath, sizeof(dirpath), "%s/newdir", UPPERDIR);
+
+  if (mkdir(dirpath, 0755) != 0) {
+    perror("Failed to create directory in merged dir");
+    exit(EXIT_FAILURE);
+  }
+  printf("Directory created in merged: %s\n", dirpath);
+  printf("step4 : success\n");
+}
+
+int main() {
+  create_directories();
+  mount_overlayfs();
+  create_directory_in_merged();
+  return 0;
+}

+ 0 - 0
user/apps/test_poll/main.c → user/apps/c_unitest/test_poll.c


+ 0 - 0
user/apps/test_poll/ppoll.c → user/apps/c_unitest/test_ppoll.c


+ 83 - 0
user/apps/c_unitest/test_processgroup.c

@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", fail_msg,           \
+             (unsigned long)(right), (unsigned long)(left));                   \
+    }                                                                          \
+  } while (0)
+
+// 打印进程信息
+void print_ids(const char *name) {
+  printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n", name, getpid(), getppid(),
+         getpgid(0), // 获取当前进程的 PGID
+         getsid(0)); // 获取当前进程的 SID
+}
+
+int main() {
+  printf("===== 测试进程组 =====\n");
+  print_ids("Parent");
+
+  // 创建第一个子进程
+  pid_t child1 = fork();
+  if (child1 == 0) {
+    // 子进程1:设置自己的进程组
+    printf("\n[Child1] 子进程启动...\n");
+    print_ids("Child1 (before setpgid)");
+
+    if (setpgid(0, 0) == -1) { // 将自己的 PGID 设置为自己的 PID
+      perror("setpgid failed");
+      exit(EXIT_FAILURE);
+    }
+
+    print_ids("Child1 (after setpgid)");
+
+    // Assert: PGID 应该等于 PID
+    // assert(getpgid(0) == getpid());
+    TEST_ASSERT(getpgid(0), getpid(),
+                "Successfully set child1 as processgroup leader",
+                "Child1 PGID check failed");
+
+    sleep(2); // 保持运行,便于观察
+    exit(EXIT_SUCCESS);
+  }
+
+  // 创建第二个子进程
+  pid_t child2 = fork();
+  if (child2 == 0) {
+    // 子进程2:加入第一个子进程的进程组
+    printf("\n[Child2] 子进程启动...\n");
+    print_ids("Child2 (before setpgid)");
+
+    if (setpgid(0, child1) == -1) { // 将自己的 PGID 设置为 child1 的 PID
+      perror("setpgid failed");
+      exit(EXIT_FAILURE);
+    }
+
+    print_ids("Child2 (after setpgid)");
+
+    // Assert: PGID 应该等于 child1 的 PID
+    // assert(getpgid(0) == child1);
+    TEST_ASSERT(getpgid(0), child1, "Child2 PGID is equal to Child1",
+                "Child2 PGID check failed");
+
+    sleep(2); // 保持运行,便于观察
+    exit(EXIT_SUCCESS);
+  }
+
+  // 父进程:等待子进程结束
+  waitpid(child1, NULL, 0);
+  waitpid(child2, NULL, 0);
+
+  printf("\n[Parent] 所有子进程结束后...\n");
+  print_ids("Parent");
+
+  return 0;
+}

+ 47 - 0
user/apps/c_unitest/test_pty.c

@@ -0,0 +1,47 @@
+#include <fcntl.h>
+#include <pty.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+int main() {
+  int ptm, pts;
+  char name[256];
+  struct termios term;
+
+  if (openpty(&ptm, &pts, name, NULL, NULL) == -1) {
+    perror("openpty");
+    exit(EXIT_FAILURE);
+  }
+
+  printf("slave name: %s fd: %d\n", name, pts);
+
+  tcgetattr(pts, &term);
+  term.c_lflag &= ~(ICANON | ECHO);
+  term.c_cc[VMIN] = 1;
+  term.c_cc[VTIME] = 0;
+  tcsetattr(pts, TCSANOW, &term);
+
+  printf("before print to pty slave\n");
+  dprintf(pts, "Hello world!\n");
+
+  char buf[256];
+  ssize_t n = read(ptm, buf, sizeof(buf));
+  if (n > 0) {
+    printf("read %ld bytes from slave: %.*s", n, (int)n, buf);
+  }
+
+  dprintf(ptm, "hello world from master\n");
+
+  char nbuf[256];
+  ssize_t nn = read(pts, nbuf, sizeof(nbuf));
+  if (nn > 0) {
+    printf("read %ld bytes from master: %.*s", nn, (int)nn, nbuf);
+  }
+
+  close(ptm);
+  close(pts);
+
+  return 0;
+}

+ 115 - 0
user/apps/c_unitest/test_ramfs.c

@@ -0,0 +1,115 @@
+// #include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MAX_PATH_LENGTH 100
+#define MAX_DIR_DEPTH 4
+
+int main(int argc, char const *argv[]) {
+
+  if (mkdir("/SOME", 0777) == -1) {
+    perror("Failed to create directory under /some");
+    return 1;
+  }
+
+  // Create a directory under /SOME/RAMFS
+  if (mkdir("/SOME/RAMFS", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS");
+    return 1;
+  }
+
+  // Mount the first ramfs at /SOME/RAMFS
+  if (mount("", "/SOME/RAMFS", "ramfs", 0, NULL) == -1) {
+    perror("Failed to mount ramfs at /SOME/RAMFS");
+    return 1;
+  }
+
+  if (mkdir("/SOME/RAMFS/some", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS/some");
+    return 1;
+  }
+
+  puts("Success mkdir /SOME/RAMFS/some");
+
+  // Create a directory under /SOME/RAMFS/some/another
+  if (mkdir("/SOME/RAMFS/some/another", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mkdir /SOME/RAMFS/some/another");
+
+  if (mount("", "/SOME/RAMFS/some/another", "ramfs", 0, NULL) == -1) {
+    perror("Failed to mount ramfs at /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mount on /SOME/RAMFS/some/another");
+
+  if (mkdir("/SOME/RAMFS/some/another/just_another", 0777) == -1) {
+    perror("Failed to create directory under /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mkdir /SOME/RAMFS/some/another/just_another");
+
+  if (mount("", "/SOME/RAMFS/some/another/just_another", "ramfs", 0, NULL) ==
+      -1) {
+    perror("Failed to mount ramfs at /SOME/RAMFS/some/another");
+    return 1;
+  }
+
+  puts("Success mount on /SOME/RAMFS/some/another/just_another");
+
+  // Write files under /SOME/RAMFS and /SOME/RAMFS/some/another
+  FILE *file1 = fopen("/SOME/RAMFS/file1.txt", "w");
+  if (file1 == NULL) {
+    perror("Failed to open /SOME/RAMFS/file1.txt");
+    return 1;
+  }
+  fprintf(file1, "This is file1.txt\n");
+  fclose(file1);
+
+  FILE *file2 = fopen("/SOME/RAMFS/some/another/file2.txt", "w");
+  if (file2 == NULL) {
+    perror("Failed to open /SOME/RAMFS/some/another/file2.txt");
+    return 1;
+  }
+  fprintf(file2, "This is file2.txt\n");
+  fclose(file2);
+
+  FILE *file3 = fopen("/SOME/RAMFS/some/another/just_another/file3.txt", "w+");
+  if (file3 == NULL) {
+    perror("Failed to open /SOME/RAMFS/some/another/just_another/file3.txt");
+    return 1;
+  }
+  fprintf(file3, "Multi mount behave well.\n");
+  // print file3.txt
+  char buffer[100];
+  fseek(file3, 0, SEEK_SET);
+  fread(buffer, 1, 100, file3);
+  printf("file3.txt content: %s\n", buffer);
+  fclose(file3);
+
+  // test umount with flags ( use umount2 )
+  if (umount("/SOME/RAMFS/some/another/just_another") == -1) {
+    perror("Failed to umount ramfs at /SOME/RAMFS/some/another/just_another");
+    return 1;
+  }
+
+  puts("Successful umount /SOME/RAMFS/some/another/just_another");
+
+  // delete just_another
+  if (rmdir("/SOME/RAMFS/some/another/just_another") == -1) {
+    perror("Failed to delete /SOME/RAMFS/some/another/just_another");
+    return 1;
+  }
+
+  return 0;
+}

+ 0 - 0
user/apps/test_select/main.c → user/apps/c_unitest/test_select.c


+ 77 - 0
user/apps/c_unitest/test_session.c

@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", fail_msg,           \
+             (unsigned long)(right), (unsigned long)(left));                   \
+    }                                                                          \
+  } while (0)
+
+#define TEST_CONDITION(condition, success_msg, fail_msg)                       \
+  do {                                                                         \
+    if (condition) {                                                           \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s\n", fail_msg);                                         \
+    }                                                                          \
+  } while (0)
+
+// 打印进程信息
+void print_ids(const char *name) {
+  printf("[%s] PID=%d, PPID=%d, PGID=%d, SID=%d\n", name, getpid(), getppid(),
+         getpgid(0), // 获取当前进程的 PGID
+         getsid(0)); // 获取当前进程的 SID
+}
+
+int main() {
+  printf("===== 测试 getsid =====\n");
+  print_ids("Parent");
+
+  pid_t child = fork();
+  if (child == 0) {
+    // 子进程
+    printf("\n[Child] 子进程启动...\n");
+    print_ids("Child (before setsid)");
+
+    // 创建新会话
+    pid_t newsid = setsid();
+    if (newsid == -1) {
+      perror("setsid failed");
+      exit(EXIT_FAILURE);
+    }
+
+    printf("[Child] 创建新会话成功,新 SID = %d\n", newsid);
+    print_ids("Child (after setsid)");
+
+    TEST_ASSERT(newsid, getpid(), "New sid equal to child pid",
+                "failed to set new sid");
+    TEST_ASSERT(getsid(0), getpid(), "Child sid equal to child pid",
+                "failed to set new sid");
+    TEST_ASSERT(getpgid(0), getpid(), "Child pgid equal to child pid",
+                "failed to set new sid");
+
+    exit(EXIT_SUCCESS);
+  } else if (child > 0) {
+    // 父进程
+    waitpid(child, NULL, 0); // 等待子进程结束
+    printf("\n[Parent] 子进程结束后...\n");
+    print_ids("Parent");
+
+    TEST_CONDITION(getsid(0) != child, "Parent sid unchanged",
+                   "Parent sid changed");
+    TEST_CONDITION(getpgid(0) != child, "Parent pgid unchanged",
+                   "Parent pgid changed");
+  } else {
+    perror("fork failed");
+    exit(EXIT_FAILURE);
+  }
+
+  return 0;
+}

+ 149 - 0
user/apps/c_unitest/test_shm_info.c

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

+ 38 - 0
user/apps/c_unitest/test_shm_receiver.c

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

+ 43 - 0
user/apps/c_unitest/test_shm_sender.c

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

+ 25 - 0
user/apps/c_unitest/test_sigint.c

@@ -0,0 +1,25 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// 信号处理函数
+void handle_signal(int signal) {
+  if (signal == SIGINT) {
+    printf("Caught SIGINT (Ctrl+C). Exiting gracefully...\n");
+    exit(0); // 终止程序
+  }
+}
+
+int main() {
+  // 注册信号处理函数
+  signal(SIGINT, handle_signal);
+
+  // 模拟一个长时间运行的进程
+  while (1) {
+    printf("Running... Press Ctrl+C to stop.\n");
+    sleep(5);
+  }
+
+  return 0;
+}

+ 19 - 24
user/apps/test_signal/main.c → user/apps/c_unitest/test_signal.c

@@ -24,33 +24,28 @@
 
 
 bool handle_ok = false;
 bool handle_ok = false;
 int count = 0;
 int count = 0;
-void handler(int sig)
-{
-    printf("handle %d\n", sig);
-    handle_ok = true;
-    count++;
+void handler(int sig) {
+  printf("handle %d\n", sig);
+  handle_ok = true;
+  count++;
 }
 }
 
 
-int main()
-{
-    signal(SIGKILL, &handler);
-    printf("registered.\n");
+int main() {
+  signal(SIGKILL, &handler);
+  printf("registered.\n");
 
 
-    while (1)
-    {
-        // handler(SIGKILL);
-        printf("Test signal running\n");
-        raise(SIGKILL);
-        if (handle_ok)
-        {
-            printf("Handle OK!\n");
-            handle_ok = false;
-        }
-        if (count > 0)
-        {
-            signal(SIGKILL, SIG_DFL);
-        }
+  while (1) {
+    // handler(SIGKILL);
+    printf("Test signal running\n");
+    raise(SIGKILL);
+    if (handle_ok) {
+      printf("Handle OK!\n");
+      handle_ok = false;
     }
     }
+    if (count > 0) {
+      signal(SIGKILL, SIG_DFL);
+    }
+  }
 
 
-    return 0;
+  return 0;
 }
 }

+ 0 - 0
user/apps/test_signal_restart/main.c → user/apps/c_unitest/test_signal_restart.c


+ 128 - 0
user/apps/c_unitest/test_sigprocmask.c

@@ -0,0 +1,128 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected 0x%lx, but got 0x%lx\n", fail_msg,           \
+             (unsigned long)(right), (unsigned long)(left));                   \
+    }                                                                          \
+  } while (0)
+
+static int signal_received = 0;
+
+void signal_handler(int signo) {
+  if (signo == SIGINT) {
+    printf("\nReceived SIGINT (Ctrl+C)\n");
+    signal_received = 1;
+  }
+}
+
+void print_signal_mask(const char *msg, const sigset_t *mask) {
+  printf("%s: ", msg);
+  for (int signo = 1; signo < NSIG; ++signo) {
+    if (sigismember(mask, signo)) {
+      printf("%d ", signo);
+    }
+  }
+  printf("\n");
+}
+
+// 获取当前屏蔽字的函数
+unsigned long get_signal_mask() {
+  sigset_t sigset;
+  if (sigprocmask(SIG_BLOCK, NULL, &sigset) == -1) {
+    perror("sigprocmask");
+    return -1; // 返回错误标记
+  }
+
+  // 将信号集编码为位掩码
+  unsigned long mask = 0;
+  for (int i = 1; i < NSIG; i++) {
+    if (sigismember(&sigset, i)) {
+      mask |= 1UL << (i - 1);
+    }
+  }
+  return mask;
+}
+
+int main() {
+  sigset_t new_mask, old_mask;
+  sigemptyset(&old_mask);
+
+  // 注册 SIGINT 的信号处理函数
+  if (signal(SIGINT, signal_handler) == SIG_ERR) {
+    perror("signal");
+    exit(EXIT_FAILURE);
+  }
+  printf("Signal handler for SIGINT is registered.\n");
+  signal_received = 0;
+  kill(getpid(), SIGINT);
+  sleep(5);
+
+  TEST_ASSERT(signal_received, 1, "SIGINT was received",
+              "SIGINT was not received");
+  signal_received = 0;
+
+  // 初始化新的信号集,并将 SIGINT 添加到其中
+  sigemptyset(&new_mask);
+  sigaddset(&new_mask, SIGINT);
+
+  // 打印 new_mask 的值
+  print_signal_mask("new_mask", &new_mask);
+
+  // 屏蔽 SIGINT
+  if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) < 0) {
+    perror("sigprocmask - SIG_BLOCK");
+    exit(EXIT_FAILURE);
+  }
+
+  // 打印 old_mask 的值
+  print_signal_mask("old_mask", &old_mask);
+
+  // 检查 SIGINT 是否被屏蔽
+  unsigned long actual_mask = get_signal_mask();
+  unsigned long expected_mask = (1UL << (SIGINT - 1));
+  TEST_ASSERT(actual_mask, expected_mask, "Signal mask is as expected",
+              "Signal mask mismatch");
+
+  printf("SIGINT is now blocked.\n");
+  signal_received = 0;
+  // 向当前进程发送 SIGINT
+  kill(getpid(), SIGINT);
+
+  // 等待 5 秒,以便测试 SIGINT 是否被屏蔽
+  sleep(5);
+  TEST_ASSERT(signal_received, 0, "SIGINT was blocked",
+              "SIGINT was not blocked");
+  signal_received = 0;
+  // 恢复原来的信号屏蔽字
+  if (sigprocmask(SIG_SETMASK, &old_mask, &old_mask) < 0) {
+    perror("sigprocmask - SIG_SETMASK");
+    exit(EXIT_FAILURE);
+  }
+  print_signal_mask("old_mask returned", &old_mask);
+
+  // 检查 SIGINT 是否被解除屏蔽
+  actual_mask = get_signal_mask();
+  expected_mask = 0;
+  TEST_ASSERT(actual_mask, expected_mask, "Signal mask is as expected",
+              "Signal mask mismatch");
+
+  printf("SIGINT is now unblocked.\n");
+
+  signal_received = 0;
+  kill(getpid(), SIGINT);
+
+  // 等待 5 秒,以便测试 SIGINT 是否解除屏蔽
+  sleep(5);
+  TEST_ASSERT(signal_received, 1, "SIGINT was received",
+              "SIGINT was not received");
+
+  printf("Exiting program.\n");
+  return 0;
+}

+ 0 - 0
user/apps/test_stack/main.c → user/apps/c_unitest/test_stack.c


+ 36 - 0
user/apps/c_unitest/test_statfs.c

@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <sys/statfs.h>
+
+int main(int argc, char **argv) {
+  struct statfs diskInfo;
+
+  statfs("/bin/about.elf", &diskInfo);
+  unsigned long long blocksize1 = diskInfo.f_bsize; //每个block里包含的字节数
+  unsigned long long totalsize =
+      blocksize1 * diskInfo.f_blocks; //总的字节数,f_blocks为block的数目
+  printf("Total_size=%llu B =%llu KB =%llu MB = %llu GB\n", totalsize,
+         totalsize >> 10, totalsize >> 20, totalsize >> 30);
+
+  /* 2.获取一下剩余空间和可用空间的大小 */
+  unsigned long long freeDisk = diskInfo.f_bfree * blocksize1; //剩余空间的大小
+  unsigned long long availableDisk =
+      diskInfo.f_bavail * blocksize1; //可用空间大小
+  printf("Disk_free=%llu MB =%llu GB Disk_available=%llu MB = %llu GB\n",
+         freeDisk >> 20, freeDisk >> 30, availableDisk >> 20,
+         availableDisk >> 30);
+
+  printf("====================\n");
+  printf("diskInfo address: %p\n", diskInfo);
+  printf("f_type= %lu\n", diskInfo.f_type);
+  printf("f_bsize = %lu\n", diskInfo.f_bsize);
+  printf("f_blocks = %d\n", diskInfo.f_blocks);
+  printf("f_bfree = %lu\n", diskInfo.f_bfree);
+  printf("b_avail = %d\n", diskInfo.f_bavail);
+  printf("f_files = %d\n", diskInfo.f_files);
+  printf("f_ffree = %lu\n", diskInfo.f_ffree);
+  printf("f_fsid = %ld\n", diskInfo.f_fsid);
+  printf("f_namelen = %ld\n", diskInfo.f_namelen);
+  printf("f_frsize = %ld\n", diskInfo.f_frsize);
+  printf("f_flags = %ld\n", diskInfo.f_flags);
+  return 0;
+}

+ 1 - 1
user/apps/test_uart/main.c → user/apps/c_unitest/test_uart.c

@@ -13,7 +13,7 @@ int main() {
     n = read(fd, buf, 1);
     n = read(fd, buf, 1);
     close(fd);
     close(fd);
     fd = open("/dev/char/uart:1088", O_WRONLY | O_NONBLOCK);
     fd = open("/dev/char/uart:1088", O_WRONLY | O_NONBLOCK);
-    if (n != 0) {               // 添加字符串结束符
+    if (n != 0) {                    // 添加字符串结束符
       printf("Received: %s\n", buf); // 打印接收到的数据
       printf("Received: %s\n", buf); // 打印接收到的数据
       if (buf[0] == 'g') {
       if (buf[0] == 'g') {
         break;
         break;

+ 11 - 0
user/apps/c_unitest/test_utimensat.c

@@ -0,0 +1,11 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main() {
+  int res = utimensat(AT_FDCWD, "/bin/about.elf", NULL, 0);
+  printf("utimensat res = %d\n", res);
+}

Some files were not shown because too many files changed in this diff