The writev function takes an array of struct iovec as input argument
writev(int fd, const struct iovec *iov, int iovcnt);
The input is a list of memory buffers that need to be written to a file (say). What I want to know is:
Does writev internally do this:
for (each element in iov)
write(element)
such that every element of iov is written to file in a separate I/O call? Or does writev write everything to file in a single I/O call?
Per the standards, the for loop you mentioned is not a valid implementation of
writev, for several reasons:PIPE_BUF, the pipe write is required to be atomic, but the loop would break the atomicity requirement. This issue cannot be worked around except by moving all the iov entries into a single buffer before writing when the total length is at mostPIPE_BUF.writevcall would be required to perform a partial write without blocking. As far as I know, this issue would be impossible to work around in the general case.I’m not sure about point #3, but it definitely exists in the opposite direction, when reading. Calling
readin a loop could block if a terminal has some data (shorter than the total iov length) available followed by an EOF indicator; callingreadvshould return immediately with a partial read in this case. However, due to a bug in Linux,readvon terminals is actually implemented as areadloop in kernelspace, and it does exhibit this blocking bug. I had to work around this bug in implementing musl’s stdio:http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=commit;h=2cff36a84f268c09f4c9dc5a1340652c8e298dc0
To answer the last part of your question:
In all cases, a conformant
writevimplementation will be a single syscall. Getting down to how it’s implemented on Linux: for ordinary files and for most devices, the underlying file driver has methods that implement iov-style io directly, without any sort of internal loop. But the terminal driver on Linux is highly outdated and lacks the modern io methods, causing the kernel to fallback to a write/read loop forwritev/readvwhen operating on a terminal.