Warum belässt das Schreiben kontinuierlich 4 KByte im Puffer?

30

Ich habe im Wesentlichen den folgenden Code:

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

Es funktioniert, wenn die Größe 1 GB beträgt, aber wenn die Größe ~ 2 GB beträgt, bleiben konsistent 4 KByte übrig. Ich kann dies beheben, indem ich das Schreiben in eine Schleife einwickle und den Puffer nach oben verschiebe, aber ich bin gespannt, warum es immer fehlschlägt.

Wenn die Größe beispielsweise 2147483648 ist, werden beim Schreiben nur 2147479552 geschrieben, wobei 4096 ungeschrieben bleibt. Warum sollte dies passieren und ist es richtig, das Schreiben immer in eine Schleife zu packen?

Baumwasser
quelle
2
Führen Sie es im 32-Bit-Modus aus? 2gig ist die maximale 32-Bit-Zahl.
Barmar
2
Die Regeln für den gleichzeitigen Datenverbrauch writehängen von der Art der Datensenke ab file(z. B. "normale" Datei, Pipe, Stream-Socket, Datagramm-Socket usw.). Kannst du genauer sein?
zwol
7
Warten Sie, versuchen Sie writedie gesamte Datei auf einmal? Der übliche Ansatz besteht darin, die Daten jeweils in Puffergröße zu streamen, bis Sie alles schreiben.
Luaan
4
@Luaan Wenn Sie bereits alle Daten haben, sehe ich nicht, dass etwas falsch ist , wenn Sie alles auf einmal schreiben, aber wie diese Frage und Antwort zeigt, write()müssen Sie nicht alles schreiben (was auch für kleine Puffer gilt)
Pipe
8
"Ich kann dies beheben, indem ich Write in eine Schleife einbinde", und Sie müssen dies unabhängig von der SSIZE_MAXEinschränkung tun. Die write()Spezifikation besagt, dass es nicht verpflichtet ist, den vollständigen Puffer zu schreiben, auch wenn dies fast immer der Fall ist. Der schleifenlose Code in der Frage ist ein Fehler.
Adam

Antworten:

50

Die Antwort finden Sie in man 2 write:

Es ist kein Fehler, wenn diese Anzahl kleiner als die Anzahl der angeforderten Bytes ist. Dies kann beispielsweise passieren, weil das Festplattengerät gefüllt wurde.


Und aus der write()Manpage-Beschreibung:

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

Laut POSIX.1 countist SSIZE_MAXdas Ergebnis implementierungsdefiniert , wenn es größer als ist. Siehe NOTES für die Obergrenze unter Linux.

ANMERKUNGEN

Unter Linux write()(und ähnlichen Systemaufrufen) werden höchstens 0x7ffff000(2.147.479.552) Bytes übertragen, wobei die Anzahl der tatsächlich übertragenen Bytes zurückgegeben wird. (Dies gilt sowohl für 32-Bit- als auch für 64-Bit-Systeme.)

Bobah
quelle