sys_writev.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. use system_error::SystemError;
  2. use crate::arch::syscall::nr::SYS_WRITEV;
  3. use crate::filesystem::vfs::iov::IoVec;
  4. use crate::filesystem::vfs::iov::IoVecs;
  5. use crate::syscall::table::FormattedSyscallParam;
  6. use crate::syscall::table::Syscall;
  7. use alloc::string::ToString;
  8. use alloc::vec::Vec;
  9. use super::sys_write::do_write;
  10. /// System call handler for `writev` operation
  11. ///
  12. /// The `writev` system call writes data from multiple buffers to a file descriptor.
  13. /// It is equivalent to multiple `write` calls but is more efficient.
  14. pub struct SysWriteVHandle;
  15. impl Syscall for SysWriteVHandle {
  16. /// Returns the number of arguments required by the `writev` system call
  17. fn num_args(&self) -> usize {
  18. 3
  19. }
  20. /// Handles the `writev` system call
  21. ///
  22. /// # Arguments
  23. /// * `args` - System call arguments containing:
  24. /// * `fd`: File descriptor to write to
  25. /// * `iov`: Pointer to array of I/O vectors
  26. /// * `count`: Number of elements in the I/O vector array
  27. /// * `_from_user` - Flag indicating if the call originated from user space
  28. ///
  29. /// # Returns
  30. /// * `Ok(usize)` - Number of bytes written
  31. /// * `Err(SystemError)` - Error that occurred during operation
  32. ///
  33. /// # Safety
  34. /// The caller must ensure the `iov` pointer is valid and points to properly initialized memory.
  35. fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
  36. let fd = Self::fd(args);
  37. let iov = Self::iov(args);
  38. let count = Self::count(args);
  39. // IoVecs会进行用户态检验
  40. let iovecs = unsafe { IoVecs::from_user(iov, count, false) }?;
  41. let data = iovecs.gather();
  42. do_write(fd, &data)
  43. }
  44. /// Formats the system call parameters for display/debug purposes
  45. ///
  46. /// # Arguments
  47. /// * `args` - System call arguments to format
  48. ///
  49. /// # Returns
  50. /// Vector of formatted parameters with their names and values
  51. fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
  52. vec![
  53. FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
  54. FormattedSyscallParam::new("iov", format!("{:#x}", Self::iov(args) as usize)),
  55. FormattedSyscallParam::new("count", Self::count(args).to_string()),
  56. ]
  57. }
  58. }
  59. impl SysWriteVHandle {
  60. /// Extracts the file descriptor from system call arguments
  61. fn fd(args: &[usize]) -> i32 {
  62. args[0] as i32
  63. }
  64. /// Extracts the I/O vector pointer from system call arguments
  65. fn iov(args: &[usize]) -> *const IoVec {
  66. args[1] as *const IoVec
  67. }
  68. /// Extracts the I/O vector count from system call arguments
  69. fn count(args: &[usize]) -> usize {
  70. args[2]
  71. }
  72. }
  73. syscall_table_macros::declare_syscall!(SYS_WRITEV, SysWriteVHandle);