sys_readv.rs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. use system_error::SystemError;
  2. use crate::arch::syscall::nr::SYS_READV;
  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_read::do_read;
  10. /// System call handler for `readv` operation
  11. ///
  12. /// The `readv` system call reads data into multiple buffers from a file descriptor.
  13. /// It is equivalent to multiple `read` calls but is more efficient.
  14. pub struct SysReadVHandle;
  15. impl Syscall for SysReadVHandle {
  16. fn num_args(&self) -> usize {
  17. 3
  18. }
  19. fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
  20. let fd = Self::fd(args);
  21. let iov = Self::iov(args);
  22. let count = Self::count(args);
  23. // IoVecs会进行用户态检验
  24. let iovecs = unsafe { IoVecs::from_user(iov, count, true) }?;
  25. let mut data = vec![0; iovecs.total_len()];
  26. let len = do_read(fd, &mut data)?;
  27. iovecs.scatter(&data[..len]);
  28. return Ok(len);
  29. }
  30. fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
  31. vec![
  32. FormattedSyscallParam::new("fd", Self::fd(args).to_string()),
  33. FormattedSyscallParam::new("iov", format!("{:#x}", Self::iov(args) as usize)),
  34. FormattedSyscallParam::new("count", Self::count(args).to_string()),
  35. ]
  36. }
  37. }
  38. impl SysReadVHandle {
  39. fn fd(args: &[usize]) -> i32 {
  40. args[0] as i32
  41. }
  42. fn iov(args: &[usize]) -> *const IoVec {
  43. args[1] as *const IoVec
  44. }
  45. fn count(args: &[usize]) -> usize {
  46. args[2]
  47. }
  48. }
  49. syscall_table_macros::declare_syscall!(SYS_READV, SysReadVHandle);