Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

readv(2)

FieldValue
Numbers (x64 / i386 / arm64-generic / arm32)readv 19 / 145 / 65 / 145; writev 20 / 146 / 66 / 146; preadv 295 / 333 / 69 / 361; pwritev 296 / 334 / 70 / 362; preadv2 327 / 378 / 286 / 392; pwritev2 328 / 379 / 287 / 393 (per-call table below)
Since (kernel)readv, writev 2.0; preadv, pwritev 2.6.30 (glibc 2.10); preadv2, pwritev2 4.6 (glibc 2.26)
Man pageman2/readv.2 (writev.2, preadv.2, pwritev.2, preadv2.2, pwritev2.2 are .so aliases of it)
glibc wrapperall six declared in <sys/uio.h>: readv/writev POSIX.1-2001; preadv/pwritev under __USE_MISC (man page: _DEFAULT_SOURCE since glibc 2.19, _BSD_SOURCE before); preadv2/pwritev2 under __USE_GNU (GNU extension); host glibc 2.41 exports preadv/pwritev@@GLIBC_2.10 and preadv2/pwritev2@@GLIBC_2.26 (nm -D); the raw preadv/pwritev syscalls take offset as two unsigned longs, unpacked by the wrapper
Aliases coveredwritev, preadv, pwritev, preadv2, pwritev2
Ledger IDSC-readv, SC-writev, SC-preadv, SC-pwritev, SC-preadv2, SC-pwritev2

Numbers by call, from the ledger and cross-checked against the cached kernel tables (syscall_64.tbl, syscall_32.tbl, syscall_arm.tbl, syscall_generic.tbl):

Callx64i386g64arm32Since
readv19145651452.0
writev20146661462.0
preadv295333693612.6.30
pwritev296334703622.6.30
preadv23273782863924.6
pwritev23283792873934.6

Hub row note: the domain hub groups all six calls in one row keyed to readv.md and shows preadv’s number set (295 / 333 / 69 / 361) with Since 2.6.30; the per-call values above are the ledger values (SC-readv, SC-writev, SC-preadv, SC-pwritev, SC-preadv2, SC-pwritev2).

Purpose

readv() reads iovcnt buffers from the file referred to by fd into the array of iovec structures (“scatter input”); writev() writes iovcnt buffers out (“gather output”). Buffers are processed in array order: iov[0] is completely filled (or written) before iov[1]. The transfer is atomic with respect to other users of the same open file description: writev() output lands as a single block that is not intermingled with other writers’ output, and readv() reads a contiguous block even if other threads sharing the description read concurrently. preadv()/pwritev() add an explicit offset and leave the file offset unchanged (the fd must be seekable); preadv2()/pwritev2() add a per-call flags argument, and treat offset -1 as “use and update the current file offset”. These are the only calls in the read/write family that carry per-I/O RWF_* flags; plain read() and write() (read.md, write.md) take none.

Synopsis

#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);
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);

Arguments and behavior

ArgumentBehavior
fdFile descriptor as for read()/write() (read.md, write.md); for preadv/pwritev the fd must be capable of seeking, otherwise lseek() errors apply.
iovArray of struct iovec { void *iov_base; size_t iov_len; } processed in array order.
iovcntNumber of iovec elements; 0 < iovcnt <= IOV_MAX (1024 on modern Linux, /usr/include/x86_64-linux-gnu/bits/uio_lim.h __IOV_MAX 1024; it was 16 in Linux 2.0 days). Out of range: EINVAL.
offset (p* forms)File offset for the transfer; the file offset is not changed, except preadv2/pwritev2 with offset -1 use and update the current offset.
flags (v2 forms)OR of RWF_* flags (table below); unknown flag bits fail EOPNOTSUPP.

Return value and errors

