Perché la scrittura lascia continuamente 4K byte nel buffer?


30

Ho essenzialmente il seguente codice:

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

Funziona se la dimensione è di 1 GB, ma quando la dimensione è di ~ 2 GB, vengono lasciati costantemente 4K byte. Posso risolvere questo problema avvolgendo la scrittura in un ciclo e spostando il buffer verso l'alto, ma sono curioso di sapere perché fallisce sempre.

Ad esempio, se la dimensione è 2147483648, scrivi scrive solo 2147479552, lasciando 4096 non scritto. Perché dovrebbe succedere ed è corretto avvolgere sempre la scrittura in un ciclo?


2
Lo stai eseguendo in modalità a 32 bit? 2gig è il numero massimo di 32 bit.
Barmar il

2
Le regole per quanti dati writeconsumeranno contemporaneamente dipendono dal tipo di sink di dati file(ad es. File "normale", pipe, stream stream, datagram socket, ...). Può essere più preciso?
zwol,

7
Aspetta, stai provando writetutto il file in una volta? L'approccio usuale è quello di eseguire lo streaming dei dati di dimensioni buffer alla volta fino a quando non si scrive tutto.
Luaan,

4
@Luaan Se hai già tutti i dati non vedo che c'è qualcosa di sbagliato a scriverli tutti in una volta ma come dimostra questa domanda e risposta, write()non è necessario scriverli tutti (che vale anche per piccoli buffer)
pipe

8
"Posso risolvere il problema avvolgendo la scrittura in un ciclo" e devi farlo, indipendentemente dalla SSIZE_MAXrestrizione. Le write()specifiche dicono che non è obbligatorio scrivere l'intero buffer, anche se quasi sempre. Il codice senza loop nella domanda è un bug.
Adam,

Risposte:


50

Puoi trovare la risposta in man 2 write:

Non è un errore se questo numero è inferiore al numero di byte richiesti; questo può accadere ad esempio perché il dispositivo disco è stato riempito.


E dalla write()descrizione della pagina man:

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

Secondo POSIX.1, se countè maggiore di SSIZE_MAX, il risultato è definito dall'implementazione; vedi NOTE per il limite superiore su Linux.

APPUNTI

Su Linux, write()(e simili chiamate di sistema) verranno trasferiti al massimo 0x7ffff000(2.147.479.552) byte, restituendo il numero di byte effettivamente trasferiti. (Questo è vero su entrambi i sistemi a 32 e 64 bit.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.