Methods for handling short reads / writes with scatter command?

Scatter-gather - readv () / writev () / preadv () / pwritev () - reads / writes a variable number of iovec structures in one system call. It basically reads / writes each buffer sequentially from the 0th iovec to the Nth. However, according to the documentation, it can also return fewer readv / writev calls than was requested. I was wondering if there is a standard / best practice / elegant way to handle this situation.

If we just process a bunch of character buffers or the like, that doesn't really matter. But one of the subtleties is the use of scattering for structures and / or discrete variables as separate iovec elements. How do you deal with a situation where readv / writev only reads / writes part of the structure or half the length or something like that.

Below is some kind of flimsy code of what I get:

int fd; struct iovec iov[3]; long aLong = 74775767; int aInt = 949; char aBuff[100]; //filled from where ever ssize_t bytesWritten = 0; ssize_t bytesToWrite = 0; iov[0].iov_base = &aLong; iov[0].iov_len = sizeof(aLong); bytesToWrite += iov[0].iov_len; iov[1].iov_base = &aInt; iov[1].iov_len = sizeof(aInt); bytesToWrite += iov[1].iov_len; iov[2].iov_base = &aBuff; iov[2].iov_len = sizeof(aBuff); bytesToWrite += iov[2].iov_len; bytesWritten = writev(fd, iov, 3); if (bytesWritten == -1) { //handle error } if (bytesWritten < bytesToWrite) //how to gracefully continue?......... 
+6
source share
3 answers

Use a loop like the following to advance the partially processed iov:

 for (;;) { written = writev(fd, iov+cur, count-cur); if (written < 0) goto error; while (cur < count && written >= iov[cur].iov_len) written -= iov[cur++].iov_len; if (cur == count) break; iov[cur].iov_base = (char *)iov[cur].iov_base + written; iov[cur].iov_len -= written; } 

Note that if you do not check cur < count , you will read minus iov , which may contain zero.

+11
source

AFAICS, the functions of the read / write vector work in the same way as the short short read / write, as usual. That is, you return the number of bytes read / written, but this can indicate the middle of the structure, as well as read () / write (). There is no guarantee that possible “breakpoints” (due to the lack of a better term) coincide with the borders of the vector. Therefore, unfortunately, the vector I / O functions no longer help to cope with short reads / writes than the usual I / O functions. This is actually more complicated since you need to map the byte count in the vector I / O element and the offset inside the element.

Also note that the idea of ​​using vector I / O for individual structures or data elements may not work as well; the maximum allowable value for the iovcnt argument (IOV_MAX) is usually quite small, about 1024 or so. Therefore, if you data are adjacent in memory, just pass it as one element, and not artificially split it.

+1
source

A vector record will record all the data you provide, with one call to the "writev" function. Therefore, byteswritten will always be equal to the total number of bytes provided as input. this is what i understand.

Please correct me if I am wrong

-1
source

Source: https://habr.com/ru/post/887096/


All Articles