Методы обработки коротких операций чтения / записи с разбросом? - PullRequest
7 голосов
/ 02 мая 2011

Scatter-collect - readv () / writev () / preadv () / pwritev () - читает / записывает переменное число структур iovec в одном системном вызове. В основном он читает / записывает каждый буфер последовательно от 0-го Iovec до N-го. Однако, согласно документации, он также может возвращать меньше вызовов readv / writev, чем было запрошено. Мне было интересно, есть ли стандартный / лучший метод / элегантный способ справиться с этой ситуацией.

Если мы просто работаем с кучей буферов символов или схожими, это не имеет большого значения. Но одна из тонкостей заключается в использовании разброса данных для структур и / или дискретных переменных в качестве отдельных элементов iovec. Как вы справляетесь с ситуацией, когда readv / writev только читает / записывает часть структуры или половину long или что-то в этом роде.

Ниже приведен некий придуманный код того, что я получаю:

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?.........

Ответы [ 3 ]

11 голосов
/ 02 мая 2011

Используйте цикл, подобный следующему, для продвижения частично обработанного 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;
}

Обратите внимание, что если вы не проверите cur < count, вы будете читать после конца iov, который может содержать ноль.

1 голос
/ 02 мая 2011

AFAICS, функции векторного чтения / записи работают так же, как и обычные, с короткими операциями чтения / записи. То есть вы получаете количество прочитанных / записанных байтов, но это вполне может указывать на середину структуры, как и в случае read () / write (). Нет гарантии, что возможные «точки прерывания» (из-за отсутствия лучшего термина) совпадают с векторными границами. К сожалению, функции векторного ввода-вывода, к сожалению, не дают большей помощи при работе с короткими операциями чтения / записи, чем обычные функции ввода-вывода. На самом деле все сложнее, поскольку вам необходимо отобразить число байтов в элемент вектора ввода-вывода и смещение внутри элемента.

Также обратите внимание, что идея использования векторного ввода-вывода для отдельных структур или элементов данных может не сработать; максимально допустимое значение для аргумента iovcnt (IOV_MAX) обычно довольно мало, что-то вроде 1024 или около того. Поэтому, если ваши данные находятся в памяти непрерывно, просто передайте их как один элемент, а не делите их искусственно.

0 голосов
/ 02 мая 2011

Vectored write запишет все данные, которые вы предоставили, одним вызовом функции "writev".Поэтому byteswritten всегда будет равно общему количеству байтов, предоставленных в качестве входных данных.это то, что я понимаю.

Пожалуйста, поправьте меня, если я ошибаюсь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...