浏览代码

feat(syscall): 添加syscall table的实现 (#1164)

* feat(syscall): 添加syscall table的实现

- 实现syscall table
- 为syscall table适配write/writev、read和readv系统调用

---------

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin 3 天之前
父节点
当前提交
b322121dd9

+ 7 - 2
docs/conf.py

@@ -17,7 +17,7 @@ import os
 # -- Project information -----------------------------------------------------
 
 project = 'DragonOS'
-copyright = '2022-2024, DragonOS Community'
+copyright = '2022-2025, DragonOS Community'
 author = 'longjin'
 github_org = 'DragonOS-Community'
 github_repo = 'DragonOS'
@@ -31,7 +31,12 @@ release = 'dev'
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
-extensions = ['myst_parser', 'sphinx_multiversion']
+extensions = [
+    'myst_parser', 
+    'sphinx_multiversion',
+    'sphinxcontrib.mermaid',
+    'sphinx.ext.extlinks',
+]
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']

+ 1 - 5
docs/index.rst

@@ -33,6 +33,7 @@
    kernel/container/index
    kernel/libs/index
    kernel/trace/index
+   kernel/syscall/index
 
 
 
@@ -42,11 +43,6 @@
    
    userland/appdev/index
 
-.. toctree::
-   :maxdepth: 1
-   :caption: 系统调用api文档
-
-   syscall_api/index
 
 .. toctree::
    :maxdepth: 1

+ 1 - 1
docs/kernel/filesystem/overview.md

@@ -67,7 +67,7 @@ Syscall:    │   sys_open, sys_read, sys_write, sys_close,     │
 - `sys_fchmod`:修改文件权限(未实现)
 - 其他系统调用接口(未实现)
 
-&emsp;&emsp;关于接口的具体含义,可以参考 [DragonOS系统调用接口](../../syscall_api/index.rst)
+&emsp;&emsp;关于接口的具体含义,可以参考Linux的相关文档
 
 ## 虚拟文件系统(VFS)
 

+ 3 - 3
docs/syscall_api/index.rst → docs/kernel/syscall/index.rst

@@ -1,10 +1,10 @@
-.. _syscall_api:
+.. _syscall:
 
-系统调用API
+系统调用
 ====================================
 
 .. toctree::
    :maxdepth: 1
    :caption: 目录
 
-   intro
+   syscall_table

+ 120 - 0
docs/kernel/syscall/syscall_table.rst

@@ -0,0 +1,120 @@
+系统调用表实现方案
+====================
+
+.. note::
+    Author: longjin <longjin@dragonos.org>
+
+    Date: 2025/05/13
+
+概述
+----
+
+.. mermaid::
+   :align: center
+   :caption: 系统调用表架构
+
+   classDiagram
+      class Syscall {
+         <<trait>>
+         +num_args() usize
+         +handle(args, from_user) Result<usize, SystemError>
+         +entry_format(args) Vec<FormattedSyscallParam>
+      }
+
+      class SyscallHandle {
+         +nr: usize
+         +inner_handle: &dyn Syscall
+      }
+
+      class SyscallTable {
+         -entries: [Option<&SyscallHandle>; 512]
+         +get(nr) Option<&dyn Syscall>
+      }
+
+      Syscall <|.. SysXXXXXXHandle
+      SyscallHandle "1" *-- "1" Syscall
+      SyscallTable "1" *-- "512" SyscallHandle
+
+相比于将原本集中在一个大match中的系统调用分发,本方案采用基于trait和系统调用表的实现。主要优势包括:
+
+- 降低栈内存使用:避免单个大函数占用过多栈空间
+- 支持参数打印:通过统一的参数格式化接口
+- 更好的扩展性:新增系统调用无需修改分发逻辑
+
+核心设计
+--------
+
+Syscall Trait
+~~~~~~~~~~~~~
+
+所有系统调用处理函数都需要实现 `Syscall` trait:
+
+.. code-block:: rust
+
+    pub trait Syscall: Send + Sync + 'static {
+        fn num_args(&self) -> usize;
+        fn handle(&self, args: &[usize], from_user: bool) -> Result<usize, SystemError>;
+        fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam>;
+    }
+
+- `num_args()`: 返回该系统调用需要的参数数量
+- `handle()`: 实际执行系统调用处理
+- `entry_format()`: 格式化参数用于调试打印
+
+SyscallHandle
+~~~~~~~~~~~~~
+
+`SyscallHandle` 结构体将系统调用号与处理函数关联:
+
+.. code-block:: rust
+
+    pub struct SyscallHandle {
+        pub nr: usize,  // 系统调用号
+        pub inner_handle: &'static dyn Syscall,  // 处理函数
+        pub name: &'static str,
+    }
+
+SyscallTable
+~~~~~~~~~~~~
+
+`SyscallTable` 管理所有系统调用:
+
+- 固定大小512项
+- 编译时初始化
+- 通过系统调用号快速查找处理函数
+
+使用方式
+--------
+
+实现系统调用
+~~~~~~~~~~~~
+
+1. 定义实现``Syscall`` trait的结构体
+2. 实现``handle()``和``entry_format()``方法
+3. 使用``declare_syscall!``宏注册
+
+参考实现:`sys_write.rs <sys_write_>`_
+
+.. _sys_write:
+   https://github.com/DragonOS-Community/DragonOS/blob/master/kernel/src/filesystem/vfs/syscall/sys_write.rs
+
+注册系统调用
+~~~~~~~~~~~~
+
+使用``declare_syscall!``宏注册系统调用:
+
+.. code-block:: rust
+
+    syscall_table_macros::declare_syscall!(SYS_WRITE, SysWriteHandle);
+
+参数说明:
+
+1. 系统调用名称(用于生成符号)
+2. 实现``Syscall`` trait的结构体
+
+初始化流程
+----------
+
+1. 内核启动时调用``syscall_table_init()``
+2. 从链接器符号``_syscall_table``加载所有注册的系统调用
+3. 填充系统调用表

