¿Por qué la escritura deja continuamente 4K bytes en el búfer?

30

Tengo esencialmente el siguiente código:

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;
}

Funciona si el tamaño es de 1 GB, pero cuando el tamaño es de ~ 2 GB, obtiene 4K bytes de manera constante. Puedo arreglar esto envolviendo la escritura en un bucle y moviendo el búfer hacia arriba, pero tengo curiosidad por saber por qué siempre falla.

Por ejemplo, si el tamaño es 2147483648, escribir solo escribe 2147479552, dejando 4096 sin escribir. ¿Por qué sucedería esto y es correcto envolver siempre la escritura en un bucle?

ÁrbolAgua
fuente
2
¿Lo estás ejecutando en modo de 32 bits? 2gig es el número máximo de 32 bits.
Barmar
2
Las reglas sobre la cantidad de datos que writese consumirán a la vez dependen del tipo de sumidero de datos file(por ejemplo, archivo "normal", canalización, socket de flujo, socket de datagrama, ...). ¿Puedes ser mas específico?
zwol
77
Espera, ¿estás intentando ver writetodo el archivo a la vez? El enfoque habitual es transmitir los datos del tamaño de un búfer a la vez hasta que escriba todo.
Luaan
44
@Luaan Si ya dispone de todos los datos que no veo que haya nada malo escribir todo de una vez, pero ya que esta pregunta y respuesta ilustra, write()no tiene que escribir todo (que va para las pequeñas memorias intermedias también)
tubo de
8
"Puedo solucionar esto envolviendo la escritura en un bucle" y debes hacerlo, independientemente de la SSIZE_MAXrestricción. La write()especificación dice que no tiene ninguna obligación de escribir el búfer completo, incluso si casi siempre lo hace. El código sin bucle en la pregunta es un error.
Adam

Respuestas:

50

Puedes encontrar la respuesta en man 2 write:

No es un error si este número es menor que el número de bytes solicitados; Esto puede suceder, por ejemplo, porque el dispositivo de disco estaba lleno.


Y de la write()descripción de la página del manual:

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

Según POSIX.1, si countes mayor que SSIZE_MAX, el resultado está definido por la implementación; vea las NOTAS para el límite superior en Linux.

Notas

En Linux, write()(y llamadas de sistema similares) transferirán como máximo 0x7ffff000(2,147,479,552) bytes, devolviendo el número de bytes realmente transferidos. (Esto es cierto tanto en los sistemas de 32 bits como en los de 64 bits).

bobah
fuente