2015-04-18 4 views
17

Die Funktionssignatur für write(2) ist ssize_t write(int fd, const void *buf, size_t count). Im Allgemeinen ist der Maximalwert von size_t größer als der von ssize_t. Bedeutet dies, dass die Datenmenge, die write tatsächlich schreiben kann, tatsächlich SSIZE_MAX statt SIZE_MAX ist? Wenn das nicht der Fall ist, was passiert, wenn die Anzahl der geschriebenen Bytes größer als SSIZE_MAX in Bezug auf Überläufe ist?Wird write (2) immer kleiner oder gleich SSIZE_MAX schreiben?

Ich wundere mich im Wesentlichen, ob diese Datenmenge von write durch SSIZE_MAX oder SIZE_MAX begrenzt geschrieben wird.

+0

Prozesse haben auch Grenzen. Ein Prozess, der die Dateigrößenbeschränkung des Prozesses überschreitet, wird fehlschlagen (Fehler "EFBIG"), daher kann dieses Limit yeyo

+0

SSIZE_T steht für Signed Size und bedeutet somit eine signierte Nummer. Dies ist der Fall, wenn während des Systemaufrufs ein Fehler aufgetreten ist. Also die maximale Anzahl der Schreibvorgänge kann nicht größer signiert werden Size_t – madz

+0

Pendrive, ich weiß so viel. Das geht meine Frage überhaupt nicht an. Der Rückgabewert ist 'ssize_t', der auf den meisten Systemen einen begrenzteren Bereich als' size_t' hat, also frage ich im Wesentlichen, ob die Schreiboperationen durch 'SSIZE_MAX' oder' SIZE_MAX' begrenzt sind. –

Antwort

15

Der Typ ssize_t wird von POSIX als signierter Typ definiert, der ohne weitere Garantien mindestens 32767 (_POSIX_SSIZE_MAX) speichern kann. Daher kann der Maximalwert kleiner als der Maximalwert size_t sein.

ssize_t ‚s POSIX Definition:

ssize_t 

Verwendet für eine Anzahl von Bytes oder einer Fehleranzeige.

So ist es möglich, dass die Anzahl der Bytes, die Sie geschrieben haben, größer sein kann als was ssize_t halten kann. In diesem Fall überlässt POSIX es der Implementierung.

Von write() ‚s POSIX-Spezifikation:

ssize_t write(int fildes, const void *buf, size_t nbyte); 

Wenn der Wert von nbyte größer als {SSIZE_MAX}, das Ergebnis ist die Implementierung definiert.

+0

Ich weiß, dass es ein bisschen wanderte, aber wenn '-ansi' verwendet wird, dann sind' SSIZE_MAX' und '_POSIX_SIZE_MAX' möglicherweise nicht auf GNU-Systemen definiert. Siehe auch [SSIZE_MAX auf ia64] (https://sourceware.org/ml/libc-hacker/2002-08/msg00031.html). Die Diskussion wurde schnell um alle glibc-Systeme erweitert. – jww

+0

Linux scheint 'EINVAL' zurückzugeben, wenn' nbyte> SSIZE_MAX + 1'. (Es akzeptiert 'SSIZE_MAX + 1' und gibt '0' zurück) Es ist bedauerlich, dass dies nicht einfach im Standard gehandhabt wurde, indem ein partielles Schreiben von höchstens 'SSIZE_MAX'-Bytes vorgeschrieben wurde. – PSkocik

2

Ja, die Datenmenge, die in einen einzelnen Schreibaufruf geschrieben werden kann, ist auf das beschränkt, was in einem ssize_t gespeichert werden kann. Zur Verdeutlichung siehe the relevant glibc documentation page. Um diese Seite zu zitieren, "Ihr Programm sollte immer Aufruf schreiben in einer Schleife, Iterieren, bis alle Daten geschrieben werden." (Hervorhebung hinzugefügt) Diese Seite stellt auch klar, dass ssize_t verwendet wird, um die Größe von Blöcken darzustellen, die in einer einzigen Operation gelesen oder geschrieben werden können.

+0

Wissen Sie, ob irgendwo in der POSIX-Spezifikation erwähnt wird, dass die Menge der Daten, die von 'write' geschrieben werden, durch' ssize_t' statt durch 'size_t' begrenzt ist? –

+0

Ich bin mir nicht sicher, ich bin nicht vertraut mit der POSIX-Spezifikation. –

+4

Eigentlich denke ich, die Antwort ist, dass das Verhalten implementation-defined ist: [die Seite beim Schreiben] (http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html) sagt, dass "Wenn der Wert von nbyte ist größer als {SSIZE_MAX}, das Ergebnis ist implementierungsdefiniert. " Das erscheint mir albern: Warum nicht einfach schreiben, um etwas Vernünftiges zu tun: d. H. Nur schreiben, was sicher gemacht werden kann? –

13

Die POSIX-Spezifikation für write() sagt:

Wenn der Wert von nbyte größer als {SSIZE_MAX}, das Ergebnis Implementierung definiert ist.

Also jeder Versuch, mehr als SSIZE_MAX Bytes zu schreiben, um Verhalten führt, die nicht von POSIX vorgeschrieben ist, aber das muss vom System dokumentiert werden (es ist die Implementierung definiert, nicht undefiniert, Verhalten). Verschiedene Systeme können jedoch anders damit umgehen, und es gibt nichts zu stoppen ein System einen Fehler melden (vielleicht auf EINVAL gesetzt) ​​und eine andere schreiben SSIZE_MAX Bytes und Berichterstattung, so dass es an die Anwendung erneut auf den Rest versuchen, und andere Systeme könnten erfinderisch sein und die Dinge noch anders machen.

Wenn Sie ein 64-Bit-System haben, ist SSIZE_MAX wahrscheinlich größer als die Menge an Speicherplatz im größten einzelnen Datenzentrum der Welt (möglicherweise um eine Größenordnung oder mehr, sogar unter Berücksichtigung der NSA und Google), so dass Sie wahrscheinlich keine echten Probleme damit haben werden, aber auf 32-Bit-Systemen könnten Sie leicht mehr als 2 GiB Speicherplatz haben und wenn ssize_t 32-Bit ist, müssen Sie mit allen umgehen Dies. (Unter Mac OS X 10.10.3 hat ein 32-Bit-Build mindestens standardmäßig 4 Byte size_t und ssize_t.)

+0

* größer als die Menge an Speicherplatz in der Welt (um ein paar Größenordnungen) *. Ganz und gar nicht! Es ist umgekehrt: Es braucht nur 20 Millionen 500-GB-Festplatten, um 2^63 Bytes zu überschreiten. – chqrlie

+0

@chqrlie '9223372036854775808' Bytes in Gibibyte =' 8589934592'. Teilen Sie diesen Betrag auf 500 (500 Festplatten). '17 179 869.184' 500 GiB Festplatten. Obwohl du recht hast, habe ich mehr Speicherplatz auf der Welt. – yeyo

+0

@chqrlie: Hmmm..Sie sind nah genug, dass ich den Anspruch reduziert habe. Und jeder, der versucht, so viele Daten zu kopieren, hätte Probleme mit "wo wird gelesen und geschrieben?" Und "darf man so viele Daten gleichzeitig lesen und schreiben" - und die Antwort wäre: Nein, das bist du _not_ darf nicht so viele Daten gleichzeitig schreiben '. –