+ 1 - 0
docs/requirements.txt

@@ -1,4 +1,5 @@
 sphinx==5.0.2
 myst-parser==0.18.0
 sphinx-rtd-theme
+sphinxcontrib-mermaid==1.0.0
 git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/sphinx-multiversion.git@5858b75#egg=sphinx-multiversion

+ 0 - 1
docs/syscall_api/intro.md

@@ -1 +0,0 @@
-# 简介

+ 5 - 0
kernel/Cargo.lock

@@ -531,6 +531,7 @@ dependencies = [
  "slabmalloc",
  "smoltcp",
  "static-keys",
+ "syscall_table_macros",
  "system_error",
  "uefi",
  "uefi-raw",
@@ -1665,6 +1666,10 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "syscall_table_macros"
+version = "0.1.0"
+
 [[package]]
 name = "system_error"
 version = "0.1.0"

+ 1 - 0
kernel/Cargo.toml

@@ -60,6 +60,7 @@ smoltcp = { version = "=0.11.0", default-features = false, features = [
     "proto-ipv4",
     "proto-ipv6",
 ] }
+syscall_table_macros = { path = "crates/syscall_table_macros" }
 system_error = { path = "crates/system_error" }
 uefi = { version = "=0.26.0", features = ["alloc"] }
 uefi-raw = "=0.5.0"

+ 7 - 0
kernel/crates/syscall_table_macros/Cargo.toml

@@ -0,0 +1,7 @@
+[package]
+name = "syscall_table_macros"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+

+ 19 - 0
kernel/crates/syscall_table_macros/src/lib.rs

@@ -0,0 +1,19 @@
+#![no_std]
+#![deny(clippy::all)]
+
+#[macro_export]
+#[allow(clippy::crate_in_macro_def)]
+macro_rules! declare_syscall {
+    ($nr:ident, $inner_handle:ident) => {
+        paste::paste! {
+            #[allow(non_upper_case_globals)]
+            #[link_section = ".syscall_table"]
+            #[used]
+            pub static [<HANDLE_ $nr>]: crate::syscall::table::SyscallHandle = crate::syscall::table::SyscallHandle {
+                nr: $nr,
+                inner_handle: &$inner_handle,
+                name: stringify!($nr),
+            };
+        }
+    };
+}

+ 11 - 1
kernel/src/arch/loongarch64/link.ld

@@ -74,8 +74,18 @@ SECTIONS
         *(.tracepoint.*)
         _etracepoint = .;
     }
-    . = ALIGN(32768);
 
+	. = ALIGN(4096);
+	syscall_table_start_pa = .;
+	.syscall_table (syscall_table_start_pa):
+    {
+        _syscall_table = .;
+        *(.syscall_table)
+		*(.syscall_table.*)
+        _esyscall_table = .;
+    }
+
+    . = ALIGN(32768);
 	init_proc_union_start_pa = .;
 	.data.init_proc_union (init_proc_union_start_pa):
 	 { *(.data.init_proc_union) }

+ 12 - 1
kernel/src/arch/riscv64/link.ld

@@ -76,8 +76,19 @@ SECTIONS
         *(.tracepoint.*)
         _etracepoint = .;
     }
-    . = ALIGN(32768);
 
+    . = ALIGN(4096);
+
+	syscall_table_start_pa = .;
+	.syscall_table (syscall_table_start_pa): AT(syscall_table_start_pa - KERNEL_VMA)
+    {
+        _syscall_table = .;
+        *(.syscall_table)
+		*(.syscall_table.*)
+        _esyscall_table = .;
+    }
+
+    . = ALIGN(32768);
 	init_proc_union_start_pa = .;
 	.data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA)
 	 { *(.data.init_proc_union) }

+ 14 - 4
kernel/src/arch/x86_64/link.lds

@@ -40,7 +40,7 @@ SECTIONS
 		_etext = .;
 		__etext = .;
 	}
-	. = ALIGN(32768);
+	. = ALIGN(4096);
 	data_start_pa = .;
 	.data (data_start_pa): AT(data_start_pa - KERNEL_VMA)
 	{
@@ -51,7 +51,7 @@ SECTIONS
 		_edata = .;
 	}
 
-	. = ALIGN(32768);
+	. = ALIGN(4096);
 
 	rodata_start_pa = .;
 	.rodata (rodata_start_pa): AT(rodata_start_pa - KERNEL_VMA)
@@ -65,7 +65,7 @@ SECTIONS
 		_erodata = .;
 	}
 
-	. = ALIGN(32768);
+	. = ALIGN(4096);
 
 	trace_point_start_pa = .;
 	.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
@@ -75,8 +75,18 @@ SECTIONS
         *(.tracepoint.*)
         _etracepoint = .;
     }
-    . = ALIGN(32768);
+    . = ALIGN(4096);
 
+	syscall_table_start_pa = .;
+	.syscall_table (syscall_table_start_pa): AT(syscall_table_start_pa - KERNEL_VMA)
+    {
+        _syscall_table = .;
+        *(.syscall_table)
+		*(.syscall_table.*)
+        _esyscall_table = .;
+    }
+	
+    . = ALIGN(32768);
 	init_proc_union_start_pa = .;
 	.data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA)
 	 { *(.data.init_proc_union) }

