2015-04-18 13 views
17

La firma della funzione per write(2) è ssize_t write(int fd, const void *buf, size_t count). Generalmente, il valore massimo di size_t è maggiore di quello di ssize_t. Significa che la quantità di dati che write può effettivamente scrivere è in realtà SSIZE_MAX anziché SIZE_MAX? In caso contrario, cosa succede quando il numero di byte scritti è maggiore di SSIZE_MAX rispetto agli overflow?Scriverà (2) scrive sempre meno o uguale a SSIZE_MAX?

Mi sto essenzialmente chiedendo se la quantità di dati scritti da write è limitata da SSIZE_MAX o SIZE_MAX.

+0

I processi presentano anche dei limiti. Un processo che supera il 'limite di dimensione del file del processo 'non andrà a buon fine (errore' EFBIG'), quindi quel limite potrebbe essere yeyo

+0

SSIZE_T sta per Signed Size e quindi significa che è un numero firmato. Questo è il caso in cui si è verificato un errore durante la chiamata di sistema di scrittura. Quindi il numero massimo di scritture non può essere più grande firmato Dimensioni_t – madz

+0

pendrive, lo so tanto. Questo non affronta la mia domanda affatto. Il valore restituito è 'ssize_t' che ha un intervallo più limitato rispetto a' size_t' sulla maggior parte dei sistemi, quindi in sostanza sto chiedendo se le scritture sono limitate da 'SSIZE_MAX' o' SIZE_MAX'. –

risposta

15

Il tipo ssize_t è definito da POSIX come un tipo firmato per essere in grado di memorizzare almeno 32767 (_POSIX_SSIZE_MAX) senza altre garanzie. Quindi il suo valore massimo può essere inferiore al valore massimo di size_t.

ssize_t 's definizione POSIX:

ssize_t 

Utilizzato per un conteggio di byte o di un'indicazione di errore.

Quindi è possibile che il numero di byte richiesto per essere scritto possa essere maggiore di quello che ssize_t può contenere. In tal caso, POSIX lo lascia all'implementazione.

Da POSIX spec write() s':

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

Se il valore di nbyte è maggiore di {} SSIZE_MAX, il risultato è definito dall'implementazione.

+0

Conosco un po 'il suo vagabondaggio, ma se viene usato '-ansi', allora' SSIZE_MAX' e '_POSIX_SSIZE_MAX' potrebbero non essere definiti sui sistemi GNU. Vedi anche [SSIZE_MAX su ia64] (https://sourceware.org/ml/libc-hacker/2002-08/msg00031.html). La discussione si espanse rapidamente per includere tutti i sistemi glibc. – jww

+0

Linux sembra restituire 'EINVAL' se' nbyte> SSIZE_MAX + 1'. (Accetta 'SSIZE_MAX + 1', restituendo' 0') È spiacevole che questo non sia stato semplicemente gestito nello standard imponendo una scrittura parziale di al massimo 'SSIZE_MAX' byte. – PSkocik

2

Sì, la quantità di dati che è possibile scrivere in una singola chiamata da scrivere è limitata a ciò che può essere contenuto in un ssize_t. Per chiarimenti, vedi the relevant glibc documentation page. Per citare quella pagina, "Il tuo programma dovrebbe sempre chiamare scrivere in un ciclo, iterando fino a quando tutti i dati sono scritti." (enfasi aggiunta) Quella pagina chiarisce anche che ssize_t è usato per rappresentare la dimensione dei blocchi che possono essere letti o scritti in una singola operazione.

+0

Sapete se è menzionato da qualche parte nelle specifiche POSIX che la quantità di dati scritti da 'write' è limitata da' ssize_t' invece di 'size_t'? –

+0

Non ne sono sicuro, non ho familiarità con le specifiche POSIX. –

+4

In realtà, la risposta è che il comportamento è definito dall'implementazione: [la pagina su scrittura] (http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html) dice che "Se il valore di nbyte è maggiore di {SSIZE_MAX}, il risultato è definito dall'implementazione. " Questo mi sembra sciocco: perché non definire semplicemente scrivere per fare qualcosa di ragionevole: cioè scrivere solo ciò che può essere fatto in sicurezza? –

13

Le specifiche POSIX per write() dice:

Se il valore di nbyte è maggiore di {} SSIZE_MAX, il risultato è definito dall'implementazione.

Quindi, qualsiasi tentativo di scrivere più di SSIZE_MAX byte porta a comportamenti che non viene comandato dal POSIX, ma che deve essere documentato dal sistema (è definito dall'implementazione, non indefinito, comportamento). Tuttavia, diversi sistemi possono gestirlo in modo diverso, e non c'è nulla che impedisca a un sistema di riportare un errore (forse EINVAL impostato su SSIZE_MAX e scrivere a SSIZE_MAX byte e segnalarlo, lasciandolo all'applicazione per riprovare sul resto e altro i sistemi potrebbero essere inventivi e fare le cose in modo diverso ancora.

Se si dispone di un sistema a 64 bit, lo SSIZE_MAX è probabilmente più grande della quantità di spazio su disco nel singolo centro dati più grande del mondo (possibilmente di un ordine di grandezza o più, consentendo anche l'NSA e Google), quindi è improbabile che tu possa imbatterti in problemi reali con questo, ma su sistemi a 32 bit, potresti facilmente avere più di 2 GB di spazio e se ssize_t è a 32 bit, devi occuparti di tutti Questo. (In Mac OS X 10.10.3, una build a 32 bit ha un valore di 4 byte size_t e ssize_t, almeno per impostazione predefinita.)

+0

* maggiore della quantità di spazio su disco nel mondo (di pochi ordini di grandezza) *. Affatto! È il contrario: bastano 20 milioni di dischi rigidi da 500 GB per superare i 2^63 byte. – chqrlie

+0

@chqrlie '9223372036854775808' byte in gibibyte =' 8589934592'. Dividere tale importo per 500 (500 dischi rigidi). '17 179 869.184' 500 dischi rigidi GiB. Anche se hai ragione, il mondo mio ha più spazio sul disco. – yeyo

+0

@chqrlie: Hmmm ... sei abbastanza vicino da aver ridotto la richiesta. E chiunque cerchi di copiare tanti dati potrebbe avere problemi con "da dove viene letto e scritto" e "è possibile leggere e scrivere tutti quei dati contemporaneamente" - e la risposta sarebbe "no, tu sei non è permesso scrivere tutti quei dati contemporaneamente ". –