The classic read() and write() sycalls enable you to handle a single buffer at a time. The problem is that applications often need to write various data types to a contiguous region of a file. Although you can use multiple write() calls to accomplish that, this isn't an atomic operation; another thread might access the same file region between every pair of write() calls.
As a workaround, you can pack all the data into a single buffer before writing it to a file. However, the performance overhead incurred by copying numerous memory blocks is noticeable.
Scatter/Gather Read and Write
The readv() and writev() solve this problem easily. Instead of handling a single data buffer at a time, they take an array of records, each of which represents a distinct buffer. These buffers are read from or written to in the same order that they are listed in the array. More importantly, the writev() and readv() calls are atomic.
readv() and writev() are called "scatter and gather read and write" because readv() scatters data from various sources across memory and writev() gathers data from various memory addresses. These functions are declared as follows:
int readv(int fd, const struct iovec* vec, size_t count);
int writev(int fd, const struct iovec* vec, size_t count);
The first argument is the file descriptor to be read from or written to. The second argument is a pointer to one or more structs of type iovec, which represents a data buffer. The third argument is the number of iovec structs passed in vec. Struct iovec is declared as follows:
struct iovec{ void * iov_base;
/*buffer's address*/ size_t iov_len;
/*buffer's size in bytes*/ };
The return value of both functions is the total number of bytes read or written. Example The following program gathers three buffers (strings, in this case) and outputs them using a single writev() call. The result is displayed on the standard output:
#include
int main
{ iovec vecs[3];
vecs[0].iov_base="first";
vecs[0].iov_len=5;
vecs[1].iov_base=" second ";
vecs[1].iov_len=8;
vecs[2].iov_base="last\n";
vecs[2].iov_len=5;
writev(1, vecs, 3);
/*1 is equal to stdout*/
}
This story, "Scatter/Gather I/O" was originally published by ITworld.