+ 1 - 2
kernel/src/filesystem/mbr.rs

@@ -4,7 +4,6 @@ use alloc::{
     sync::{Arc, Weak},
     vec::Vec,
 };
-use log::debug;
 use system_error::SystemError;
 
 use crate::{
@@ -106,7 +105,7 @@ impl MbrDiskPartionTable {
             table.dpte[i].starting_lba = cursor.read_u32()?;
             table.dpte[i].total_sectors = cursor.read_u32()?;
 
-            debug!("dpte[{i}] = {:?}", table.dpte[i]);
+            // debug!("dpte[{i}] = {:?}", table.dpte[i]);
         }
         table.bs_trailsig = cursor.read_u16()?;
         // debug!("bs_trailsig = {}", unsafe {

+ 149 - 0
kernel/src/filesystem/vfs/iov.rs

@@ -0,0 +1,149 @@
+use alloc::vec::Vec;
+use system_error::SystemError;
+
+use crate::syscall::user_access::{UserBufferReader, UserBufferWriter};
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub struct IoVec {
+    /// 缓冲区的起始地址
+    pub iov_base: *mut u8,
+    /// 缓冲区的长度
+    pub iov_len: usize,
+}
+
+/// 用于存储多个来自用户空间的IoVec
+///
+/// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
+/// TODO:支持分散读写
+#[derive(Debug)]
+pub struct IoVecs(Vec<IoVec>);
+
+impl IoVecs {
+    /// 获取IoVecs中所有缓冲区的总长度
+    #[inline(never)]
+    pub fn total_len(&self) -> usize {
+        self.0.iter().map(|x| x.iov_len).sum()
+    }
+
+    /// Constructs `IoVecs` from an array of `IoVec` in userspace.
+    ///
+    /// # Arguments
+    ///
+    /// * `iov` - Pointer to the array of `IoVec` in userspace
+    /// * `iovcnt` - Number of `IoVec` elements in the array
+    /// * `readv` - Whether this is for the `readv` syscall (currently unused)
+    ///
+    /// # Returns
+    ///
+    /// Returns `Ok(IoVecs)` on success, or `Err(SystemError)` if any error occurs.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe because it operates on raw pointers from userspace.
+    /// The caller must ensure:
+    /// - The pointer `iov` is valid and points to at least `iovcnt` valid `IoVec` structures
+    /// - The userspace memory is not modified during this operation
+    #[inline(never)]
+    pub unsafe fn from_user(
+        iov: *const IoVec,
+        iovcnt: usize,
+        _readv: bool,
+    ) -> Result<Self, SystemError> {
+        let iovs_reader = UserBufferReader::new(iov, iovcnt * core::mem::size_of::<IoVec>(), true)?;
+
+        // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
+        let iovs = iovs_reader.buffer::<IoVec>(0)?;
+
+        let mut slices: Vec<IoVec> = Vec::with_capacity(iovs.len());
+
+        for iov in iovs.iter() {
+            if iov.iov_len == 0 {
+                continue;
+            }
+
+            let _ = UserBufferWriter::new(iov.iov_base, iov.iov_len, true)?;
+            slices.push(*iov);
+        }
+
+        return Ok(Self(slices));
+    }
+
+    /// Aggregates data from all IoVecs into a single buffer.
+    ///
+    /// This function reads data from each IoVec in sequence and combines them into
+    /// a single contiguous buffer.
+    ///
+    /// # Returns
+    ///
+    /// Returns a [`Vec<u8>`] containing all the data from the IoVecs.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let iovecs = IoVecs::from_user(/* ... */)?;
+    /// let buffer = iovecs.gather();
+    /// ```
+    pub fn gather(&self) -> Vec<u8> {
+        let mut buf = Vec::new();
+        for slice in self.0.iter() {
+            let buf_reader = UserBufferReader::new(slice.iov_base, slice.iov_len, true).unwrap();
+            let slice = buf_reader.buffer::<u8>(0).unwrap();
+            buf.extend_from_slice(slice);
+        }
+        return buf;
+    }
+
+    /// Scatters the given data into the IoVecs.
+    ///
+    /// This function writes data sequentially to each IoVec, splitting the input data
+    /// across multiple buffers as needed. If the input data is smaller than the total
+    /// capacity of the IoVecs, only the required amount of data will be written.
+    /// If the input data is larger than the total capacity, the excess data will be ignored.
+    ///
+    /// # Arguments
+    ///
+    /// * `data` - The data to be scattered across the IoVecs
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let iovecs = IoVecs::from_user(/* ... */)?;
+    /// iovecs.scatter(&[1, 2, 3, 4, 5]);
+    /// ```
+    pub fn scatter(&self, data: &[u8]) {
+        let mut data: &[u8] = data;
+        for slice in self.0.iter() {
+            let len = core::cmp::min(slice.iov_len, data.len());
+            if len == 0 {
+                continue;
+            }
+
+            let mut buf_writer =
+                UserBufferWriter::new(slice.iov_base, slice.iov_len, true).unwrap();
+            let slice = buf_writer.buffer::<u8>(0).unwrap();
+
+            slice[..len].copy_from_slice(&data[..len]);
+            data = &data[len..];
+        }
+    }
+
+    /// Creates a buffer with capacity equal to the total length of all IoVecs.
+    ///
+    /// # Arguments
+    ///
+    /// * `set_len` - If true, sets the length of the returned Vec to the total length of all IoVecs.
+    ///               If false, the returned Vec will have length 0 but capacity equal to the total length.
+    ///
+    /// # Returns
+    ///
+    /// A new [`Vec<u8>`] with capacity (and potentially length) equal to the total length of all IoVecs.
+    pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
+        let total_len = self.total_len();
+        let mut buf: Vec<u8> = Vec::with_capacity(total_len);
+
+        if set_len {
+            buf.resize(total_len, 0);
+        }
+        return buf;
+    }
+}

