Почему запись постоянно оставляет 4K байтов в буфере?


30

У меня есть по существу следующий код:

int fileWrite(int file, void * pBuffer, size_t size)
{
    size_t bytesWritten = (size_t)write( file, pBuffer, size ) ;
    if (bytesWritten != size)
    {
       return -1;
    }
    return 0;
}

Это работает, если размер составляет 1 ГБ, но когда размер составляет ~ 2 ГБ, он последовательно получает 4 КБ байта. Я могу исправить это, поместив запись в цикл и переместив буфер вверх, но мне любопытно, почему он всегда терпит неудачу.

Например, если размер 2147483648, запись только записывает 2147479552, оставляя 4096 незаписанным. Почему это происходит, и правильно ли всегда заключать запись в цикл?


2
Вы запускаете его в 32-битном режиме? 2gig - это максимальное 32-битное число.
Бармар

2
Правила того, сколько данных writeбудет потребляться одновременно, зависят от типа приемника данных file(например, «обычный» файл, канал, сокет потока, сокет дейтаграммы, ...). Можете быть более конкретными?
Звол

7
Подождите, вы пытаетесь writeвесь файл сразу? Обычный подход заключается в потоковой передаче данных размером буфера за раз, пока вы не напишите все.
Луаан

4
@Luaan Если у вас уже есть все данные, я не вижу, что что-то неправильно записывает все сразу, но, как показывает этот вопрос и ответ, write()не нужно записывать все это (что касается небольших буферов)
pipe

8
«Я могу исправить это, поместив запись в цикл», и вам нужно, независимо от SSIZE_MAXограничения. Спецификация write()говорит, что не обязана писать полный буфер, даже если это почти всегда так. Код без петель в вопросе является ошибкой.
Адам

Ответы:


50

Вы можете найти ответ в man 2 write:

Не является ошибкой, если это число меньше числа запрошенных байтов; это может произойти, например, потому что дисковое устройство было заполнено.


И из write()описания страницы руководства :

ssize_t write(int fd, const void *buf, size_t count);

Согласно POSIX.1, если countбольше чем SSIZE_MAX, результат определяется реализацией; см. примечания для верхнего предела в Linux.

НОТЫ

В Linux write()(и аналогичных системных вызовах) будет передано не более 0x7ffff000(2 147 479 552) байтов, возвращая количество фактически переданных байтов. (Это верно как для 32-битных, так и для 64-битных систем.)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.