Чому запис постійно залишає 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(наприклад, "звичайний" файл, труба, сокет потоку, сокет дейтаграми, ...). Чи можете ви бути більш конкретними?
zwol

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.