+ 1 - 0
kernel/src/filesystem/vfs/mod.rs

@@ -1,5 +1,6 @@
 pub mod fcntl;
 pub mod file;
+pub mod iov;
 pub mod mount;
 pub mod open;
 pub mod stat;

+ 6 - 166
kernel/src/filesystem/vfs/syscall.rs → kernel/src/filesystem/vfs/syscall/mod.rs

@@ -12,7 +12,7 @@ use crate::{
     driver::base::{block::SeekFrom, device::device_number::DeviceNumber},
     filesystem::vfs::{file::FileDescriptorVec, vcore as Vcore},
     libs::rwlock::RwLockWriteGuard,
-    mm::{verify_area, VirtAddr},
+    mm::VirtAddr,
     process::ProcessManager,
     syscall::{
         user_access::{self, check_and_clone_cstr, UserBufferWriter},
@@ -35,6 +35,11 @@ use super::{
     VFS_MAX_FOLLOW_SYMLINK_TIMES,
 };
 
+mod sys_read;
+mod sys_readv;
+mod sys_write;
+mod sys_writev;
+
 pub const SEEK_SET: u32 = 0;
 pub const SEEK_CUR: u32 = 1;
 pub const SEEK_END: u32 = 2;
@@ -497,48 +502,6 @@ impl Syscall {
         return r;
     }
 
-    /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
-    ///
-    /// @param fd 文件描述符编号
-    /// @param buf 输出缓冲区
-    ///
-    /// @return Ok(usize) 成功读取的数据的字节数
-    /// @return Err(SystemError) 读取失败,返回posix错误码
-    pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
-        let binding = ProcessManager::current_pcb().fd_table();
-        let fd_table_guard = binding.read();
-
-        let file = fd_table_guard.get_file_by_fd(fd);
-        if file.is_none() {
-            return Err(SystemError::EBADF);
-        }
-        // drop guard 以避免无法调度的问题
-        drop(fd_table_guard);
-        let file = file.unwrap();
-
-        return file.read(buf.len(), buf);
-    }
-
-    /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
-    ///
-    /// @param fd 文件描述符编号
-    /// @param buf 输入缓冲区
-    ///
-    /// @return Ok(usize) 成功写入的数据的字节数
-    /// @return Err(SystemError) 写入失败,返回posix错误码
-    pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
-        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)?;
-
-        // drop guard 以避免无法调度的问题
-        drop(fd_table_guard);
-        return file.write(buf.len(), buf);
-    }
-
     /// @brief 调整文件操作指针的位置
     ///
     /// @param fd 文件描述符编号
@@ -1421,28 +1384,6 @@ impl Syscall {
         return Ok(0);
     }
 
-    pub fn writev(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> {
-        // IoVecs会进行用户态检验
-        let iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, false) }?;
-
-        let data = iovecs.gather();
-
-        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![0; iovecs.0.iter().map(|x| x.len()).sum()];
-
-        let len = Self::read(fd, &mut data)?;
-
-        iovecs.scatter(&data[..len]);
-
-        return Ok(len);
-    }
-
     pub fn readlink_at(
         dirfd: i32,
         path: *const u8,
@@ -1675,104 +1616,3 @@ impl Syscall {
         do_utimes(&pathname, times)
     }
 }
-
-#[repr(C)]
-#[derive(Debug, Clone, Copy)]
-pub struct IoVec {
-    /// 缓冲区的起始地址
-    pub iov_base: *mut u8,
-    /// 缓冲区的长度
-    pub iov_len: usize,
-}
-
-/// 用于存储多个来自用户空间的IoVec
-///
-/// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
-/// TODO:支持分散读写
-#[derive(Debug)]
-pub struct IoVecs(Vec<&'static mut [u8]>);
-
-impl IoVecs {
-    /// 从用户空间的IoVec中构造IoVecs
-    ///
-    /// @param iov 用户空间的IoVec
-    /// @param iovcnt 用户空间的IoVec的数量
-    /// @param readv 是否为readv系统调用
-    ///
-    /// @return 构造成功返回IoVecs,否则返回错误码
-    pub unsafe fn from_user(
-        iov: *const IoVec,
-        iovcnt: usize,
-        _readv: bool,
-    ) -> Result<Self, SystemError> {
-        // 检查iov指针所在空间是否合法
-        verify_area(
-            VirtAddr::new(iov as usize),
-            iovcnt * core::mem::size_of::<IoVec>(),
-        )
-        .map_err(|_| SystemError::EFAULT)?;
-
-        // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
-        let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
-
-        let mut slices: Vec<&mut [u8]> = Vec::with_capacity(iovs.len());
-
-        for iov in iovs.iter() {
-            if iov.iov_len == 0 {
-                continue;
-            }
-
-            verify_area(
-                VirtAddr::new(iov.iov_base as usize),
-                iovcnt * core::mem::size_of::<IoVec>(),
-            )
-            .map_err(|_| SystemError::EFAULT)?;
-
-            slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
-        }
-
-        return Ok(Self(slices));
-    }
-
-    /// @brief 将IoVecs中的数据聚合到一个缓冲区中
-    ///
-    /// @return 返回聚合后的缓冲区
-    pub fn gather(&self) -> Vec<u8> {
-        let mut buf = Vec::new();
-        for slice in self.0.iter() {
-            buf.extend_from_slice(slice);
-        }
-        return buf;
-    }
-
-    /// @brief 将给定的数据分散写入到IoVecs中
-    pub fn scatter(&mut self, data: &[u8]) {
-        let mut data: &[u8] = data;
-        for slice in self.0.iter_mut() {
-            let len = core::cmp::min(slice.len(), data.len());
-            if len == 0 {
-                continue;
-            }
-
-            slice[..len].copy_from_slice(&data[..len]);
-            data = &data[len..];
-        }
-    }
-
-    /// @brief 创建与IoVecs等长的缓冲区
-    ///
-    /// @param set_len 是否设置返回的Vec的len。
-    /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
-    /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
-    ///
-    /// @return 返回创建的缓冲区
-    pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
-        let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
-        let mut buf: Vec<u8> = Vec::with_capacity(total_len);
-
-        if set_len {
-            buf.resize(total_len, 0);
-        }
-        return buf;
-    }
-}

