Browse Source

添加pread&pwrite (#528)

添加pread&pwrite
裕依 1 year ago
parent
commit
27b967a38a
3 changed files with 160 additions and 31 deletions
  1. 75 22
      kernel/src/filesystem/vfs/file.rs
  2. 46 2
      kernel/src/filesystem/vfs/syscall.rs
  3. 39 7
      kernel/src/syscall/mod.rs

+ 75 - 22
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<usize, SystemError> {
-        // 先检查本文件在权限等规则下,是否可读取。
-        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<usize, SystemError> {
+        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<usize, SystemError> {
+        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<usize, SystemError> {
+        self.do_write(offset, len, buf, false)
+    }
+
+    fn do_read(
+        &mut self,
+        offset: usize,
+        len: usize,
+        buf: &mut [u8],
+        update_offset: bool,
+    ) -> Result<usize, SystemError> {
+        // 先检查本文件在权限等规则下,是否可读取。
+        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<usize, SystemError> {
         // 先检查本文件在权限等规则下,是否可写入。
         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 获取文件的元数据

+ 46 - 2
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<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.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<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.lock_no_preempt().pwrite(offset, len, buf);
+    }
+
     /// @brief 切换工作目录
     ///
     /// @param dest_path 目标路径

+ 39 - 7
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;