Però una volta che si sia aperto lo stream (ma prima di aver compiuto operazioni su di esso) è possibile intervenire sulle modalità di buffering; la funzione che permette di controllare la bufferizzazione è setvbuf, il suo prototipo è:
Imposta la bufferizzazione dello stream stream nella modalità indicata da mode, usando buf come buffer di lunghezza size.
Restituisce zero in caso di successo, ed un valore qualunque in caso di errore, nel qual caso errno viene impostata opportunamente.
La funzione permette di controllare tutti gli aspetti della bufferizzazione; l'utente può specificare un buffer da usare al posto di quello allocato dal sistema passandone alla funzione l'indirizzo in buf e la dimensione in size.
Ovviamente se si usa un buffer specificato dall'utente questo deve essere stato allocato e rimanere disponibile per tutto il tempo in cui si opera sullo stream. In genere conviene allocarlo con malloc e disallocarlo dopo la chiusura del file; ma fintanto che il file è usato all'interno di una funzione, può anche essere usata una variabile automatica. In stdio.h è definita la macro BUFSIZ, che indica le dimensioni generiche del buffer di uno stream; queste vengono usate dalla funzione setbuf. Non è detto però che tale dimensione corrisponda sempre al valore ottimale (che può variare a seconda del dispositivo).
Dato che la procedura di allocazione manuale è macchinosa, comporta dei rischi (come delle scritture accidentali sul buffer) e non assicura la scelta delle dimensioni ottimali, è sempre meglio lasciare allocare il buffer alle funzioni di libreria, che sono in grado di farlo in maniera ottimale e trasparente all'utente (in quanto la disallocazione avviene automaticamente). Inoltre siccome alcune implementazioni usano parte del buffer per mantenere delle informazioni di controllo, non è detto che le dimensioni dello stesso coincidano con quelle su cui viene effettuato l'I/O.
|
|
Oltre a setvbuf le glibc definiscono altre tre funzioni per la gestione della bufferizzazione di uno stream: setbuf, setbuffer e setlinebuf; i loro prototipi sono:
Disabilita la bufferizzazione se buf è NULL, altrimenti usa buf come buffer di dimensione BUFSIZ in modalità fully buffered.
Disabilita la bufferizzazione se buf è NULL, altrimenti usa buf come buffer di dimensione size in modalità fully buffered.
Pone lo stream in modalità line buffered.
Restituisce un valore diverso da zero se stream è in modalità line buffered.
Restituisce le dimensioni del buffer di stream.
Come già accennato, indipendentemente dalla modalità di bufferizzazione scelta, si può forzare lo scarico dei dati sul file con la funzione fflush, il suo prototipo è:
Forza la scrittura di tutti i dati bufferizzati dello stream stream.
Restituisce zero in caso di successo, ed EOF in caso di errore, impostando errno a EBADF se stream non è aperto o non è aperto in scrittura, o ad uno degli errori di write.
Se stream è NULL lo scarico dei dati è forzato per tutti gli stream aperti. Esistono però circostanze, ad esempio quando si vuole essere sicuri che sia stato eseguito tutto l'output su terminale, in cui serve poter effettuare lo scarico dei dati solo per gli stream in modalità line buffered; per questo motivo le glibc supportano una estensione di Solaris, la funzione _flushlbf, il cui prototipo è:
Forza la scrittura di tutti i dati bufferizzati degli stream in modalità line buffered.
Si ricordi comunque che lo scarico dei dati dai buffer effettuato da queste funzioni non comporta la scrittura di questi su disco; se si vuole che il kernel dia effettivamente avvio alle operazioni di scrittura su disco occorre usare sync o fsync (si veda sez. 6.3.3).
Infine esistono anche circostanze in cui si vuole scartare tutto l'output pendente; per questo si può usare fpurge, il cui prototipo è:
Cancella i buffer di input e di output dello stream stream.
Restituisce zero in caso di successo, ed EOF in caso di errore.
La funzione scarta tutti i dati non ancora scritti (se il file è aperto in scrittura), e tutto l'input non ancora letto (se è aperto in lettura), compresi gli eventuali caratteri rimandati indietro con ungetc.