+ 105 - 0
kernel/src/filesystem/vfs/syscall/sys_read.rs

@@ -0,0 +1,105 @@
+use system_error::SystemError;
+
+use crate::arch::syscall::nr::SYS_READ;
+use crate::process::ProcessManager;
+use crate::syscall::table::FormattedSyscallParam;
+use crate::syscall::table::Syscall;
+use crate::syscall::user_access::UserBufferWriter;
+
+use alloc::string::ToString;
+use alloc::vec::Vec;
+
+/// System call handler for the `read` syscall
+///
+/// This handler implements the `Syscall` trait to provide functionality for reading data from a file descriptor.
+pub struct SysReadHandle;
+
+impl Syscall for SysReadHandle {
+    /// Returns the number of arguments expected by the `read` syscall
+    fn num_args(&self) -> usize {
+        3
+    }
+
+    /// Handles the `read` system call
+    ///
+    /// Reads data from the specified file descriptor into a user buffer.
+    ///
+    /// # Arguments
+    /// * `args` - Array containing:
+    ///   - args[0]: File descriptor (i32)
+    ///   - args[1]: Pointer to user buffer (*mut u8)
+    ///   - args[2]: Length of data to read (usize)
+    /// * `from_user` - Indicates if the call originates from user space
+    ///
+    /// # Returns
+    /// * `Ok(usize)` - Number of bytes successfully read
+    /// * `Err(SystemError)` - Error code if operation fails
+    fn handle(&self, args: &[usize], from_user: bool) -> Result<usize, SystemError> {
+        let fd = Self::fd(args);
+        let buf_vaddr = Self::buf(args);
+        let len = Self::len(args);
+
+        let mut user_buffer_writer = UserBufferWriter::new(buf_vaddr, len, from_user)?;
+
+        let user_buf = user_buffer_writer.buffer(0)?;
+        do_read(fd, user_buf)
+    }
+
+    /// Formats the syscall parameters for display/debug purposes
+    ///
+    /// # Arguments
+    /// * `args` - The raw syscall arguments
+    ///
+    /// # Returns
+    /// Vector of formatted parameters with descriptive names
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
+            FormattedSyscallParam::new("buf", format!("{:#x}", Self::buf(args) as usize)),
+            FormattedSyscallParam::new("len", Self::len(args).to_string()),
+        ]
+    }
+}
+
+impl SysReadHandle {
+    /// Extracts the file descriptor from syscall arguments
+    fn fd(args: &[usize]) -> i32 {
+        args[0] as i32
+    }
+
+    /// Extracts the buffer pointer from syscall arguments
+    fn buf(args: &[usize]) -> *mut u8 {
+        args[1] as *mut u8
+    }
+
+    /// Extracts the buffer length from syscall arguments
+    fn len(args: &[usize]) -> usize {
+        args[2]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_READ, SysReadHandle);
+
+/// Internal implementation of the read operation
+///
+/// # Arguments
+/// * `fd` - File descriptor to read from
+/// * `buf` - Buffer to store read data
+///
+/// # Returns
+/// * `Ok(usize)` - Number of bytes successfully read
+/// * `Err(SystemError)` - Error code if operation fails
+pub(super) fn do_read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
+    let binding = ProcessManager::current_pcb().fd_table();
+    let fd_table_guard = binding.read();
+
+    let file = fd_table_guard.get_file_by_fd(fd);
+    if file.is_none() {
+        return Err(SystemError::EBADF);
+    }
+    // drop guard 以避免无法调度的问题
+    drop(fd_table_guard);
+    let file = file.unwrap();
+
+    return file.read(buf.len(), buf);
+}

+ 65 - 0
kernel/src/filesystem/vfs/syscall/sys_readv.rs

