#+title: Vectored IO
#+date: <2022-10-22 Sat 16:07>
#+author: thebesttv

在做网络编程的 异步TCP 作业的时候, [[file:./liburing.org][想用 =liburing=]],
发现要先学一下 =readv()= 和 =writev()=:
- [[https://en.wikipedia.org/wiki/Vectored_I/O][Wiki: Vectored I/O]]
- [[https://www.oreilly.com/library/view/linux-system-programming/0596009585/ch04.html#:~:text=fun%20to%20implement.-,readv(%20)%20and%20writev(%20),-POSIX%201003.1%2D2001][Chapter 4. Advanced File I/O --- Linux System Programming by Robert Love]]

* What is Vectored IO

/Vectored IO/ is doing IO with *a vector of buffers*, instead of using
just a single buffer as in =read()= and =write()=.  It is also called
/scatter/gather IO/, as it scatters data into, or gathers data from, a
set of buffers.

* Vectored IO in Linux

=readv()= (scatter input) and =writev()= (gather output) are Linux
implementations of vectored IO.  They share the exact same signature:
#+begin_src c
  #include <sys/uio.h>
  ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
  ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
#+end_src
Here =iov= is an array of buffers, and =iovcnt= is the length of the
array (i.e. it counts how many buffers there are in the array).  A
description of the =iov= array from =man 3 iovec=:
#+begin_quote
each element of the array represents a memory region, and the whole
array represents a vector of memory regions.
#+end_quote

Each buffer in the =iov= array is a =struct iovec=:
#+begin_src c
  #include <sys/uio.h>
  struct iovec {
    void   *iov_base;  /* Starting address */
    size_t  iov_len;   /* Size of the memory pointed to by iov_base. */
  };
#+end_src

* Comparison with =read()= & =write()=

Traditional =read()= and =write()= functions have similar signatures
except for the single buffer =buf=, which is non-=const= with =read()=
(as data is written to =buf=) and =const= with =write()= (as data is
only read from =buf=).
#+begin_src c
  #include <unistd.h>
  ssize_t read(int fd, void *buf, size_t count);
  ssize_t write(int fd, const void *buf, size_t count);
#+end_src

* Examples

** =write()=

Printing a message to stdout with =write()=:
#+include: vectored-io/hw-write.c src c

** =writev()=

Splitting the message into 3 separate buffers and printing them to
stdout with =writev()=:
#+include: vectored-io/hw-writev.c src c