Browse Source

新增系统调用,并对照linux-6.1.9改写sys_wait4 (#440)

* 1. 新增以下系统调用
            - SYS_LSTAT
            - SYS_READV
            - SYS_ACCESS
            - SYS_UNLINK
            - SYS_CHMOD
            - SYS_FCHMOD
            - SYS_UMASK
            - SYS_SYSINFO
            - SYS_CLOCK_GETTIME
            - SYS_FCHMODAT
            - SYS_FACCESSAT

2. 修改sys_wait4,使得其部分符合Linux的行为(还是有些地方不符合的,详情请对比linux-6.1.9的sys_wait4接口)
LoGin 1 year ago
parent
commit
bf4a48994a

+ 36 - 0
kernel/src/arch/x86_64/ipc/signal.rs

@@ -277,6 +277,42 @@ bitflags! {
     }
 }
 
+/// SIGCHLD si_codes
+#[derive(Debug, Clone, Copy, PartialEq, Eq, ToPrimitive)]
+#[allow(dead_code)]
+pub enum SigChildCode {
+    /// child has exited
+    ///
+    /// CLD_EXITED
+    Exited = 1,
+    /// child was killed
+    ///
+    /// CLD_KILLED
+    Killed = 2,
+    /// child terminated abnormally
+    ///
+    /// CLD_DUMPED
+    Dumped = 3,
+    /// traced child has trapped
+    ///
+    /// CLD_TRAPPED
+    Trapped = 4,
+    /// child has stopped
+    ///
+    /// CLD_STOPPED
+    Stopped = 5,
+    /// stopped child has continued
+    ///
+    /// CLD_CONTINUED
+    Continued = 6,
+}
+
+impl Into<i32> for SigChildCode {
+    fn into(self) -> i32 {
+        self as i32
+    }
+}
+
 #[repr(C, align(16))]
 #[derive(Debug, Clone, Copy)]
 pub struct SigFrame {

+ 7 - 6
kernel/src/arch/x86_64/process/syscall.rs

@@ -22,15 +22,16 @@ impl Syscall {
         envp: Vec<String>,
         regs: &mut TrapFrame,
     ) -> Result<(), SystemError> {
-        // kdebug!(
-        //     "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
+        // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
+        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+        let pcb = ProcessManager::current_pcb();
+        // crate::kdebug!(
+        //     "pid: {:?}  do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
+        //     pcb.pid(),
         //     path,
         //     argv,
         //     envp
         // );
-        // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
-        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
-        let pcb = ProcessManager::current_pcb();
 
         let mut basic_info = pcb.basic_mut();
         // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
@@ -109,7 +110,7 @@ impl Syscall {
 
         // kdebug!("regs: {:?}\n", regs);
 
-        // kdebug!(
+        // crate::kdebug!(
         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
         //     load_result.entry_point()
         // );

+ 36 - 4
kernel/src/arch/x86_64/syscall.rs

@@ -7,15 +7,25 @@ use crate::{
     ipc::signal_types::SignalArch,
     libs::align::SafeForZero,
     mm::VirtAddr,
+    process::ProcessManager,
     syscall::{Syscall, SystemError, SYS_RT_SIGRETURN},
 };
 use alloc::string::String;
 
 use super::{interrupt::TrapFrame, mm::barrier::mfence};
 
+pub const SYS_LSTAT: usize = 6;
+pub const SYS_READV: usize = 19;
 pub const SYS_ACCESS: usize = 21;
-pub const SYS_PRLIMIT64: usize = 302;
+pub const SYS_UNLINK: usize = 87;
+pub const SYS_CHMOD: usize = 90;
+pub const SYS_FCHMOD: usize = 91;
+pub const SYS_UMASK: usize = 95;
+pub const SYS_SYSINFO: usize = 99;
+pub const SYS_CLOCK_GETTIME: usize = 228;
+pub const SYS_FCHMODAT: usize = 268;
 pub const SYS_FACCESSAT: usize = 269;
+pub const SYS_PRLIMIT64: usize = 302;
 pub const SYS_FACCESSAT2: usize = 439;
 
 /// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体
@@ -44,9 +54,15 @@ extern "C" {
 }
 
 macro_rules! syscall_return {
-    ($val:expr, $regs:expr) => {{
+    ($val:expr, $regs:expr, $show:expr) => {{
         let ret = $val;
         $regs.rax = ret as u64;
+
+        if $show {
+            let pid = ProcessManager::current_pcb().pid();
+            crate::kdebug!("syscall return:pid={:?},ret= {:?}\n", pid, ret as isize);
+        }
+
         unsafe {
             CurrentIrqArch::interrupt_disable();
         }
@@ -69,18 +85,34 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) -> () {
         frame.r9 as usize,
     ];
     mfence();
+    let pid = ProcessManager::current_pcb().pid();
+    let show = false;
+    // let show = if syscall_num != SYS_SCHED && pid.data() > 3 {
+    //     true
+    // } else {
+    //     false
+    // };
+
+    if show {
+        crate::kdebug!("syscall: pid: {:?}, num={:?}\n", pid, syscall_num);
+    }
 
     // Arch specific syscall
     match syscall_num {
         SYS_RT_SIGRETURN => {
-            syscall_return!(X86_64SignalArch::sys_rt_sigreturn(frame) as usize, frame);
+            syscall_return!(
+                X86_64SignalArch::sys_rt_sigreturn(frame) as usize,
+                frame,
+                show
+            );
         }
         _ => {}
     }
     syscall_return!(
         Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize)
             as u64,
-        frame
+        frame,
+        show
     );
 }
 

+ 22 - 8
kernel/src/filesystem/vfs/core.rs

@@ -16,10 +16,15 @@ use crate::{
         vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType},
     },
     kdebug, kerror, kinfo,
+    process::ProcessManager,
     syscall::SystemError,
 };
 
-use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId, MAX_PATHLEN};
+use super::{
+    file::FileMode,
+    utils::{rsplit_path, user_path_at},
+    IndexNode, InodeId, MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES,
+};
 
 /// @brief 原子地生成新的Inode号。
 /// 请注意,所有的inode号都需要通过该函数来生成.全局的inode号,除了以下两个特殊的以外,都是唯一的
@@ -206,13 +211,17 @@ pub fn do_mkdir(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
 }
 
 /// @brief 删除文件夹
-pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
+pub fn do_remove_dir(dirfd: i32, path: &str) -> Result<u64, SystemError> {
     // 文件名过长
     if path.len() > MAX_PATHLEN as usize {
         return Err(SystemError::ENAMETOOLONG);
     }
 
-    let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
+    let pcb = ProcessManager::current_pcb();
+    let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path.to_string())?;
+
+    let inode: Result<Arc<dyn IndexNode>, SystemError> =
+        inode_begin.lookup_follow_symlink(remain_path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES);
 
     if inode.is_err() {
         let errno = inode.unwrap_err();
@@ -222,9 +231,10 @@ pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
         }
     }
 
-    let (filename, parent_path) = rsplit_path(path);
+    let (filename, parent_path) = rsplit_path(&remain_path);
     // 查找父目录
-    let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
+    let parent_inode: Arc<dyn IndexNode> = inode_begin
+        .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
 
     if parent_inode.metadata()?.file_type != FileType::Dir {
         return Err(SystemError::ENOTDIR);
@@ -242,13 +252,16 @@ pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
 }
 
 /// @brief 删除文件
-pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
+pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> {
     // 文件名过长
     if path.len() > MAX_PATHLEN as usize {
         return Err(SystemError::ENAMETOOLONG);
     }
+    let pcb = ProcessManager::current_pcb();
+    let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path.to_string())?;
 
-    let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
+    let inode: Result<Arc<dyn IndexNode>, SystemError> =
+        inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
 
     if inode.is_err() {
         let errno = inode.clone().unwrap_err();
@@ -264,7 +277,8 @@ pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
 
     let (filename, parent_path) = rsplit_path(path);
     // 查找父目录
-    let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
+    let parent_inode: Arc<dyn IndexNode> = inode_begin
+        .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
 
     if parent_inode.metadata()?.file_type != FileType::Dir {
         return Err(SystemError::ENOTDIR);

+ 3 - 0
kernel/src/filesystem/vfs/file.rs

@@ -19,6 +19,7 @@ use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
 
 /// 文件私有信息的枚举类型
 #[derive(Debug, Clone)]
+#[allow(dead_code)]
 pub enum FilePrivateData {
     /// 管道文件私有信息
     Pipefs(PipeFsPrivateData),
@@ -198,6 +199,7 @@ impl File {
     }
 
     /// @brief 根据inode号获取子目录项的名字
+    #[allow(dead_code)]
     pub fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
         return self.inode.get_entry_name(ino);
     }
@@ -535,6 +537,7 @@ impl FileDescriptorVec {
         return Ok(());
     }
 
+    #[allow(dead_code)]
     pub fn iter(&self) -> FileDescriptorIterator {
         return FileDescriptorIterator::new(self);
     }

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

@@ -1,5 +1,3 @@
-#![allow(dead_code)]
-
 pub mod core;
 pub mod fcntl;
 pub mod file;
@@ -50,6 +48,7 @@ pub enum FileType {
     Socket,
 }
 
+#[allow(dead_code)]
 #[derive(Debug, Clone)]
 pub enum SpecialNodeData {
     /// 管道文件
@@ -62,6 +61,7 @@ pub enum SpecialNodeData {
 
 /* these are defined by POSIX and also present in glibc's dirent.h */
 /// 完整含义请见 http://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html
+#[allow(dead_code)]
 pub const DT_UNKNOWN: u16 = 0;
 /// 命名管道,或者FIFO
 pub const DT_FIFO: u16 = 1;
@@ -78,7 +78,9 @@ pub const DT_LNK: u16 = 10;
 // 是一个socket
 pub const DT_SOCK: u16 = 12;
 // 这个是抄Linux的,还不知道含义
+#[allow(dead_code)]
 pub const DT_WHT: u16 = 14;
+#[allow(dead_code)]
 pub const DT_MAX: u16 = 16;
 
 /// vfs容许的最大的符号链接跳转次数

+ 40 - 5
kernel/src/filesystem/vfs/open.rs

@@ -1,14 +1,20 @@
-use crate::syscall::SystemError;
+use crate::{
+    process::ProcessManager,
+    syscall::{user_access::check_and_clone_cstr, SystemError},
+};
 
-use super::{fcntl::AtFlags, syscall::ModeType};
+use super::{
+    fcntl::AtFlags, syscall::ModeType, utils::user_path_at, MAX_PATHLEN,
+    VFS_MAX_FOLLOW_SYMLINK_TIMES,
+};
 
 pub(super) fn do_faccessat(
-    _dirfd: i32,
-    _pathname: *const u8,
+    dirfd: i32,
+    path: *const u8,
     mode: ModeType,
     flags: u32,
 ) -> Result<usize, SystemError> {
-    if (mode.bits() & (!ModeType::S_IXUGO.bits())) != 0 {
+    if (mode.bits() & (!ModeType::S_IRWXO.bits())) != 0 {
         return Err(SystemError::EINVAL);
     }
 
@@ -22,6 +28,35 @@ pub(super) fn do_faccessat(
 
     // let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0;
 
+    let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
+
+    if path.len() == 0 {
+        return Err(SystemError::EINVAL);
+    }
+
+    let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
+
+    // 如果找不到文件,则返回错误码ENOENT
+    let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
+
     // todo: 接着完善(可以借鉴linux 6.1.9的do_faccessat)
     return Ok(0);
 }
+
+pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError> {
+    let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
+
+    if path.len() == 0 {
+        return Err(SystemError::EINVAL);
+    }
+
+    let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
+
+    // 如果找不到文件,则返回错误码ENOENT
+    let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
+
+    kwarn!("do_fchmodat: not implemented yet\n");
+    // todo: 真正去改变文件的权限
+
+    return Ok(0);
+}

+ 97 - 27
kernel/src/filesystem/vfs/syscall.rs

@@ -9,7 +9,7 @@ use alloc::{
 use crate::{
     driver::base::{block::SeekFrom, device::DeviceNumber},
     filesystem::vfs::file::FileDescriptorVec,
-    include::bindings::bindings::{verify_area, AT_REMOVEDIR, PROC_MAX_FD_NUM},
+    include::bindings::bindings::{verify_area, PROC_MAX_FD_NUM},
     kerror,
     libs::rwlock::RwLockWriteGuard,
     mm::VirtAddr,
@@ -25,7 +25,7 @@ use super::{
     core::{do_mkdir, do_remove_dir, do_unlink_at},
     fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
     file::{File, FileMode},
-    open::do_faccessat,
+    open::{do_faccessat, do_fchmodat},
     utils::{rsplit_path, user_path_at},
     Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
 };
@@ -153,15 +153,21 @@ impl Syscall {
     /// @param o_flags 打开文件的标志位
     ///
     /// @return 文件描述符编号,或者是错误码
-    pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
+    pub fn open(path: &str, mode: FileMode, follow_symlink: bool) -> Result<usize, SystemError> {
         // kdebug!("open: path: {}, mode: {:?}", path, mode);
         // 文件名过长
         if path.len() > MAX_PATHLEN as usize {
             return Err(SystemError::ENAMETOOLONG);
         }
 
-        let inode: Result<Arc<dyn IndexNode>, SystemError> =
-            ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
+        let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup_follow_symlink(
+            path,
+            if follow_symlink {
+                VFS_MAX_FOLLOW_SYMLINK_TIMES
+            } else {
+                0
+            },
+        );
 
         let inode: Arc<dyn IndexNode> = if inode.is_err() {
             let errno = inode.unwrap_err();
@@ -457,15 +463,12 @@ impl Syscall {
     /// - `flags`:标志位
     ///
     ///
-    pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
-        // kdebug!("sys_unlink_at={path:?}");
-        if (flags & (!AT_REMOVEDIR)) != 0 {
-            return Err(SystemError::EINVAL);
-        }
+    pub fn unlinkat(dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
+        let flags = AtFlags::from_bits(flags as i32).ok_or(SystemError::EINVAL)?;
 
-        if (flags & AT_REMOVEDIR) > 0 {
+        if flags.contains(AtFlags::AT_REMOVEDIR) {
             // kdebug!("rmdir");
-            match do_remove_dir(&pathname) {
+            match do_remove_dir(dirfd, &pathname) {
                 Err(err) => {
                     kerror!("Failed to Remove Directory, Error Code = {:?}", err);
                     return Err(err);
@@ -476,7 +479,7 @@ impl Syscall {
             }
         }
 
-        match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) {
+        match do_unlink_at(dirfd, &pathname) {
             Err(err) => {
                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
                 return Err(err);
@@ -487,6 +490,25 @@ impl Syscall {
         }
     }
 
+    pub fn unlink(pathname: *const u8) -> Result<usize, SystemError> {
+        if pathname.is_null() {
+            return Err(SystemError::EFAULT);
+        }
+        let ureader = UserBufferReader::new(pathname, MAX_PATHLEN, true)?;
+
+        let buf: &[u8] = ureader.buffer(0).unwrap();
+
+        let pathname: &CStr = CStr::from_bytes_until_nul(buf).map_err(|_| SystemError::EINVAL)?;
+
+        let pathname: &str = pathname.to_str().map_err(|_| SystemError::EINVAL)?;
+        if pathname.len() >= MAX_PATHLEN {
+            return Err(SystemError::ENAMETOOLONG);
+        }
+        let pathname = pathname.trim();
+
+        return do_unlink_at(AtFlags::AT_FDCWD.bits(), pathname).map(|v| v as usize);
+    }
+
     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
         let binding = ProcessManager::current_pcb().fd_table();
@@ -730,13 +752,6 @@ impl Syscall {
         return Ok(kstat);
     }
 
-    fn do_stat(path: &str) -> Result<PosixKstat, SystemError> {
-        let fd = Self::open(path, FileMode::O_RDONLY)?;
-        let ret = Self::do_fstat(fd as i32);
-        Self::close(fd)?;
-        ret
-    }
-
     pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
         let kstat = Self::do_fstat(fd)?;
         if usr_kstat.is_null() {
@@ -749,11 +764,17 @@ impl Syscall {
     }
 
     pub fn stat(path: &str, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
-        let fd = Self::open(path, FileMode::O_RDONLY)?;
-        Self::fstat(fd as i32, user_kstat).map_err(|e| {
-            Self::close(fd).ok();
-            e
-        })
+        let fd = Self::open(path, FileMode::O_RDONLY, true)?;
+        let r = Self::fstat(fd as i32, user_kstat);
+        Self::close(fd).ok();
+        return r;
+    }
+
+    pub fn lstat(path: &str, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
+        let fd = Self::open(path, FileMode::O_RDONLY, false)?;
+        let r = Self::fstat(fd as i32, user_kstat);
+        Self::close(fd).ok();
+        return r;
     }
 
     pub fn mknod(
@@ -799,6 +820,20 @@ impl Syscall {
         Self::write(fd, &data)
     }
 
+    pub fn readv(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> {
+        // IoVecs会进行用户态检验
+        let mut iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, true) }?;
+
+        let mut data = Vec::new();
+        data.resize(iovecs.0.iter().map(|x| x.len()).sum(), 0);
+
+        let len = Self::read(fd, &mut data)?;
+
+        iovecs.scatter(&data[..len]);
+
+        return Ok(len);
+    }
+
     pub fn readlink_at(
         dirfd: i32,
         path: *const u8,
@@ -840,7 +875,7 @@ impl Syscall {
         return do_faccessat(
             AtFlags::AT_FDCWD.bits(),
             pathname,
-            ModeType::from_bits_truncate(mode),
+            ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
             0,
         );
     }
@@ -851,7 +886,42 @@ impl Syscall {
         mode: u32,
         flags: u32,
     ) -> Result<usize, SystemError> {
-        return do_faccessat(dirfd, pathname, ModeType::from_bits_truncate(mode), flags);
+        return do_faccessat(
+            dirfd,
+            pathname,
+            ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
+            flags,
+        );
+    }
+
+    pub fn chmod(pathname: *const u8, mode: u32) -> Result<usize, SystemError> {
+        return do_fchmodat(
+            AtFlags::AT_FDCWD.bits(),
+            pathname,
+            ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
+        );
+    }
+
+    pub fn fchmodat(dirfd: i32, pathname: *const u8, mode: u32) -> Result<usize, SystemError> {
+        return do_fchmodat(
+            dirfd,
+            pathname,
+            ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
+        );
+    }
+
+    pub fn fchmod(fd: i32, mode: u32) -> Result<usize, SystemError> {
+        let _mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?;
+        let binding = ProcessManager::current_pcb().fd_table();
+        let fd_table_guard = binding.read();
+        let _file = fd_table_guard
+            .get_file_by_fd(fd)
+            .ok_or(SystemError::EBADF)?;
+
+        // fchmod没完全实现,因此不修改文件的权限
+        // todo: 实现fchmod
+        kwarn!("fchmod not fully implemented");
+        return Ok(0);
     }
 }
 

+ 2 - 1
kernel/src/filesystem/vfs/utils.rs

@@ -7,6 +7,7 @@ use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE};
 /// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
 ///
 /// 举例:对于 /123/456/789/   本函数返回的第一个值为123, 第二个值为456/789
+#[allow(dead_code)]
 pub fn split_path(path: &str) -> (&str, Option<&str>) {
     let mut path_split: core::str::SplitN<&str> = path.trim_matches('/').splitn(2, "/");
     let comp = path_split.next().unwrap_or("");
@@ -30,7 +31,7 @@ pub fn rsplit_path(path: &str) -> (&str, Option<&str>) {
 ///
 /// ## 返回值
 ///
-/// 返回值为(需要lookup的inode, 剩余的path)
+/// 返回值为(需要执行lookup的inode, 剩余的path)
 pub fn user_path_at(
     pcb: &Arc<ProcessControlBlock>,
     dirfd: i32,

+ 1 - 0
kernel/src/ipc/pipe.rs

@@ -128,6 +128,7 @@ impl IndexNode for LockedPipeInode {
             // 否则在读等待队列中睡眠,并释放锁
             unsafe {
                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
+
                 inode.read_wait_queue.sleep_without_schedule();
                 drop(inode);
 

+ 5 - 0
kernel/src/ipc/signal_types.rs

@@ -335,6 +335,11 @@ impl Default for SigPending {
 }
 
 impl SigPending {
+    /// 判断是否有待处理的信号
+    pub fn has_pending(&self) -> bool {
+        return !self.signal.is_empty();
+    }
+
     pub fn signal(&self) -> SigSet {
         self.signal
     }

+ 1 - 0
kernel/src/lib.rs

@@ -7,6 +7,7 @@
 #![feature(const_trait_impl)]
 #![feature(const_refs_to_cell)]
 #![feature(core_intrinsics)]
+#![feature(cstr_from_bytes_until_nul)]
 #![feature(c_void_variant)]
 #![feature(drain_filter)]
 #![feature(inline_const)]

+ 253 - 0
kernel/src/process/exit.rs

@@ -0,0 +1,253 @@
+use core::intrinsics::likely;
+
+use alloc::sync::Arc;
+
+use crate::{
+    arch::{
+        ipc::signal::{SigChildCode, Signal},
+        sched::sched,
+        CurrentIrqArch,
+    },
+    exception::InterruptArch,
+    syscall::{user_access::UserBufferWriter, SystemError},
+};
+
+use super::{
+    abi::WaitOption, pid::PidType, resource::RUsage, Pid, ProcessControlBlock, ProcessManager,
+    ProcessState,
+};
+
+/// 内核wait4时的参数
+#[derive(Debug)]
+pub struct KernelWaitOption<'a> {
+    pub pid_type: PidType,
+    pub pid: Pid,
+    pub options: WaitOption,
+    pub ret_status: i32,
+    pub ret_info: Option<WaitIdInfo>,
+    pub ret_rusage: Option<&'a mut RUsage>,
+    pub no_task_error: Option<SystemError>,
+}
+
+#[derive(Debug, Clone)]
+pub struct WaitIdInfo {
+    pub pid: Pid,
+    pub status: i32,
+    pub cause: i32,
+}
+
+impl<'a> KernelWaitOption<'a> {
+    pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self {
+        Self {
+            pid_type,
+            pid,
+            options,
+            ret_status: 0,
+            ret_info: None,
+            ret_rusage: None,
+            no_task_error: None,
+        }
+    }
+}
+
+pub fn kernel_wait4(
+    mut pid: i64,
+    wstatus_buf: Option<UserBufferWriter<'_>>,
+    options: WaitOption,
+    rusage_buf: Option<&mut RUsage>,
+) -> Result<usize, SystemError> {
+    // i64::MIN is not defined
+    if pid == i64::MIN {
+        return Err(SystemError::ESRCH);
+    }
+
+    // 判断pid类型
+    let pidtype: PidType;
+
+    if pid == -1 {
+        pidtype = PidType::MAX;
+    } else if pid < 0 {
+        pidtype = PidType::PGID;
+        kwarn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
+        pid = -pid;
+    } else if pid == 0 {
+        pidtype = PidType::PGID;
+        kwarn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
+        pid = ProcessManager::current_pcb().pid().data() as i64;
+    } else {
+        pidtype = PidType::PID;
+    }
+
+    let pid = Pid(pid as usize);
+
+    // 构造参数
+    let mut kwo = KernelWaitOption::new(pidtype, pid, options);
+
+    kwo.options.insert(WaitOption::WEXITED);
+    kwo.ret_rusage = rusage_buf;
+
+    // 调用do_wait,执行等待
+    let r = do_wait(&mut kwo)?;
+
+    // 如果有wstatus_buf,则将wstatus写入用户空间
+    if let Some(mut wstatus_buf) = wstatus_buf {
+        let wstatus = if let Some(ret_info) = &kwo.ret_info {
+            ret_info.status
+        } else {
+            kwo.ret_status
+        };
+        wstatus_buf.copy_one_to_user(&wstatus, 0)?;
+    }
+
+    return Ok(r);
+}
+
+/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/exit.c#1573
+fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
+    let mut retval: Result<usize, SystemError>;
+    // todo: 在signal struct里面增加等待队列,并在这里初始化子进程退出的回调,使得子进程退出时,能唤醒当前进程。
+
+    loop {
+        kwo.no_task_error = Some(SystemError::ECHILD);
+        let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD);
+        if kwo.pid_type != PidType::MAX && child_pcb.is_err() {
+            if let Some(err) = &kwo.no_task_error {
+                retval = Err(err.clone());
+            } else {
+                retval = Ok(0);
+            }
+
+            if !kwo.options.contains(WaitOption::WNOHANG) {
+                retval = Err(SystemError::ERESTARTSYS);
+                if ProcessManager::current_pcb()
+                    .sig_info_irqsave()
+                    .sig_pending()
+                    .has_pending()
+                    == false
+                {
+                    // todo: 增加子进程退出的回调后,这里可以直接等待在自身的child_wait等待队列上。
+                    continue;
+                } else {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+
+        if kwo.pid_type == PidType::PID {
+            let child_pcb = child_pcb.unwrap();
+            // 获取weak引用,以便于在do_waitpid中能正常drop pcb
+            let child_weak = Arc::downgrade(&child_pcb);
+            let r = do_waitpid(child_pcb, kwo);
+            if r.is_some() {
+                return r.unwrap();
+            } else {
+                child_weak.upgrade().unwrap().wait_queue.sleep();
+            }
+        } else if kwo.pid_type == PidType::MAX {
+            // 等待任意子进程
+            // todo: 这里有问题!如果正在for循环的过程中,子进程退出了,可能会导致父进程永远等待。
+            let current_pcb = ProcessManager::current_pcb();
+            let rd_childen = current_pcb.children.read();
+            let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+            for pid in rd_childen.iter() {
+                let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
+                if pcb.sched_info().state().is_exited() {
+                    kwo.ret_status = pcb.sched_info().state().exit_code().unwrap() as i32;
+                    drop(pcb);
+                    unsafe { ProcessManager::release(pid.clone()) };
+                    return Ok(pid.clone().into());
+                } else {
+                    unsafe { pcb.wait_queue.sleep_without_schedule() };
+                }
+            }
+            drop(irq_guard);
+            sched();
+        } else {
+            // todo: 对于pgid的处理
+            kwarn!("kernel_wait4: currently not support {:?}", kwo.pid_type);
+            return Err(SystemError::EINVAL);
+        }
+    }
+
+    return retval;
+}
+
+fn do_waitpid(
+    child_pcb: Arc<ProcessControlBlock>,
+    kwo: &mut KernelWaitOption,
+) -> Option<Result<usize, SystemError>> {
+    let state = child_pcb.sched_info().state();
+    // 获取退出码
+    match state {
+        ProcessState::Runnable => {
+            if kwo.options.contains(WaitOption::WNOHANG)
+                || kwo.options.contains(WaitOption::WNOWAIT)
+            {
+                if let Some(info) = &mut kwo.ret_info {
+                    *info = WaitIdInfo {
+                        pid: child_pcb.pid(),
+                        status: Signal::SIGCONT as i32,
+                        cause: SigChildCode::Continued.into(),
+                    };
+                } else {
+                    kwo.ret_status = 0xffff;
+                }
+
+                return Some(Ok(0));
+            }
+        }
+        ProcessState::Blocked(_) | ProcessState::Stopped => {
+            // todo: 在stopped里面,添加code字段,表示停止的原因
+            let exitcode = 0;
+            // 由于目前不支持ptrace,因此这个值为false
+            let ptrace = false;
+
+            if (!ptrace) && (!kwo.options.contains(WaitOption::WUNTRACED)) {
+                kwo.ret_status = 0;
+                return Some(Ok(0));
+            }
+
+            if likely(!(kwo.options.contains(WaitOption::WNOWAIT))) {
+                kwo.ret_status = (exitcode << 8) | 0x7f;
+            }
+            if let Some(infop) = &mut kwo.ret_info {
+                *infop = WaitIdInfo {
+                    pid: child_pcb.pid(),
+                    status: exitcode,
+                    cause: SigChildCode::Stopped.into(),
+                };
+            }
+
+            return Some(Ok(child_pcb.pid().data()));
+        }
+        ProcessState::Exited(status) => {
+            let pid = child_pcb.pid();
+            // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
+
+            if likely(!kwo.options.contains(WaitOption::WEXITED)) {
+                return None;
+            }
+
+            // todo: 增加对线程组的group leader的处理
+
+            if let Some(infop) = &mut kwo.ret_info {
+                *infop = WaitIdInfo {
+                    pid,
+                    status: status as i32,
+                    cause: SigChildCode::Exited.into(),
+                };
+            }
+
+            kwo.ret_status = status as i32;
+
+            drop(child_pcb);
+            // kdebug!("wait4: to release {pid:?}");
+            unsafe { ProcessManager::release(pid) };
+            return Some(Ok(pid.into()));
+        }
+    };
+
+    return None;
+}

+ 15 - 0
kernel/src/process/mod.rs

@@ -55,6 +55,7 @@ use self::kthread::WorkerPrivate;
 pub mod abi;
 pub mod c_adapter;
 pub mod exec;
+pub mod exit;
 pub mod fork;
 pub mod idle;
 pub mod init;
@@ -473,6 +474,7 @@ impl ProcessState {
         return matches!(self, ProcessState::Blocked(true));
     }
 
+    /// Returns `true` if the process state is [`Exited`].
     #[inline(always)]
     pub fn is_exited(&self) -> bool {
         return matches!(self, ProcessState::Exited(_));
@@ -485,6 +487,15 @@ impl ProcessState {
     pub fn is_stopped(&self) -> bool {
         matches!(self, ProcessState::Stopped)
     }
+
+    /// Returns exit code if the process state is [`Exited`].
+    #[inline(always)]
+    pub fn exit_code(&self) -> Option<usize> {
+        match self {
+            ProcessState::Exited(code) => Some(*code),
+            _ => None,
+        }
+    }
 }
 
 bitflags! {
@@ -848,6 +859,10 @@ impl ProcessControlBlock {
         self.sig_info.read()
     }
 
+    pub fn sig_info_irqsave(&self) -> RwLockReadGuard<ProcessSignalInfo> {
+        self.sig_info.read_irqsave()
+    }
+
     pub fn try_siginfo(&self, times: u8) -> Option<RwLockReadGuard<ProcessSignalInfo>> {
         for _ in 0..times {
             if let Some(r) = self.sig_info.try_read() {

+ 40 - 106
kernel/src/process/syscall.rs

@@ -8,13 +8,13 @@ use alloc::{
 
 use super::{
     abi::WaitOption,
+    exit::kernel_wait4,
     fork::{CloneFlags, KernelCloneArgs},
     resource::{RLimit64, RLimitID, RUsage, RUsageWho},
-    KernelStack, Pid, ProcessManager, ProcessState,
+    KernelStack, Pid, ProcessManager,
 };
 use crate::{
-    arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch, MMArch},
-    exception::InterruptArch,
+    arch::{interrupt::TrapFrame, MMArch},
     filesystem::{
         procfs::procfs_register_pid,
         vfs::{file::FileDescriptorVec, MAX_PATHLEN},
@@ -24,9 +24,7 @@ use crate::{
     process::ProcessControlBlock,
     sched::completion::Completion,
     syscall::{
-        user_access::{
-            check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter,
-        },
+        user_access::{check_and_clone_cstr, check_and_clone_cstr_array, UserBufferWriter},
         Syscall, SystemError,
     },
 };
@@ -38,11 +36,16 @@ impl Syscall {
     }
 
     pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
-        ProcessManager::fork(
-            frame,
-            CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
-        )
-        .map(|pid| pid.into())
+        // 由于Linux vfork需要保证子进程先运行(除非子进程调用execve或者exit),
+        // 而我们目前没有实现这个特性,所以暂时使用fork代替vfork(linux文档表示这样也是也可以的)
+        Self::fork(frame)
+
+        // 下面是以前的实现,除非我们实现了子进程先运行的特性,否则不要使用,不然会导致父进程数据损坏
+        // ProcessManager::fork(
+        //     frame,
+        //     CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
+        // )
+        // .map(|pid| pid.into())
     }
 
     pub fn execve(
@@ -100,98 +103,35 @@ impl Syscall {
         options: i32,
         rusage: *mut c_void,
     ) -> Result<usize, SystemError> {
-        let ret = WaitOption::from_bits(options as u32);
-        let options = match ret {
-            Some(options) => options,
-            None => {
-                return Err(SystemError::EINVAL);
-            }
+        let options = WaitOption::from_bits(options as u32).ok_or(SystemError::EINVAL)?;
+
+        let wstatus_buf = if wstatus.is_null() {
+            None
+        } else {
+            Some(UserBufferWriter::new(
+                wstatus,
+                core::mem::size_of::<i32>(),
+                true,
+            )?)
         };
 
-        let mut _rusage_buf =
-            UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?;
-
-        let mut wstatus_buf =
-            UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?;
-
-        let cur_pcb = ProcessManager::current_pcb();
-        let rd_childen = cur_pcb.children.read();
-
-        if pid > 0 {
-            let pid = Pid(pid as usize);
-            let child_pcb = ProcessManager::find(pid).ok_or(SystemError::ECHILD)?;
-            drop(rd_childen);
-
-            loop {
-                let state = child_pcb.sched_info().state();
-                // 获取退出码
-                match state {
-                    ProcessState::Runnable => {
-                        if options.contains(WaitOption::WNOHANG)
-                            || options.contains(WaitOption::WNOWAIT)
-                        {
-                            if !wstatus.is_null() {
-                                wstatus_buf.copy_one_to_user(&WaitOption::WCONTINUED.bits(), 0)?;
-                            }
-                            return Ok(0);
-                        }
-                    }
-                    ProcessState::Blocked(_) | ProcessState::Stopped => {
-                        // 指定WUNTRACED则等待暂停的进程,不指定则返回0
-                        if !options.contains(WaitOption::WUNTRACED)
-                            || options.contains(WaitOption::WNOWAIT)
-                        {
-                            if !wstatus.is_null() {
-                                wstatus_buf.copy_one_to_user(&WaitOption::WSTOPPED.bits(), 0)?;
-                            }
-                            return Ok(0);
-                        }
-                    }
-                    ProcessState::Exited(status) => {
-                        // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
-                        if !wstatus.is_null() {
-                            wstatus_buf.copy_one_to_user(
-                                &(status as u32 | WaitOption::WEXITED.bits()),
-                                0,
-                            )?;
-                        }
-                        drop(child_pcb);
-                        // kdebug!("wait4: to release {pid:?}");
-                        unsafe { ProcessManager::release(pid) };
-                        return Ok(pid.into());
-                    }
-                };
-
-                // 等待指定进程
-                child_pcb.wait_queue.sleep();
-            }
-        } else if pid < -1 {
-            // TODO 判断是否pgid == -pid(等待指定组任意进程)
-            // 暂时不支持
-            return Err(SystemError::EINVAL);
-        } else if pid == 0 {
-            // TODO 判断是否pgid == current_pgid(等待当前组任意进程)
-            // 暂时不支持
-            return Err(SystemError::EINVAL);
+        let mut tmp_rusage = if rusage.is_null() {
+            None
         } else {
-            // 等待任意子进程(这两)
-            let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
-            for pid in rd_childen.iter() {
-                let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
-                if pcb.sched_info().state().is_exited() {
-                    if !wstatus.is_null() {
-                        wstatus_buf.copy_one_to_user(&0, 0)?;
-                    }
-                    return Ok(pid.clone().into());
-                } else {
-                    unsafe { pcb.wait_queue.sleep_without_schedule() };
-                }
-            }
-            drop(irq_guard);
-            sched();
-        }
+            Some(RUsage::default())
+        };
 
-        return Ok(0);
+        let r = kernel_wait4(pid, wstatus_buf, options, tmp_rusage.as_mut())?;
+
+        if !rusage.is_null() {
+            let mut rusage_buf = UserBufferWriter::new::<RUsage>(
+                rusage as *mut RUsage,
+                core::mem::size_of::<RUsage>(),
+                true,
+            )?;
+            rusage_buf.copy_one_to_user(&tmp_rusage.unwrap(), 0)?;
+        }
+        return Ok(r);
     }
 
     /// # 退出进程
@@ -356,16 +296,12 @@ impl Syscall {
     pub fn prlimit64(
         _pid: Pid,
         resource: usize,
-        new_limit: *const RLimit64,
+        _new_limit: *const RLimit64,
         old_limit: *mut RLimit64,
     ) -> Result<usize, SystemError> {
         let resource = RLimitID::try_from(resource)?;
         let mut writer = None;
 
-        if new_limit.is_null() {
-            return Err(SystemError::EINVAL);
-        }
-
         if !old_limit.is_null() {
             writer = Some(UserBufferWriter::new(
                 old_limit,
@@ -374,8 +310,6 @@ impl Syscall {
             )?);
         }
 
-        let _reader = UserBufferReader::new(new_limit, core::mem::size_of::<RLimit64>(), true)?;
-
         match resource {
             RLimitID::Stack => {
                 if let Some(mut writer) = writer {

+ 57 - 0
kernel/src/syscall/misc.rs

@@ -0,0 +1,57 @@
+use crate::arch::mm::LockedFrameAllocator;
+
+use super::{user_access::UserBufferWriter, Syscall, SystemError};
+
+#[repr(C)]
+
+/// 系统信息
+///
+/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/uapi/linux/sysinfo.h#8
+#[derive(Debug, Default, Copy, Clone)]
+pub struct SysInfo {
+    uptime: u64,
+    loads: [u64; 3],
+    totalram: u64,
+    freeram: u64,
+    sharedram: u64,
+    bufferram: u64,
+    totalswap: u64,
+    freeswap: u64,
+    procs: u16,
+    pad: u16,
+    totalhigh: u64,
+    freehigh: u64,
+    mem_unit: u32,
+    // 这后面还有一小段,但是我们不需要
+}
+
+impl Syscall {
+    pub fn sysinfo(info: *mut SysInfo) -> Result<usize, SystemError> {
+        let mut writer = UserBufferWriter::new(info, core::mem::size_of::<SysInfo>(), true)?;
+        let mut sysinfo = SysInfo::default();
+
+        let mem = LockedFrameAllocator.get_usage();
+        sysinfo.uptime = 0;
+        sysinfo.loads = [0; 3];
+        sysinfo.totalram = mem.total().bytes() as u64;
+        sysinfo.freeram = mem.free().bytes() as u64;
+        sysinfo.sharedram = 0;
+        sysinfo.bufferram = 0;
+        sysinfo.totalswap = 0;
+        sysinfo.freeswap = 0;
+        sysinfo.procs = 0;
+        sysinfo.pad = 0;
+        sysinfo.totalhigh = 0;
+        sysinfo.freehigh = 0;
+        sysinfo.mem_unit = 0;
+
+        writer.copy_one_to_user(&sysinfo, 0)?;
+
+        return Ok(0);
+    }
+
+    pub fn umask(_mask: u32) -> Result<usize, SystemError> {
+        kwarn!("SYS_UMASK has not yet been implemented\n");
+        return Ok(0o777);
+    }
+}

+ 62 - 8
kernel/src/syscall/mod.rs

@@ -4,7 +4,10 @@ use core::{
 };
 
 use crate::{
-    arch::syscall::{SYS_ACCESS, SYS_FACCESSAT, SYS_FACCESSAT2, SYS_PRLIMIT64},
+    arch::syscall::{
+        SYS_ACCESS, SYS_CHMOD, SYS_CLOCK_GETTIME, SYS_FACCESSAT, SYS_FACCESSAT2, SYS_FCHMOD,
+        SYS_FCHMODAT, SYS_LSTAT, SYS_PRLIMIT64, SYS_READV, SYS_SYSINFO, SYS_UMASK, SYS_UNLINK,
+    },
     libs::{futex::constant::FutexFlag, rand::GRandFlags},
     process::{
         fork::KernelCloneArgs,
@@ -35,8 +38,12 @@ use crate::{
     },
 };
 
-use self::user_access::{UserBufferReader, UserBufferWriter};
+use self::{
+    misc::SysInfo,
+    user_access::{UserBufferReader, UserBufferWriter},
+};
 
+pub mod misc;
 pub mod user_access;
 
 #[repr(i32)]
@@ -317,6 +324,9 @@ pub enum SystemError {
     EVMPRTLDFailed = 135,
     EVMLAUNCHFailed = 136,
     KVM_HVA_ERR_BAD = 137,
+
+    // === 以下错误码不应该被用户态程序使用 ===
+    ERESTARTSYS = 512,
 }
 
 impl SystemError {
@@ -383,7 +393,6 @@ pub const SYS_SOCKET_PAIR: usize = 53;
 pub const SYS_SETSOCKOPT: usize = 54;
 pub const SYS_GETSOCKOPT: usize = 55;
 
-#[allow(dead_code)]
 pub const SYS_CLONE: usize = 56;
 pub const SYS_FORK: usize = 57;
 pub const SYS_VFORK: usize = 58;
@@ -507,7 +516,7 @@ impl Syscall {
 
                     let flags = args[1];
                     let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
-                    Self::open(path, open_flags)
+                    Self::open(path, open_flags, true)
                 };
                 res
             }
@@ -657,13 +666,13 @@ impl Syscall {
                 }
             }
             SYS_WAIT4 => {
-                let pid = args[0] as i64;
+                let pid = args[0] as i32;
                 let wstatus = args[1] as *mut i32;
                 let options = args[2] as c_int;
                 let rusage = args[3] as *mut c_void;
                 // 权限校验
                 // todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小
-                Self::wait4(pid, wstatus, options, rusage)
+                Self::wait4(pid.into(), wstatus, options, rusage)
             }
 
             SYS_EXIT => {
@@ -754,6 +763,11 @@ impl Syscall {
                     }
                 }
             }
+
+            SYS_UNLINK => {
+                let pathname = args[0] as *const u8;
+                Self::unlink(pathname)
+            }
             SYS_KILL => {
                 let pid = Pid::new(args[0]);
                 let sig = args[1] as c_int;
@@ -1093,13 +1107,14 @@ impl Syscall {
                 Self::do_futex(uaddr, operation, val, timespec, uaddr2, utime as u32, val3)
             }
 
+            SYS_READV => Self::readv(args[0] as i32, args[1], args[2]),
             SYS_WRITEV => Self::writev(args[0] as i32, args[1], args[2]),
 
             SYS_ARCH_PRCTL => Self::arch_prctl(args[0], args[1]),
 
             SYS_SET_TID_ADDR => Self::set_tid_address(args[0]),
 
-            SYS_STAT => {
+            SYS_STAT | SYS_LSTAT => {
                 let path: &CStr = unsafe { CStr::from_ptr(args[0] as *const c_char) };
                 let path: Result<&str, core::str::Utf8Error> = path.to_str();
                 let res = if path.is_err() {
@@ -1109,7 +1124,13 @@ impl Syscall {
                     let kstat = args[1] as *mut PosixKstat;
                     let vaddr = VirtAddr::new(kstat as usize);
                     match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
-                        Ok(_) => Self::stat(path, kstat),
+                        Ok(_) => {
+                            if syscall_num == SYS_STAT {
+                                Self::stat(path, kstat)
+                            } else {
+                                Self::lstat(path, kstat)
+                            }
+                        }
                         Err(e) => Err(e),
                     }
                 };
@@ -1225,6 +1246,39 @@ impl Syscall {
                 Self::faccessat2(dirfd, pathname, mode, flags)
             }
 
+            SYS_CLOCK_GETTIME => {
+                let clockid = args[0] as i32;
+                let timespec = args[1] as *mut TimeSpec;
+                Self::clock_gettime(clockid, timespec)
+            }
+
+            SYS_SYSINFO => {
+                let info = args[0] as *mut SysInfo;
+                Self::sysinfo(info)
+            }
+
+            SYS_UMASK => {
+                let mask = args[0] as u32;
+                Self::umask(mask)
+            }
+
+            SYS_CHMOD => {
+                let pathname = args[0] as *const u8;
+                let mode = args[1] as u32;
+                Self::chmod(pathname, mode)
+            }
+            SYS_FCHMOD => {
+                let fd = args[0] as i32;
+                let mode = args[1] as u32;
+                Self::fchmod(fd, mode)
+            }
+            SYS_FCHMODAT => {
+                let dirfd = args[0] as i32;
+                let pathname = args[1] as *const u8;
+                let mode = args[2] as u32;
+                Self::fchmodat(dirfd, pathname, mode)
+            }
+
             _ => panic!("Unsupported syscall ID: {}", syscall_num),
         };
         return r;

+ 11 - 0
kernel/src/syscall/user_access.rs

@@ -223,6 +223,17 @@ impl<'a> UserBufferReader<'a> {
         return Ok(());
     }
 
+    /// 把用户空间的数据转换成指定类型的切片
+    ///
+    /// ## 参数
+    ///
+    /// - `offset`:字节偏移量
+    pub fn buffer<T>(&self, offset: usize) -> Result<&[T], SystemError> {
+        Ok(self
+            .convert_with_offset::<T>(self.buffer, offset)
+            .map_err(|_| SystemError::EINVAL)?)
+    }
+
     fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
         if offset >= src.len() {
             return Err(SystemError::EINVAL);

+ 43 - 0
kernel/src/time/syscall.rs

@@ -3,6 +3,8 @@ use core::{
     ptr::null_mut,
 };
 
+use num_traits::FromPrimitive;
+
 use crate::{
     syscall::{user_access::UserBufferWriter, Syscall, SystemError},
     time::{sleep::nanosleep, TimeSpec},
@@ -36,6 +38,29 @@ pub const SYS_TIMEZONE: PosixTimeZone = PosixTimeZone {
     tz_dsttime: 0,
 };
 
+/// The IDs of the various system clocks (for POSIX.1b interval timers):
+#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive)]
+pub enum PosixClockID {
+    Realtime = 0,
+    Monotonic = 1,
+    ProcessCPUTimeID = 2,
+    ThreadCPUTimeID = 3,
+    MonotonicRaw = 4,
+    RealtimeCoarse = 5,
+    MonotonicCoarse = 6,
+    Boottime = 7,
+    RealtimeAlarm = 8,
+    BoottimeAlarm = 9,
+}
+
+impl TryFrom<i32> for PosixClockID {
+    type Error = SystemError;
+
+    fn try_from(value: i32) -> Result<Self, Self::Error> {
+        <Self as FromPrimitive>::from_i32(value).ok_or(SystemError::EINVAL)
+    }
+}
+
 impl Syscall {
     /// @brief 休眠指定时间(单位:纳秒)(提供给C的接口)
     ///
@@ -107,4 +132,22 @@ impl Syscall {
 
         return Ok(0);
     }
+
+    pub fn clock_gettime(clock_id: c_int, tp: *mut TimeSpec) -> Result<usize, SystemError> {
+        let clock_id = PosixClockID::try_from(clock_id)?;
+        if clock_id != PosixClockID::Realtime {
+            kwarn!("clock_gettime: currently only support Realtime clock, but got {:?}. Defaultly return realtime!!!\n", clock_id);
+        }
+        if tp.is_null() {
+            return Err(SystemError::EFAULT);
+        }
+        let mut tp_buf =
+            UserBufferWriter::new::<TimeSpec>(tp, core::mem::size_of::<TimeSpec>(), true)?;
+
+        let posix_time = do_gettimeofday();
+
+        tp_buf.copy_one_to_user(&posix_time, 0)?;
+
+        return Ok(0);
+    }
 }