@@ -0,0 +1,65 @@
+use system_error::SystemError;
+
+use crate::arch::syscall::nr::SYS_READV;
+use crate::filesystem::vfs::iov::IoVec;
+use crate::filesystem::vfs::iov::IoVecs;
+use crate::syscall::table::FormattedSyscallParam;
+use crate::syscall::table::Syscall;
+
+use alloc::string::ToString;
+use alloc::vec::Vec;
+
+use super::sys_read::do_read;
+
+/// System call handler for `readv` operation
+///
+/// The `readv` system call reads data into multiple buffers from a file descriptor.
+/// It is equivalent to multiple `read` calls but is more efficient.
+pub struct SysReadVHandle;
+
+impl Syscall for SysReadVHandle {
+    fn num_args(&self) -> usize {
+        3
+    }
+
+    fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
+        let fd = Self::fd(args);
+        let iov = Self::iov(args);
+        let count = Self::count(args);
+
+        // IoVecs会进行用户态检验
+        let iovecs = unsafe { IoVecs::from_user(iov, count, true) }?;
+
+        let mut data = vec![0; iovecs.total_len()];
+
+        let len = do_read(fd, &mut data)?;
+
+        iovecs.scatter(&data[..len]);
+
+        return Ok(len);
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
+            FormattedSyscallParam::new("iov", format!("{:#x}", Self::iov(args) as usize)),
+            FormattedSyscallParam::new("count", Self::count(args).to_string()),
+        ]
+    }
+}
+
+impl SysReadVHandle {
+    fn fd(args: &[usize]) -> i32 {
+        args[0] as i32
+    }
+
+    fn iov(args: &[usize]) -> *const IoVec {
+        args[1] as *const IoVec
+    }
+
+    fn count(args: &[usize]) -> usize {
+        args[2]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_READV, SysReadVHandle);

+ 104 - 0
kernel/src/filesystem/vfs/syscall/sys_write.rs

@@ -0,0 +1,104 @@
+use system_error::SystemError;
+
+use crate::arch::syscall::nr::SYS_WRITE;
+use crate::process::ProcessManager;
+use crate::syscall::table::FormattedSyscallParam;
+use crate::syscall::table::Syscall;
+use crate::syscall::user_access::UserBufferReader;
+
+use alloc::string::ToString;
+use alloc::vec::Vec;
+
+/// System call handler for the `write` syscall
+///
+/// This handler implements the `Syscall` trait to provide functionality for writing data to a file descriptor.
+pub struct SysWriteHandle;
+
+impl Syscall for SysWriteHandle {
+    /// Returns the number of arguments expected by the `write` syscall
+    fn num_args(&self) -> usize {
+        3
+    }
+
+    /// Handles the `write` system call
+    ///
+    /// Writes data from a user buffer to the specified file descriptor.
+    ///
+    /// # Arguments
+    /// * `args` - Array containing:
+    ///   - args[0]: File descriptor (i32)
+    ///   - args[1]: Pointer to user buffer (*const u8)
+    ///   - args[2]: Length of data to write (usize)
+    /// * `from_user` - Indicates if the call originates from user space
+    ///
+    /// # Returns
+    /// * `Ok(usize)` - Number of bytes successfully written
+    /// * `Err(SystemError)` - Error code if operation fails
+    fn handle(&self, args: &[usize], from_user: bool) -> Result<usize, SystemError> {
+        let fd = Self::fd(args);
+        let buf_vaddr = Self::buf(args);
+        let len = Self::len(args);
+
+        let user_buffer_reader = UserBufferReader::new(buf_vaddr, len, from_user)?;
+
+        let user_buf = user_buffer_reader.read_from_user(0)?;
+
+        do_write(fd, user_buf)
+    }
+
+    /// Formats the syscall parameters for display/debug purposes
+    ///
+    /// # Arguments
+    /// * `args` - The raw syscall arguments
+    ///
+    /// # Returns
+    /// Vector of formatted parameters with descriptive names
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
+            FormattedSyscallParam::new("buf", format!("{:#x}", Self::buf(args) as usize)),
+            FormattedSyscallParam::new("len", Self::len(args).to_string()),
+        ]
+    }
+}
+
+impl SysWriteHandle {
+    /// Extracts the file descriptor from syscall arguments
+    fn fd(args: &[usize]) -> i32 {
+        args[0] as i32
+    }
+
+    /// Extracts the buffer pointer from syscall arguments
+    fn buf(args: &[usize]) -> *const u8 {
+        args[1] as *const u8
+    }
+
+    /// Extracts the buffer length from syscall arguments
+    fn len(args: &[usize]) -> usize {
+        args[2]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_WRITE, SysWriteHandle);
+
+/// Internal implementation of the write operation
+///
+/// # Arguments
+/// * `fd` - File descriptor to write to
+/// * `buf` - Buffer containing data to write
+///
+/// # Returns
+/// * `Ok(usize)` - Number of bytes successfully written
+/// * `Err(SystemError)` - Error code if operation fails
+pub(super) fn do_write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
+    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)?;
+
+    // drop guard 以避免无法调度的问题
+    drop(fd_table_guard);
+    return file.write(buf.len(), buf);
+}

+ 85 - 0
kernel/src/filesystem/vfs/syscall/sys_writev.rs

