From 27b967a38a6dd7a266c43b5e705c29dfbbd71ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A3=95=E4=BE=9D?= <68320855+yuyi2439@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:53:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0pread&pwrite=20(#528)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加pread&pwrite --- kernel/src/filesystem/vfs/file.rs | 97 +++++++++++++++++++++------- kernel/src/filesystem/vfs/syscall.rs | 48 +++++++++++++- kernel/src/syscall/mod.rs | 46 +++++++++++-- 3 files changed, 160 insertions(+), 31 deletions(-) diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index fb3f7405..05e9cd40 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -169,22 +169,7 @@ impl File { /// @return Ok(usize) 成功读取的字节数 /// @return Err(SystemError) 错误码 pub fn read(&mut self, len: usize, buf: &mut [u8]) -> Result { - // 先检查本文件在权限等规则下,是否可读取。 - self.readable()?; - - if buf.len() < len { - return Err(SystemError::ENOBUFS); - } - - // 如果文件指针已经超过了文件大小,则返回0 - if self.offset > self.inode.metadata()?.size as usize { - return Ok(0); - } - let len = self - .inode - .read_at(self.offset, len, buf, &mut self.private_data)?; - self.offset += len; - return Ok(len); + self.do_read(self.offset, len, buf, true) } /// @brief 从buffer向文件写入指定的字节数的数据 @@ -195,6 +180,71 @@ impl File { /// @return Ok(usize) 成功写入的字节数 /// @return Err(SystemError) 错误码 pub fn write(&mut self, len: usize, buf: &[u8]) -> Result { + self.do_write(self.offset, len, buf, true) + } + + /// ## 从文件中指定的偏移处读取指定的字节数到buf中 + /// + /// ### 参数 + /// - `offset`: 文件偏移量 + /// - `len`: 要读取的字节数 + /// - `buf`: 读出缓冲区 + /// + /// ### 返回值 + /// - `Ok(usize)`: 成功读取的字节数 + pub fn pread( + &mut self, + offset: usize, + len: usize, + buf: &mut [u8], + ) -> Result { + self.do_read(offset, len, buf, false) + } + + /// ## 从buf向文件中指定的偏移处写入指定的字节数的数据 + /// + /// ### 参数 + /// - `offset`: 文件偏移量 + /// - `len`: 要写入的字节数 + /// - `buf`: 写入缓冲区 + /// + /// ### 返回值 + /// - `Ok(usize)`: 成功写入的字节数 + pub fn pwrite(&mut self, offset: usize, len: usize, buf: &[u8]) -> Result { + self.do_write(offset, len, buf, false) + } + + fn do_read( + &mut self, + offset: usize, + len: usize, + buf: &mut [u8], + update_offset: bool, + ) -> Result { + // 先检查本文件在权限等规则下,是否可读取。 + self.readable()?; + if buf.len() < len { + return Err(SystemError::ENOBUFS); + } + + let len = self + .inode + .read_at(offset, len, buf, &mut self.private_data)?; + + if update_offset { + self.offset += len; + } + + Ok(len) + } + + fn do_write( + &mut self, + offset: usize, + len: usize, + buf: &[u8], + update_offset: bool, + ) -> Result { // 先检查本文件在权限等规则下,是否可写入。 self.writeable()?; if buf.len() < len { @@ -202,15 +252,18 @@ impl File { } // 如果文件指针已经超过了文件大小,则需要扩展文件大小 - let file_size = self.inode.metadata()?.size as usize; - if self.offset > file_size { - self.inode.resize(self.offset)?; + if offset > self.inode.metadata()?.size as usize { + self.inode.resize(offset)?; } let len = self .inode - .write_at(self.offset, len, buf, &mut self.private_data)?; - self.offset += len; - return Ok(len); + .write_at(offset, len, buf, &mut self.private_data)?; + + if update_offset { + self.offset += len; + } + + Ok(len) } /// @brief 获取文件的元数据 diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index a5126bfc..3e8beae0 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -304,7 +304,7 @@ impl Syscall { /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 /// /// @param fd 文件描述符编号 - /// @param buf 输出缓冲区。 + /// @param buf 输出缓冲区 /// /// @return Ok(usize) 成功读取的数据的字节数 /// @return Err(SystemError) 读取失败,返回posix错误码 @@ -326,7 +326,7 @@ impl Syscall { /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 /// /// @param fd 文件描述符编号 - /// @param buf 输入缓冲区。 + /// @param buf 输入缓冲区 /// /// @return Ok(usize) 成功写入的数据的字节数 /// @return Err(SystemError) 写入失败,返回posix错误码 @@ -362,6 +362,50 @@ impl Syscall { return file.lock_no_preempt().lseek(seek); } + /// # sys_pread64 系统调用的实际执行函数 + /// + /// ## 参数 + /// - `fd`: 文件描述符 + /// - `buf`: 读出缓冲区 + /// - `len`: 要读取的字节数 + /// - `offset`: 文件偏移量 + pub fn pread(fd: i32, buf: &mut [u8], len: usize, offset: usize) -> Result { + 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.lock_no_preempt().pread(offset, len, buf); + } + + /// # sys_pwrite64 系统调用的实际执行函数 + /// + /// ## 参数 + /// - `fd`: 文件描述符 + /// - `buf`: 写入缓冲区 + /// - `len`: 要写入的字节数 + /// - `offset`: 文件偏移量 + pub fn pwrite(fd: i32, buf: &[u8], len: usize, offset: usize) -> Result { + 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.lock_no_preempt().pwrite(offset, len, buf); + } + /// @brief 切换工作目录 /// /// @param dest_path 目标路径 diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index f08e3edb..94e92211 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -129,9 +129,7 @@ impl Syscall { } SYS_CLOSE => { let fd = args[0]; - let res = Self::close(fd); - - res + Self::close(fd) } SYS_READ => { let fd = args[0] as i32; @@ -142,8 +140,7 @@ impl Syscall { UserBufferWriter::new(buf_vaddr as *mut u8, len, from_user)?; let user_buf = user_buffer_writer.buffer(0)?; - let res = Self::read(fd, user_buf); - res + Self::read(fd, user_buf) } SYS_WRITE => { let fd = args[0] as i32; @@ -154,8 +151,7 @@ impl Syscall { UserBufferReader::new(buf_vaddr as *const u8, len, from_user)?; let user_buf = user_buffer_reader.read_from_user(0)?; - let res = Self::write(fd, user_buf); - res + Self::write(fd, user_buf) } SYS_LSEEK => { @@ -173,6 +169,32 @@ impl Syscall { Self::lseek(fd, w) } + + SYS_PREAD64 => { + let fd = args[0] as i32; + let buf_vaddr = args[1]; + let len = args[2]; + let offset = args[3]; + + let mut user_buffer_writer = + UserBufferWriter::new(buf_vaddr as *mut u8, len, frame.from_user())?; + let buf = user_buffer_writer.buffer(0)?; + Self::pread(fd, buf, len, offset) + } + + SYS_PWRITE64 => { + let fd = args[0] as i32; + let buf_vaddr = args[1]; + let len = args[2]; + let offset = args[3]; + + let user_buffer_reader = + UserBufferReader::new(buf_vaddr as *const u8, len, frame.from_user())?; + + let buf = user_buffer_reader.read_from_user(0)?; + Self::pwrite(fd, buf, len, offset) + } + SYS_IOCTL => { let fd = args[0]; let cmd = args[1]; @@ -943,6 +965,16 @@ impl Syscall { Self::umask(mask) } + SYS_FCHOWN => { + kwarn!("SYS_FCHOWN has not yet been implemented"); + Ok(0) + } + + SYS_FSYNC => { + kwarn!("SYS_FSYNC has not yet been implemented"); + Ok(0) + } + #[cfg(target_arch = "x86_64")] SYS_CHMOD => { let pathname = args[0] as *const u8;