Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
refactor(vfs): 将read和readv系统调用提取到独立模块
Signed-off-by: longjin <[email protected]>
  • Loading branch information
fslongjin committed May 13, 2025
commit abecb993b3acec7c442af1b78e1a5f8679f13331
38 changes: 2 additions & 36 deletions kernel/src/filesystem/vfs/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use crate::{
time::{syscall::PosixTimeval, PosixTimeSpec},
};

use super::iov::{IoVec, IoVecs};
use super::stat::{do_newfstatat, do_statx, PosixKstat};
use super::vcore::do_symlinkat;
use super::{
Expand All @@ -36,6 +35,8 @@ use super::{
VFS_MAX_FOLLOW_SYMLINK_TIMES,
};

mod sys_read;
mod sys_readv;
mod sys_write;
mod sys_writev;

Expand Down Expand Up @@ -501,28 +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 调整文件操作指针的位置
///
/// @param fd 文件描述符编号
Expand Down Expand Up @@ -1405,19 +1384,6 @@ impl Syscall {
return Ok(0);
}

pub fn readv(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> {
// IoVecs会进行用户态检验
let iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, true) }?;

let mut data = vec![0; iovecs.total_len()];

let len = Self::read(fd, &mut data)?;

iovecs.scatter(&data[..len]);

return Ok(len);
}

pub fn readlink_at(
dirfd: i32,
path: *const u8,
Expand Down
105 changes: 105 additions & 0 deletions kernel/src/filesystem/vfs/syscall/sys_read.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 65 additions & 0 deletions kernel/src/filesystem/vfs/syscall/sys_readv.rs
Original file line number Diff line number Diff line change
@@ -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);
6 changes: 3 additions & 3 deletions kernel/src/filesystem/vfs/syscall/sys_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Syscall for SysWriteHandle {
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::count(args);
let len = Self::len(args);

let user_buffer_reader = UserBufferReader::new(buf_vaddr, len, from_user)?;

Expand All @@ -57,7 +57,7 @@ impl Syscall for SysWriteHandle {
vec![
FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
FormattedSyscallParam::new("buf", format!("{:#x}", Self::buf(args) as usize)),
FormattedSyscallParam::new("count", Self::count(args).to_string()),
FormattedSyscallParam::new("len", Self::len(args).to_string()),
]
}
}
Expand All @@ -74,7 +74,7 @@ impl SysWriteHandle {
}

/// Extracts the buffer length from syscall arguments
fn count(args: &[usize]) -> usize {
fn len(args: &[usize]) -> usize {
args[2]
}
}
Expand Down
13 changes: 0 additions & 13 deletions kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +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_LSEEK => {
let fd = args[0] as i32;
Expand Down Expand Up @@ -784,8 +773,6 @@ impl Syscall {
return ret;
}

SYS_READV => Self::readv(args[0] as i32, args[1], args[2]),

SYS_SET_TID_ADDRESS => Self::set_tid_address(args[0]),

#[cfg(target_arch = "x86_64")]
Expand Down