@@ -0,0 +1,85 @@
+use system_error::SystemError;
+
+use crate::arch::syscall::nr::SYS_WRITEV;
+use crate::filesystem::vfs::iov::IoVec;
+use crate::filesystem::vfs::iov::IoVecs;
+use crate::syscall::table::FormattedSyscallParam;
+use crate::syscall::table::Syscall;
+
+use alloc::string::ToString;
+use alloc::vec::Vec;
+
+use super::sys_write::do_write;
+
+/// System call handler for `writev` operation
+///
+/// The `writev` system call writes data from multiple buffers to a file descriptor.
+/// It is equivalent to multiple `write` calls but is more efficient.
+pub struct SysWriteVHandle;
+
+impl Syscall for SysWriteVHandle {
+    /// Returns the number of arguments required by the `writev` system call
+    fn num_args(&self) -> usize {
+        3
+    }
+
+    /// Handles the `writev` system call
+    ///
+    /// # Arguments
+    /// * `args` - System call arguments containing:
+    ///   * `fd`: File descriptor to write to
+    ///   * `iov`: Pointer to array of I/O vectors
+    ///   * `count`: Number of elements in the I/O vector array
+    /// * `_from_user` - Flag indicating if the call originated from user space
+    ///
+    /// # Returns
+    /// * `Ok(usize)` - Number of bytes written
+    /// * `Err(SystemError)` - Error that occurred during operation
+    ///
+    /// # Safety
+    /// The caller must ensure the `iov` pointer is valid and points to properly initialized memory.
+    fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
+        let fd = Self::fd(args);
+        let iov = Self::iov(args);
+        let count = Self::count(args);
+
+        // IoVecs会进行用户态检验
+        let iovecs = unsafe { IoVecs::from_user(iov, count, false) }?;
+        let data = iovecs.gather();
+        do_write(fd, &data)
+    }
+
+    /// Formats the system call parameters for display/debug purposes
+    ///
+    /// # Arguments
+    /// * `args` - System call arguments to format
+    ///
+    /// # Returns
+    /// Vector of formatted parameters with their names and values
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
+            FormattedSyscallParam::new("iov", format!("{:#x}", Self::iov(args) as usize)),
+            FormattedSyscallParam::new("count", Self::count(args).to_string()),
+        ]
+    }
+}
+
+impl SysWriteVHandle {
+    /// Extracts the file descriptor from system call arguments
+    fn fd(args: &[usize]) -> i32 {
+        args[0] as i32
+    }
+
+    /// Extracts the I/O vector pointer from system call arguments
+    fn iov(args: &[usize]) -> *const IoVec {
+        args[1] as *const IoVec
+    }
+
+    /// Extracts the I/O vector count from system call arguments
+    fn count(args: &[usize]) -> usize {
+        args[2]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_WRITEV, SysWriteVHandle);

+ 3 - 1
kernel/src/init/init.rs

@@ -23,7 +23,7 @@ use crate::{
     process::{kthread::kthread_init, process_init, ProcessManager},
     sched::SchedArch,
     smp::{early_smp_init, SMPArch},
-    syscall::Syscall,
+    syscall::{syscall_init, Syscall},
     time::{
         clocksource::clocksource_boot_finish, timekeeping::timekeeping_init, timer::timer_init,
     },
@@ -69,6 +69,8 @@ fn do_start_kernel() {
 
     init_intertrait();
 
+    syscall_init().expect("syscall init failed");
+
     vfs_init().expect("vfs init failed");
     driver_init().expect("driver init failed");
 

+ 2 - 2
kernel/src/net/syscall.rs

@@ -8,7 +8,7 @@ use system_error::SystemError;
 use crate::{
     filesystem::vfs::{
         file::{File, FileMode},
-        syscall::{IoVec, IoVecs},
+        iov::{IoVec, IoVecs},
         FileType,
     },
     libs::spinlock::SpinLockGuard,
@@ -295,7 +295,7 @@ impl Syscall {
     /// @return 成功返回接收的字节数,失败返回错误码
     pub fn recvmsg(fd: usize, msg: &mut MsgHdr, _flags: u32) -> Result<usize, SystemError> {
         // 检查每个缓冲区地址是否合法,生成iovecs
-        let mut iovs = unsafe { IoVecs::from_user(msg.msg_iov, msg.msg_iovlen, true)? };
+        let iovs = unsafe { IoVecs::from_user(msg.msg_iov, msg.msg_iovlen, true)? };
 
         let socket: Arc<SocketInode> = ProcessManager::current_pcb()
             .get_socket(fd as i32)

+ 20 - 25
kernel/src/syscall/mod.rs

@@ -23,6 +23,7 @@ use crate::{
 use log::{info, warn};
 use num_traits::FromPrimitive;
 use system_error::SystemError;
+use table::{syscall_table, syscall_table_init};
 
 use crate::{
     arch::{interrupt::TrapFrame, MMArch},
@@ -49,6 +50,7 @@ use self::{
 };
 
 pub mod misc;
+pub mod table;
 pub mod user_access;
 
 // 与linux不一致的调用,在linux基础上累加
@@ -99,6 +101,18 @@ impl Syscall {
         args: &[usize],
         frame: &mut TrapFrame,
     ) -> Result<usize, SystemError> {
+        // 首先尝试从syscall_table获取处理函数
+        if let Some(handler) = syscall_table().get(syscall_num) {
+            // 使用以下代码可以打印系统调用号和参数,方便调试
+            // log::debug!(
+            //     "Syscall {} called with args {}",
+            //     handler.name,
+            //     handler.args_string(args)
+            // );
+            return handler.inner_handle.handle(args, frame.is_from_user());
+        }
+
+        // 如果找不到,fallback到原有逻辑
         let r = match syscall_num {
             SYS_PUT_STRING => {
                 Self::put_string(args[0] as *const u8, args[1] as u32, args[2] as u32)
@@ -155,28 +169,6 @@ impl Syscall {
                 let fd = args[0];
                 Self::close(fd)
             }
-            SYS_READ => {
-                let fd = args[0] as i32;
-                let buf_vaddr = args[1];
-                let len = args[2];
-                let from_user = frame.is_from_user();
-                let mut user_buffer_writer =
-                    UserBufferWriter::new(buf_vaddr as *mut u8, len, from_user)?;
-
-                let user_buf = user_buffer_writer.buffer(0)?;
-                Self::read(fd, user_buf)
-            }
-            SYS_WRITE => {
-                let fd = args[0] as i32;
-                let buf_vaddr = args[1];
-                let len = args[2];
-                let from_user = frame.is_from_user();
-                let user_buffer_reader =
-                    UserBufferReader::new(buf_vaddr as *const u8, len, from_user)?;
-
-                let user_buf = user_buffer_reader.read_from_user(0)?;
-                Self::write(fd, user_buf)
-            }
 
             SYS_LSEEK => {
                 let fd = args[0] as i32;
@@ -781,9 +773,6 @@ impl Syscall {
                 return ret;
             }
 
-            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_SET_TID_ADDRESS => Self::set_tid_address(args[0]),
 
             #[cfg(target_arch = "x86_64")]
@@ -1267,3 +1256,9 @@ impl Syscall {
         return Ok(s.len());
     }
 }
+
+#[inline(never)]
+pub fn syscall_init() -> Result<(), SystemError> {
+    syscall_table_init()?;
+    Ok(())
+}

+ 129 - 0
kernel/src/syscall/table.rs

@@ -0,0 +1,129 @@
+#![allow(unused)]
+
+use alloc::string::String;
+use alloc::string::ToString;
+use alloc::vec::Vec;
+use core::cell::OnceCell;
+use core::fmt::Display;
+
+use crate::libs::once::Once;
+use crate::syscall::SystemError;
+
+/// 定义Syscall trait
+pub trait Syscall: Send + Sync + 'static {
+    /// 系统调用参数数量
+    fn num_args(&self) -> usize;
+    fn handle(&self, args: &[usize], from_user: bool) -> Result<usize, SystemError>;
+
+    /// Formats the system call parameters for display/debug purposes
+    ///
+    /// # Arguments
+    /// * `args` - System call arguments to format
+    ///
+    /// # Returns
+    /// Vector of formatted parameters with their names and values
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam>;
+}
+
+pub struct FormattedSyscallParam {
+    pub name: &'static str,
+    pub value: String,
+}
+
+impl FormattedSyscallParam {
+    pub fn new(name: &'static str, value: String) -> Self {
+        Self { name, value }
+    }
+}
+
+impl Display for FormattedSyscallParam {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        write!(f, "{}: {}", self.name, self.value)
+    }
+}
+
+/// 系统调用处理句柄
+#[repr(C)]
+pub struct SyscallHandle {
+    pub nr: usize,
+    pub inner_handle: &'static dyn Syscall,
+    pub name: &'static str,
+}
+
+impl SyscallHandle {
+    #[inline(never)]
+    pub fn args_string(&self, args: &[usize]) -> String {
+        let args_slice = self.inner_handle.entry_format(args);
+        args_slice
+            .iter()
+            .map(|p| format!("{}", p))
+            .collect::<Vec<String>>()
+            .join(", ")
+    }
+}
+
+/// 系统调用表类型
+#[repr(C)]
+pub struct SyscallTable {
+    entries: [Option<&'static SyscallHandle>; Self::ENTRIES],
+}
+
+impl SyscallTable {
+    pub const ENTRIES: usize = 512;
+    /// 获取系统调用处理函数
+    pub fn get(&self, nr: usize) -> Option<&'static SyscallHandle> {
+        *self.entries.get(nr)?
+    }
+}
+
+// 声明外部链接的syscall_table符号
+extern "C" {
+    fn _syscall_table();
+    fn _esyscall_table();
+}
+
+/// 全局系统调用表实例
+#[used]
+#[link_section = ".data"]
+static mut SYS_CALL_TABLE: SyscallTable = SyscallTable {
+    entries: [None; SyscallTable::ENTRIES],
+};
+
+#[inline]
+pub(super) fn syscall_table() -> &'static SyscallTable {
+    unsafe { &SYS_CALL_TABLE }
+}
+
+/// 初始化系统调用表
+#[inline(never)]
+pub(super) fn syscall_table_init() -> Result<(), SystemError> {
+    static INIT: Once = Once::new();
+    INIT.call_once(|| {
+        log::debug!("Initializing syscall table...");
+
+        // 初始化系统调用表
+        unsafe {
+            let start = _syscall_table as usize;
+            let end = _esyscall_table as usize;
+            let size = end - start;
+            let count = size / core::mem::size_of::<SyscallHandle>();
+
+            if size % core::mem::size_of::<SyscallHandle>() != 0 {
+                panic!("Invalid syscall table size: {}", size);
+            }
+
+            let handles =
+                core::slice::from_raw_parts(_syscall_table as *const SyscallHandle, count);
+            for handle in handles {
+                if handle.nr < SyscallTable::ENTRIES {
+                    SYS_CALL_TABLE.entries[handle.nr] = Some(handle);
+                } else {
+                    panic!("Invalid syscall number: {}", handle.nr);
+                }
+            }
+
+            log::debug!("Syscall table (count: {count}) initialized successfully.")
+        }
+    });
+    Ok(())
+}

+ 1 - 3
user/apps/riscv_init/Makefile

@@ -8,14 +8,12 @@ CC=$(CROSS_COMPILE)gcc
 
 
 .PHONY: all
-all: main.c
-# $(CC) -static -o init main.c
+all: $(riscv_rust_init)
 	$(MAKE) -C riscv_rust_init ARCH=$(ARCH) install
 
 .PHONY: install clean
 install: all
 	$(MAKE) -C riscv_rust_init ARCH=$(ARCH) install
-# mv init $(DADK_CURRENT_BUILD_DIR)/init
 
 
 clean:

+ 0 - 9
user/apps/riscv_init/main.c

@@ -1,9 +0,0 @@
-#include <stdio.h>
-
-int main() {
-  while(1){
-    printf("\033[43;37mHello, World!\033[0m\n");
-    sleep(1);
-  }
-  return 0;
-}

+ 1 - 1
user/dadk/config/riscv_init-0.1.0.toml

@@ -29,7 +29,7 @@ build-command = "make install"
 # 安装相关信息
 [install]
 # (可选)安装到DragonOS的路径
-in-dragonos-path = "/bin"
+in-dragonos-path = "/"
 # 清除相关信息
 [clean]
 # (可选)清除命令