Success returns the number of bytes read or written; a short transfer is not an error (read.md, write.md). On error, -1 and errno: the errors of read(2)/write(2) for all six calls, plus the lseek(2) errors (ESPIPE and friends) for the offset forms, plus EINVAL (sum of iov_len values overflows ssize_t; iovcnt < 0 or above the permitted maximum) and EOPNOTSUPP (unknown flag in flags). RWF_NOWAIT returns EAGAIN when data would have to be fetched from storage (see the 5.9/5.10 bug note below).

Flags and constants

RWF_* values from /usr/include/x86_64-linux-gnu/bits/uio-ext.h (glibc 2.41, included by <sys/uio.h> under __USE_GNU); “since” from the cached man2/readv.2 plus man-pages 6.19 readv.2 fetched from man7.org (source-cache/fetched/readv.2.current.plain, per worklog 1-c):

FlagValueSinceMeaning
RWF_HIPRI0x14.6High-priority polled I/O; only meaningful with O_DIRECT
RWF_DSYNC0x24.7Per-write O_DSYNC; only meaningful for pwritev2()
RWF_SYNC0x44.7Per-write O_SYNC; only meaningful for pwritev2()
RWF_NOWAIT0x84.14Do not wait for data that is not immediately available; returns EAGAIN rather than reading from storage; only meaningful for preadv2()
RWF_APPEND0x104.16Per-write O_APPEND; offset ignored, data appended; offset -1 still updates the current offset
RWF_NOAPPEND0x206.9Do not honor O_APPEND for this pwritev2()
RWF_ATOMIC0x406.11Torn-write protection; see write.md for the full constraint list and statx.md for stx_atomic_write_*
RWF_DONTCACHE0x806.14Drop instantiated page-cache pages when the I/O completes; a hint, EOPNOTSUPP if unsupported
RWF_NOSIGNAL0x100(kernel master uapi)Suppress SIGPIPE for pipe/socket writes; in kernel headers, not described in man-pages 6.19 readv.2

RWF_ATOMIC and RWF_DONTCACHE are absent from the cached 2021 man-pages snapshot; the host glibc 2.41 headers define RWF_ATOMIC (0x40) but their RWF_SUPPORTED mask stops there, so RWF_DONTCACHE and RWF_NOSIGNAL are not defined by the installed headers (verified against bits/uio-ext.h).

Security and notes

  • Atomicity caveat: the single-block guarantee is per open file description; with O_APPEND, POSIX appends remain subject to the NFS client-side corruption caveat noted on write.md.
  • POSIX XSI 2.9.7 offset-atomicity: before Linux 3.14 concurrent reads/writes sharing an open file description could overlap; fixed in 3.14 (man2/read.2 BUGS, same rule covers readv/writev).
  • Historical glibc fallback: with early kernels whose IOV_MAX was 16, the glibc readv()/writev() wrappers emulated the call with a temporary buffer and read()/write(); this was needed only for kernels older than 2.6.18 and glibc 2.20+ always calls the syscall directly (man2/readv.2, Historical C library/kernel differences).
  • Linux 5.9 and 5.10 bug: preadv2() with RWF_NOWAIT may return 0 even when not at end of file (man2/readv.2 BUGS).
  • readv()/writev() are POSIX (first appeared in 4.2BSD); preadv/pwritev are nonstandard but on modern BSDs; preadv2/pwritev2 are Linux-specific.

References

  • man2/readv.2 in the cached man-pages tree (dated 2021-08-27); .so aliases writev.2, preadv.2, pwritev.2, preadv2.2, pwritev2.2.
  • man-pages 6.19 readv.2 fetched from man7.org (source-cache/fetched/readv.2.current.plain) for RWF_ATOMIC / RWF_DONTCACHE / RWF_NOAPPEND (worklog 1-c).
  • Constants: /usr/include/x86_64-linux-gnu/sys/uio.h, bits/uio-ext.h, bits/uio_lim.h; kernel master include/uapi/linux/fs.h (source-cache/fetched/k-uapi-fs.h).
  • Syscalls ledger rows SC-readv, SC-writev, SC-preadv, SC-pwritev, SC-preadv2, SC-pwritev2; siblings read, write; domain hub.