jwb@cepmax.ncsu.edu (John W. Baugh Jr.) (06/22/91)
Stevens (in Unix Network Programming) notes that read/write on a socket may input/output fewer bytes than requested. Can I expect the same behavior for readv/writev? If so, how might one implement "readvn"/"writevn"? (a la Steven's readn/writen) John Baugh jwb@cepmax.ncsu.edu
torek@elf.ee.lbl.gov (Chris Torek) (06/24/91)
In article <1991Jun21.215941.5693@ncsu.edu> jwb@cepmax.ncsu.edu writes: >Stevens (in Unix Network Programming) notes that read/write on a >socket may input/output fewer bytes than requested. Can I expect the >same behavior for readv/writev? Yes. >If so, how might one implement "readvn"/"writevn"? (a la Steven's ...) (I am guessing what these are: loops around the read/write calls.) It is ugly. You must make use of the fact that the if the system call returns `early', it has partially processed at most one vector (and fully processed only any earlier vectors). Thus, something like: cc = readv(fd, iov, iovcnt); if (cc == 0) ... handle EOF ...; if (cc < 0) ... handle error ...; for (p = iov, n = iovcnt; n > 0; p++, n--) { if (iov->iov_len > cc) { iov->iov_base += cc; iov->iov_len -= cc; break; } cc -= iov->iov_len; } if (cc == 0) ... all done ...; iov = p; iovcnt = n; /* now there are iovcnt io vectors undone */ Note that this may modify one of the I/O vectors, hence is not suitable in some cases. To be fully general this would have to copy the vectors in those cases, and work from the copies; then it would have to free the copies when the whole transfer is done. This is one reason I elected to ignore readv and writev in my 4BSD stdio rewrite. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
rsalz@bbn.com (Rich Salz) (06/26/91)
In <1991Jun21.215941.5693@ncsu.edu> jwb@cepmax.ncsu.edu writes: >Stevens (in Unix Network Programming) notes that read/write on a >socket may input/output fewer bytes than requested. Can I expect the >same behavior for readv/writev? If so, how might one implement >"readvn"/"writevn"? (a la Steven's readn/writen) I assume you want something like this: /* ** Handling the return value of writev is a pain. It should return ** the number of iov's it fully wrote out, and update the fields ** in all of them to contain the new startpoints. */ int bigwritev(fd, vp, vpcount) int fd; struct iovec *vp; register int vpcount; { register int i; register long left; /* Get the total bytecount. */ for (left = 0, i = vpcount; --i >= 0; ) left += vp[i].iov_len; while (vpcount) { if ((i = writev(fd, vp, vpcount)) < 0) return -1; if ((left -= i) <= 0) break; for (; i >= vp->iov_len; vp++, vpcount--) i -= vp->iov_len; vp->iov_base += i; vp->iov_len -= i; } return 0; } -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.
torek@elf.ee.lbl.gov (Chris Torek) (06/26/91)
In article <14609@dog.ee.lbl.gov> I wrote: > for (p = iov, n = iovcnt; n > 0; p++, n--) { > if (iov->iov_len > cc) { [etc] All the `iov->'s in the loop should be `p->'s. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov