Vectored IO
在做网络编程的 异步TCP 作业的时候, 想用 liburing
,
发现要先学一下 readv()
和 writev()
:
1. 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.
2. Vectored IO in Linux
readv()
(scatter input) and writev()
(gather output) are Linux
implementations of vectored IO. They share the exact same signature:
#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);
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
:
each element of the array represents a memory region, and the whole array represents a vector of memory regions.
Each buffer in the iov
array is a struct iovec
:
#include <sys/uio.h> struct iovec { void *iov_base; /* Starting address */ size_t iov_len; /* Size of the memory pointed to by iov_base. */ };
3. 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
).
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count);
4. Examples
4.1. write()
Printing a message to stdout with write()
:
#include <stdio.h> // perror() #include <stdlib.h> // exit(), EXIT_SUCCESS, EXIT_FAILURE #include <unistd.h> // write(), STDOUT_FILENO int main() { const char buf[] = "Hello world from thebesttv!\n"; if (write(STDOUT_FILENO, buf, sizeof(buf)) == -1) { perror("write()"); exit(EXIT_FAILURE); } return EXIT_SUCCESS; }
4.2. writev()
Splitting the message into 3 separate buffers and printing them to
stdout with writev()
:
#include <stdio.h> // perror() #include <string.h> // strlen() #include <stdlib.h> // exit(), EXIT_SUCCESS, EXIT_FAILURE #include <unistd.h> // STDOUT_FILENO #include <sys/uio.h> // vectored IO: iovec, writev() #define LENGTH 3 int main() { const char *bufs[LENGTH] = {"Hello ", "world ", "from thebesttv!\n"}; struct iovec vecs[LENGTH]; for (int i = 0; i < LENGTH; i++) { vecs[i].iov_base = (void *)bufs[i]; vecs[i].iov_len = strlen(bufs[i]); }; if (writev(STDOUT_FILENO, vecs, LENGTH) == -1) { perror("writev()"); exit(EXIT_FAILURE); } return EXIT_SUCCESS; }