2009-09-20 7 views
56

Ho appreso che, per impostazione predefinita, I/O nei programmi è memorizzato nel buffer, cioè sono serviti da una memoria temporanea al programma richiedente. Capisco che il buffering migliori le prestazioni dell'IO (magari riducendo le chiamate di sistema). Ho visto esempi di disabilitazione del buffering, come setvbuf in C. Qual è la differenza tra le due modalità e quando si dovrebbe essere utilizzate l'una sull'altra?IO bufferizzato vs non bufferizzato

risposta

90

Si desidera l'output senza buffer ogni volta che si desidera assicurarsi che l'output sia stato scritto prima di continuare. Un esempio è l'errore standard in una libreria di runtime C, che di solito è unbuffered per impostazione predefinita. Dal momento che gli errori sono (si spera) poco frequenti, vorresti conoscerli immediatamente. D'altra parte, l'output standard è memorizzato nel buffer semplicemente perché si presuppone che ci saranno molti più dati che lo attraversano.

Un altro esempio è una libreria di registrazione. Se i tuoi messaggi di log sono conservati all'interno dei buffer nel tuo processo, e il tuo processo non esegue il dump di core, ci sono ottime probabilità che l'output non venga mai scritto.

Inoltre, non sono solo le chiamate di sistema ridotte al minimo ma anche l'I/O del disco. Diciamo che un programma legge un file un byte alla volta. Con l'ingresso senza buffer, andrai al disco (relativamente molto lento) per ogni byte, anche se probabilmente dovrà comunque leggere in un blocco intero (l'hardware del disco stesso potrebbe avere dei buffer ma tu stai ancora andando al controller del disco che sarà più lento dell'accesso in memoria).

Con il buffering, l'intero blocco viene letto nel buffer in una volta, quindi i singoli byte vengono consegnati dall'area del buffer (in memoria, incredibilmente veloce).

Tieni presente che il buffer può assumere molte forme, come nel seguente esempio:

+-------------------+-------------------+ 
| Process A   | Process B   | 
+-------------------+-------------------+ 
| C runtime library | C runtime library | C RTL buffers 
+-------------------+-------------------+ 
|    OS caches    | Operating system buffers 
+---------------------------------------+ 
|  Disk controller hardware cache | Disk hardware buffers 
+---------------------------------------+ 
|     Disk    | 
+---------------------------------------+ 
21

Volete uscita senza buffer quando si dispone già di un'ampia sequenza di byte pronti a scrivere su disco, e vogliono evitare una copia aggiuntiva in un secondo buffer nel mezzo.

I flussi di output bufferizzati accumulano i risultati di scrittura in un buffer intermedio, inviandolo al file system del sistema operativo solo quando è stato accumulato un numero sufficiente di dati (o è richiesto flush()). Questo riduce il numero di chiamate al file system. Poiché le chiamate al sistema di file possono essere costose sulla maggior parte delle piattaforme (rispetto alla memcpy breve), l'output bufferizzato è un guadagno netto quando si esegue un numero elevato di scritture di piccole dimensioni. L'output non bufferizzato è generalmente migliore quando si hanno già buffer di grandi dimensioni da inviare: la copia su un buffer intermedio non ridurrà ulteriormente il numero di chiamate del sistema operativo e introdurrà ulteriore lavoro.

L'uscita non bufferata ha nulla da fare per garantire che i dati raggiungano il disco; tale funzionalità è fornita da flush() e funziona su entrambi i flussi bufferizzati e non bufferizzati. Le scritture di IO non bufferate non garantiscono che i dati abbiano raggiunto il disco fisico: il file system del sistema operativo è libero di conservare una copia dei dati per un tempo indefinito, senza mai scriverlo sul disco, se lo desidera. È richiesto solo il commit su disco quando si richiama flush(). (Nota che close() chiamerà flush() a tuo nome).

+0

Chiamando 'flush()' garantisce che sia scritto sul disco? Pensavo che lo avessi passato solo al buffer del disco. – jrdioko

+2

È necessario 'O_SYNC' per garantire le scritture. – moshbear