Por que a gravação deixa continuamente 4K bytes no buffer?

30

Eu tenho essencialmente o seguinte 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 se o tamanho é de 1 GB, mas quando o tamanho é de ~ 2 GB, obtém 4K bytes permanentemente. Eu posso corrigir isso colocando a gravação em um loop e movendo o buffer para cima, mas estou curioso para saber por que está sempre falhando.

Por exemplo, se o tamanho for 2147483648, somente as gravações serão gravadas 2147479552, deixando 4096 não gravadas. Por que isso aconteceria e é correto sempre envolver a gravação em um loop?

ÁrvoreÁgua
fonte
2
Você está executando no modo de 32 bits? 2gig é o número máximo de 32 bits.
Barmar 10/04
2
As regras para a quantidade de dados writeconsumidos ao mesmo tempo dependem do tipo de coletor de dados file(por exemplo, arquivo "regular", canal, soquete de fluxo, soquete de datagrama, ...). Você pode ser mais específico?
zwol 10/04
7
Espere, você está tentando writeo arquivo inteiro de uma só vez? A abordagem usual é transmitir os dados com um tamanho de buffer por vez até você escrever tudo.
Luaan 11/04
4
@Luaan Se você já possui todos os dados, não vejo que haja algo errado ao escrever tudo de uma vez, mas, como ilustram esta pergunta e resposta, write()não precisa escrever tudo (o que também vale para pequenos buffers)
pipe
8
"Eu posso consertar isso envolvendo a gravação em um loop" e você precisa, independentemente da SSIZE_MAXrestrição. A write()especificação diz que não tem obrigação de escrever o buffer completo, mesmo que quase sempre o faça. O código sem loop na pergunta é um bug.
Adam

Respostas:

50

Você pode encontrar a resposta em man 2 write:

Não é um erro se esse número for menor que o número de bytes solicitados; isso pode acontecer, por exemplo, porque o dispositivo de disco foi preenchido.


E a partir da write()descrição da página de manual:

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

De acordo com o POSIX.1, se countfor maior que SSIZE_MAX, o resultado é definido pela implementação; veja NOTAS para o limite superior no Linux.

NOTAS

No Linux, write()(e chamadas de sistema similares) transferem no máximo 0x7ffff000(2.147.479.552) bytes, retornando o número de bytes realmente transferidos. (Isso ocorre nos sistemas de 32 e 64 bits.)

bobah
fonte