Когда системный вызов write () записывает весь запрошенный буфер, а не просто выполняет частичную запись? - PullRequest
6 голосов
/ 29 марта 2009

Если я рассчитываю на мой системный вызов write () для записи, скажем, например, 100 байт, я всегда помещаю этот вызов write () в цикл, который проверяет, является ли возвращаемая длина той, которую я ожидал отправить, и если нет, то он увеличивает указатель буфера и уменьшает длину на величину, которая была записана.

Итак, еще раз я только что сделал это, но теперь, когда есть StackOverflow, я могу спросить вас всех, знают ли люди, когда мои записи напишут ВСЕ, что я прошу по сравнению с возвратом мне частичной записи?

Дополнительные комментарии: Ответ X-Istence напомнил мне, что я должен был отметить, что файловый дескриптор был блокирующим (т.е. не неблокирующим). Я думаю, он предлагает, чтобы единственный способ write () в дескрипторе блокирующего файла не записывал все указанные данные, это когда write () прерывался сигналом. Мне кажется, это по крайней мере интуитивно понятно ...

Ответы [ 3 ]

5 голосов
/ 29 марта 2009
Запись

может возвращать частичную запись, особенно с использованием операций над сокетами или при заполнении внутренних буферов. Так что хороший способ сделать следующее:

while(size > 0 && (res=write(fd,buff,size))!=size) {
    if(res<0 && errno==EINTR) 
       continue;
    if(res < 0) {
        // real error processing
        break;
    }
    size-=res;
    buf+=res;
}

Никогда не передавайте то, что обычно происходит ...

Примечание: в случае полного диска вы получите ENOSPC без частичной записи.

4 голосов
/ 29 марта 2009

Вам нужно проверить errno, чтобы увидеть, был ли прерван ваш вызов, или почему write () вернулась раньше, и почему он записал только определенное количество байтов.

С мужчина 2, запись

При использовании неблокирующих операций ввода-вывода для таких объектов, как сокеты, которые подлежат управлению потоком, write () и writev () могут записать меньше байтов, чем запрошено; возвращаемое значение должно быть отмечено, а остаток операции должен быть повторен, когда это возможно.

По сути, если вы не записываете в неблокирующий сокет, только в другой раз это произойдет, если вас прервет сигнал.

[EINTR] Сигнал прервал запись, прежде чем она могла быть завершена.

См. Раздел «Ошибки» на справочной странице для получения дополнительной информации о том, что можно вернуть и когда оно будет возвращено. Оттуда вам нужно выяснить, является ли ошибка достаточно серьезной, чтобы зарегистрировать ошибку и выйти, или вы можете продолжить операцию под рукой!

Все это обсуждается в книге: Расширенное программирование Unix Марком Дж. Рочкиндом , я написал бесчисленное количество программ с помощью этой книги и предложил бы это при программировании для UNIX-подобных ОС.

0 голосов
/ 29 марта 2009

Записывает, не должно быть никаких причин когда-либо записывать частичный буфер на афаик. Возможные причины частичной записи: если у вас заканчивается свободное место на диске, вы пишете после конца блочного устройства, или если вы пишете на символьное устройство / какое-либо другое устройство.

Однако план повторных попыток записи вслепую, вероятно, не такой удачный - проверьте, чтобы узнать, следует ли вам повторить попытку в первую очередь.

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