Completato I/O formattato, posizionamento, gestione del bufferingm
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 24 Dec 2001 23:52:14 +0000 (23:52 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 24 Dec 2001 23:52:14 +0000 (23:52 +0000)
thread e stream.

filestd.tex

index 2e9b05af38d47538260c57eb57836ead8850735e..6348a7daa0978b0a775ee32be414d44d5aea3943 100644 (file)
@@ -1,4 +1,4 @@
- \chapter{I file: l'interfaccia standard ANSI C}
+\chapter{I file: l'interfaccia standard ANSI C}
 \label{cha:files_std_interface}
 
 Esamineremo in questo capitolo l'interfaccia standard ANSI C per i file,
 \label{cha:files_std_interface}
 
 Esamineremo in questo capitolo l'interfaccia standard ANSI C per i file,
@@ -908,25 +908,24 @@ chiama \func{getdelim} ed il suo prototipo 
   carattere di newline come separatore di linea.
 \end{prototype}
 
   carattere di newline come separatore di linea.
 \end{prototype}
 
-Il comportamento di \func{getdelim} è identico a quello di
-\func{getline} (che può essere implementata da questa passando
-\verb|'\n'| come valore di \param{delim}).
+Il comportamento di \func{getdelim} è identico a quello di \func{getline} (che
+può essere implementata da questa passando \verb|'\n'| come valore di
+\param{delim}).
 
 
 
 
-\subsection{Input/output formattato}
+\subsection{L'input/output formattato}
 \label{sec:file_formatted_io}
 
 L'ultima modalità di input/output è quella formattata, che è una delle
 \label{sec:file_formatted_io}
 
 L'ultima modalità di input/output è quella formattata, che è una delle
-caratteristiche più utilizzate delle librerie standard del C; in genere
-questa è la modalità in cui si esegue normalmente l'output su terminale
-poichè permette di stampare in maniera facile e veloce dati, tabelle e
-messaggi.
+caratteristiche più utilizzate delle librerie standard del C; in genere questa
+è la modalità in cui si esegue normalmente l'output su terminale poiché
+permette di stampare in maniera facile e veloce dati, tabelle e messaggi.
 
 
-L'output formattato viene eseguito con una delle 13 funzioni della
-famiglia \func{printf}; le tre più usate sono le seguenti:
+L'output formattato viene eseguito con una delle 13 funzioni della famiglia
+\func{printf}; le tre più usate sono le seguenti:
 \begin{functions}
   \headdecl{stdio.h} 
 \begin{functions}
   \headdecl{stdio.h} 
-  \funcdecl{int printf(const char *format, ...)} Stampa su \var{stdout}
+  \funcdecl{int printf(const char *format, ...)} Stampa su \file{stdout}
   gli argomenti, secondo il formato specificato da \param{format}.
   
   \funcdecl{int fprintf(FILE *stream, const char *format, ...)}  Stampa
   gli argomenti, secondo il formato specificato da \param{format}.
   
   \funcdecl{int fprintf(FILE *stream, const char *format, ...)}  Stampa
@@ -1003,23 +1002,30 @@ degli specificatori di conversione (riportati in \ntab) che la conclude.
   \label{tab:file_format_spec}
 \end{table}
 
   \label{tab:file_format_spec}
 \end{table}
 
-
 Il formato di una direttiva di conversione prevede una serie di possibili
 Il formato di una direttiva di conversione prevede una serie di possibili
-elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione; in
+elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione. In
 generale essa è sempre del tipo:
 \begin{center}
 \begin{verbatim}
 % [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
 \end{verbatim}
 \end{center}
 generale essa è sempre del tipo:
 \begin{center}
 \begin{verbatim}
 % [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
 \end{verbatim}
 \end{center}
-in cui i valori opzionali sono indicati fra parentesi, e prevedono la
-presenza, in questo ordine, di: uno specificatore per il parametro da usare
-(terminato da un \cmd{\$}, uno o più flag (riassunti in
-\tabref{tab:file_format_flag}) che controllano il formato di stampa della
-conversione (riassunti in \tabref{tab:file_format_type}), uno specificatore di
-larghezza, eventualmente seguito (per i numeri in virgola mobile) da un
-specificatore di precisione, uno specificatore del tipo di dato (che ne indica
-la lunghezza).
+in cui tutti i valori tranne il \cmd{\%} e lo specificatatore di conversione
+sono opzionali (e per questo sono indicati fra parentesi quadre); si possono
+usare più elementi opzionali, nel qual caso devono essere specificati in
+questo ordine:
+\begin{itemize*}
+\item uno specificatore del parametro da usare (terminato da un \cmd{\$}),
+\item uno o più flag (i cui valori possibili sono riassunti in
+  \tabref{tab:file_format_flag}) che controllano il formato di stampa della
+  conversione
+\item uno specificatore di larghezza (un numero decimale), eventualmente
+  seguito (per i numeri in virgola mobile) da un specificatore di precisione
+  (un altro numero decimale),
+\item uno specificatore del tipo di dato, che ne indica la dimensione (i cui
+  valori possibili sono riassunti in \tabref{tab:file_format_type}).
+\end{itemize*}
+
 
 \begin{table}[htb]
   \centering
 
 \begin{table}[htb]
   \centering
@@ -1078,8 +1084,8 @@ di \func{printf} e nella documentazione delle \acr{glibc}.
 \end{table}
 
 Una versione alternativa delle funzioni di output formattato, che permettono
 \end{table}
 
 Una versione alternativa delle funzioni di output formattato, che permettono
-di usare il puntatore ad una lista di argomenti (vedi \secref{proc_variadic}),
-sono le seguenti:
+di usare il puntatore ad una lista di argomenti (vedi
+\secref{sec:proc_variadic}), sono le seguenti:
 \begin{functions}
   \headdecl{stdio.h} 
   
 \begin{functions}
   \headdecl{stdio.h} 
   
@@ -1113,11 +1119,99 @@ scritti sulla stringa di destinazione:
   Identica a \func{vsprintf}, ma non scrive su \param{str} più di
   \param{size} caratteri.
 \end{prototype}
   Identica a \func{vsprintf}, ma non scrive su \param{str} più di
   \param{size} caratteri.
 \end{prototype}
+\noindent in modo da evitare possibili buffer overflow.
+
+
+Per eliminare alla radice questi problemi, le \acr{glibc} supportano una
+estensione specifica GNU che alloca dinamicamente tutto lo spazio necessario;
+l'estensione si attiva al solito definendo \macro{\_GNU\_SOURCE}, le due
+funzioni sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+    
+  \funcdecl{int asprintf(char **strptr, const char *format, ...)}  Stampa gli
+  argomenti specificati secondo il formato specificato da \param{format} su
+  una stringa allocata automaticamente all'indirizzo \param{*strptr}.
+  
+  \funcdecl{int vasprintf(char **strptr, const char *format, va\_list ap)}
+  Stampa gli argomenti della lista \param{ap} secondo il formato specificato
+  da \param{format} su una stringa allocata automaticamente all'indirizzo
+  \param{*strptr}.
 
 
-Per evitare questi problemi con la stampa su stringhe di lunghezza
-insuffciente le \acr{glibc} supportano una estensione specifica GNU che alloca
-dinamicamente tutto lo spazio necessario; l'estensione si attiva al solito
-definendo \macro{\_GNU\_SOURCE}, 
+  \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
+\end{functions}
+Entrambe le funzioni prendono come parametro \param{strptr} che deve essere
+l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà
+restituito (si ricordi quanto detto in \secref{sec:proc_var_passing} a
+proposito dei \textit{value result argument}) l'indirizzo della stringa
+allogata automaticamente dalle funzioni. Occorre onoltre ricordarsi di
+invocare \func{free} per liberare detto puntatore quando la stringa non serve
+più, onde evitare memory leak.
+
+Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e
+\func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre
+estensioni permettono di scrivere con caratteri estesi. Anche queste funzioni,
+il cui nome è generato dalle precedenti funzioni aggiungendo una \func{w}
+davanti a \func{print}, sono trattate in dettaglio nella documentazione delle
+\acr{glibc}.
+
+In corrispondenza alla famiglia di funzioni \func{printf} che si usano per
+l'output formattato, l'input formattato viene eseguito con le funzioni della
+famiglia \func{scanf}; fra queste le tre più importanti sono:
+\begin{functions}
+  \headdecl{stdio.h} \funcdecl{int scanf(const char *format, ...)} Esegue una
+  scansione di \file{stdin} cercando una corrispondenza di quanto letto con il
+  formato dei dati specificato da \param{format}, ed effettua le relative
+  conversione memorizzando il risultato nei parametri seguenti.
+  
+  \funcdecl{int fscanf(FILE *stream, const char *format, ...)}  Analoga alla
+  precedente, ma effettua la scansione su \param{stream}.
+  
+  \funcdecl{int sscanf(char *str, const char *format, ...)} Analoga alle
+  precedenti, ma effettua la scansione dalla stringa \param{str}.
+  
+  \bodydesc{Le funzioni ritornano il numero di elementi assegnati. Questi
+    possono essere in numero inferiore a quelli specificati, ed anche zero.
+    Quest'ultimo valore significa che non si è trovata corrispondenza. In caso
+    di errore o fine del file viene invece restituito \macro{EOF}.}
+\end{functions}
+\noindent e come per le analoghe funzioni di scrittura esistono le relative
+\func{vscanf}, \func{vfscanf} \func{vsscanf} che usano un puntatore ad una
+lista di argomenti.
+
+Tutte le funzioni della famiglia delle \func{scanf} vogliono come argomenti i
+puntatori alle variabili che dovranno contenere le conversioni; questo è un
+primo elemento di disagio in quanto è molto facile dimenticarsi di questa
+caratteristica.
+
+Le funzioni leggono i caratteri dallo stream (o dalla stringa) di input ed
+eseguono un confronto con quanto indicato in \param{format}, la sintassi di
+questo parametro è simile a quella usata per l'analogo di \func{printf}, ma ci
+sono varie differenze.  Le funzioni di input infatti sono più orientate verso
+la lettura di testo libero che verso un input formattato in campi fissi. Uno
+spazio in \param{format} corrisponde con un numero qualunque di caratteri di
+separazione (che possono essere spazi, tabulatori, virgole etc.), mentre
+caratteri diversi richiedono una corrispondenza esatta. Le direttive di
+conversione sono analoghe a quelle di \func{printf} e si trovano descritte in
+dettaglio nelle man page e nel manuale delle \acr{glibc}.
+
+Le funzioni eseguono la lettura dall'input, scartano i separatori (e gli
+eventuali caratteri diversi indicati dalla stringa di formato) effettuando le
+conversioni richieste; in caso la corrispondenza fallisca (o la funzione non
+sia in grado di effettuare una delle conversioni richieste) la scansione viene
+interrotta immediatamente e la funzione ritorna lasciando posizionato lo
+stream al primo carattere che non corrisponde.
+
+Data la notevole complessità di uso di queste funzioni, che richiedono molta
+cura nella definizione delle corrette stringhe di formato e sono facilmente
+soggette ad errori, e considerato anche il fatto che è estremamente macchinoso
+recuperare in caso di fallimento nelle corrispondenze, l'input formattato non
+è molto usato. In genere infatti quando si ha a che fare con un input
+relativamente semplice si preferisce usare l'input di linea ed effetture
+scansione e conversione di quanto serve direttamente con una delle funzioni di
+conversione delle stringhe; se invece il formato è più complesso diventa più
+facile utilizzare uno strumento come il \cmd{flex} per generare un
+analizzatore lessicale o il \cmd{bison} per generare un parser.
 
 
 \subsection{Posizionamento su uno stream}
 
 
 \subsection{Posizionamento su uno stream}
@@ -1129,14 +1223,14 @@ punto prestabilito; questo fintanto che l'operazione di riposizionamento 
 supportata dal file sottostante lo stream, quando cioè si ha a che fare con
 quello che viene detto un file ad \textsl{accesso casuale}.
 
 supportata dal file sottostante lo stream, quando cioè si ha a che fare con
 quello che viene detto un file ad \textsl{accesso casuale}.
 
-In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel
-file è espressa da un intero positivo, rappresentato dal tipo
-\type{off\_t}, il problema è alcune delle funzioni usate per il
-riposizionamento sugli stream originano dalle prime versioni di unix in
-cui questo tipo non era ancora stato definito, e che in altri sistemi
-non è detto che la posizione su un file venga sempre rappresentata con
-un numero di caratteri (ad esempio in VMS può essere rappresentata come
-numero di record, e offset rispetto al record corrente).
+In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel file è
+espressa da un intero positivo, rappresentato dal tipo \type{off\_t}, il
+problema è alcune delle funzioni usate per il riposizionamento sugli stream
+originano dalle prime versioni di Unix, in cui questo tipo non era ancora
+stato definito, e che in altri sistemi non è detto che la posizione su un file
+venga sempre rappresentata con il numero di caratteri dall'inizio (ad esempio
+in VMS può essere rappresentata come numero di record, e offset rispetto al
+record corrente).
 
 Tutto questo comporta la presenza di diverse funzioni che eseguono
 sostanzialmente le stesse operazioni, ma usano parametri di tipo
 
 Tutto questo comporta la presenza di diverse funzioni che eseguono
 sostanzialmente le stesse operazioni, ma usano parametri di tipo
@@ -1153,32 +1247,58 @@ posizione in uno stream sono:
   all'inizio del file.
 \end{functions}
 
   all'inizio del file.
 \end{functions}
 
-L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i
-file descriptor, ed i parametri, a parte il tipo, hanno lo stesso
-significato; in particolare \param{whence} assume gli stessi valori già
-visti in \secref{sec:file_lseek}. La funzione restituisce 0 in caso di
-successo e -1 in caso di errore. 
+L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i file
+descriptor, ed i parametri, a parte il tipo, hanno lo stesso significato; in
+particolare \param{whence} assume gli stessi valori già visti in
+\secref{sec:file_lseek}.  La funzione restituisce 0 in caso di successo e -1
+in caso di errore.  La funzione \func{rewind} riporta semplicemente la
+posizione corrente all'inzio dello stream, ma non esattamente equivalente ad
+una \func{fseek(stream, 0L, SEEK\_SET)} in quanto vengono cancellati anche i
+flag di errore e fine del file.
 
 
-Per leggere la posizione corrente si usa invece la funzione \func{ftell}, il
+Per ottenere la posizione corrente si usa invece la funzione \func{ftell}, il
 cui prototipo è:
 \begin{prototype}{stdio.h}{long ftell(FILE *stream)} 
 cui prototipo è:
 \begin{prototype}{stdio.h}{long ftell(FILE *stream)} 
-  Legge la posizione attuale nello stream.
+  Legge la posizione attuale nello stream \param{stream}.
   
   \bodydesc{La funzione restituisce la posizione corrente, o -1 in caso
     di fallimento, che può esser dovuto sia al fatto che il file non
     supporta il riposizionamento che al fatto che la posizione non può
     essere espressa con un \type{long int}}
 \end{prototype}
   
   \bodydesc{La funzione restituisce la posizione corrente, o -1 in caso
     di fallimento, che può esser dovuto sia al fatto che il file non
     supporta il riposizionamento che al fatto che la posizione non può
     essere espressa con un \type{long int}}
 \end{prototype}
-
+\noindent la funzione restituisce la posizione come numero di byte
+dall'inizio dello stream. 
+
+Queste funzioni esprimono tutte la posizione nel file come un \func{long int},
+dato che (ad esempio quando si usa un filesystem indicizzato a 64 bit) questo
+può non essere possibile lo standard POSIX ha introdotto le nuove funzioni
+\func{fgetpos} e \func{fsetpos}, che invece usano il nuovo tipo
+\type{fpos\_t}, ed i cui prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int fsetpos(FILE *stream, fpos\_t *pos)} Setta la posizione
+  corrente nello stream \param{stream} al valore specificato da \func{pos}.
   
   
+  \funcdecl{int fgetpos(FILE *stream, fpos\_t *pos)} Scrive la posizione
+  corrente nello stream \param{stream} in \func{pos}.
+  
+  \bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di
+    errore.}
+\end{functions}
+
+In Linux, a partire dalle glibc 2.1, sono presenti anche le funzioni
+\func{fseeko} e \func{ftello}, assolutamente identiche alle precedenti ma con
+argomenti di tipo \type{off\_t} anziché di tipo \type{long int}.
+
 
 
 \section{Funzioni avanzate}
 \label{sec:file_stream_adv_func}
 
 
 
 \section{Funzioni avanzate}
 \label{sec:file_stream_adv_func}
 
-In questa sezione esamineremo le funzioni che permettono di controllare
-alcune caratteristiche più particolari degli stream, come la lettura
-degli attributi, le modalità di bufferizzazione, etc.
+In questa sezione esamineremo alcune funzioni avanzate che permettono di
+eseguire operazioni particolari sugli stream, come leggerne gli attributi,
+controllarne le modalità di bufferizzazione, ecc.
 
 
 \subsection{Le funzioni di controllo}
 
 
 \subsection{Le funzioni di controllo}
@@ -1198,7 +1318,7 @@ stream; questo pu
 \func{\_\_fwritable} i cui prototipi sono:
 \begin{functions}
   \headdecl{stdio\_ext.h}
 \func{\_\_fwritable} i cui prototipi sono:
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freadable (FILE *stream)}
+  \funcdecl{int \_\_freadable(FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} consente la lettura.
 
   \funcdecl{int \_\_fwritable(FILE *stream)}  
   Restituisce un valore diverso da zero se \param{stream} consente la lettura.
 
   \funcdecl{int \_\_fwritable(FILE *stream)}  
@@ -1210,7 +1330,7 @@ Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting} servono ad un
 uso ancora più specialistico, il loro prototipo è: 
 \begin{functions}
   \headdecl{stdio\_ext.h}
 uso ancora più specialistico, il loro prototipo è: 
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freading (FILE *stream)}
+  \funcdecl{int \_\_freading(FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   lettura o se l'ultima operazione è stata di lettura.
 
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   lettura o se l'ultima operazione è stata di lettura.
 
@@ -1235,8 +1355,99 @@ del buffer e del suo contenuto.
 \label{sec:file_buffering_ctrl}
 
 Come accennato in \secref{sec:file_buffering} le librerie definiscono una
 \label{sec:file_buffering_ctrl}
 
 Come accennato in \secref{sec:file_buffering} le librerie definiscono una
-serie di funzioni che permettono di controllare il comportamento degli
-stream; se non si è 
+serie di funzioni che permettono di controllare il comportamento degli stream;
+se non si è specificato nulla la modalità di buffering viene decisa
+autonomamente sulla base del tipo di file sottostante, ed i buffer vengono
+allocati automaticamente.
+
+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 è \func{setvbuf}, il
+suo prototipo è:
+\begin{prototype}{stdio.h}{int setvbuf(FILE *stream, char *buf, int mode, 
+    size\_t size)}
+  
+  Setta la bufferizzazione dello stream \func{stream} nella modalità indicata
+  da \param{mode}, usando \func{buf} come buffer di lunghezza \param{size}.
+  
+  \bodydesc{Restituisce zero in caso di successo, ed un valore qualunque in
+    caso di errore.}
+\end{prototype}
+
+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 \param{buf} e la dimensione in
+\func{size}. 
+
+Ovviamente se si usa un buffer specificato dall'utente questo deve essere
+stato allocato e restare disponibile per tutto il tempo in cui si opera sullo
+stream. In genere conviene allocarlo con \func{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 genere è
+definita una macro \macro{BUFSIZ} che indica le dimensioni ottimali del
+buffer. Dato che la procedura è macchinosa e comporta dei rischi (come delle
+scritture accidentali sul buffer) è sempre meglio lasciare allocare il buffer
+alle funzioni di librerie, che sono in grado di farlo in maniera ottimale e
+trasparente all'utente.
+
+Per evitare il settaggio del buffer basta passare un valore \macro{NULL} per
+\param{buf} e la funzione ignorerà il parametro \param{size} usando il buffer
+allocato automaticamente dal sistema.  In questo modo si potrà comunque
+modificare la modalità di bufferizzazione, passando in \param{mode} uno degli
+opportuni valori elencati in \ntab; qualora si specifiche la modalità non
+bufferizzata i valori di \param{buf} e \param{size} vengono ignorati.
+
+\begin{table}[htb]
+  \centering
+    \begin{tabular}[c]{|l|l|}
+      \hline
+      \textbf{Valore} & \textbf{Modalità} \\
+      \hline
+      \hline
+      \macro{\_IONBF} & \textit{unbuffered}\\
+      \macro{\_IOLBF} & \textit{line buffered}\\
+      \macro{\_IOFBF} & \textit{fully buffered}\\
+      \hline
+    \end{tabular}
+  \label{tab:file_stream_buf_mode}
+  \caption{Valori possibili per il parametro \param{mode} di \func{setvbuf} 
+    nel settaggio delle modalità di bufferizzazione.}
+\end{table}
+
+Oltre a \func{setvbuf} le \acr{glibc} definiscono altre tre funzioni per la
+gestione della bufferizzazione di uno stream: \func{setbuf}, \func{setbuffer}
+e \func{setlinebuf}, i loro prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{void setbuf(FILE *stream, char *buf)} Disabilita la
+  bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \func{buf}
+  come buffer di dimensione \macro{BUFSIZ} in modalità \textit{fully buffered}.
+  
+  \funcdecl{void setbuffer(FILE *stream, char *buf, size\_t size)} Disabilita
+  la bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \func{buf}
+  come buffer di dimensione \param{size} in modalità \textit{fully buffered}.
+  
+  \funcdecl{void setlinebuf(FILE *stream)} Pone lo stream in modalità
+  \textit{line buffered}.
+\end{functions}
+\noindent tutte queste funzioni sono realizzate con opportune chiamate a
+\func{setvbuf} e sono definite solo per compatibilità con le vecchie librerie
+BSD.
+
+Sempre seguendo Solaris le \acr{glibc} provvedono alcune estensioni non
+standard che permettono di leggere le proprietà di bufferizzazione di uno
+stream; dette funzioni sono:
+\begin{functions}
+  \headdecl{stdio\_ext.h} 
+  
+  \funcdecl{int \_\_flbf(FILE *stream)} Restituisce un valore diverso da zero
+  se \param{stream} è in modalità \textit{line buffered}.
+  
+  \funcdecl{size\_t \_\_fbufsize(FILE *stream)} Restituisce le dimensioni del
+  buffer di \param{stream}.
+\end{functions}
+
 
 
 \subsection{Gli stream e i thread}
 
 
 \subsection{Gli stream e i thread}
@@ -1248,8 +1459,19 @@ consapevoli delle possibili complicazioni anche quando non si usano i
 thread, dato che l'implementazione delle librerie è influenzata
 pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
 
 thread, dato che l'implementazione delle librerie è influenzata
 pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
 
-
-
+Lo standard POSIX richiede che le operazioni sui file siano atomiche rispetto
+ai thread, per questo le operazioni sui buffer effettuate dalle funzioni di
+libreria durante la lettura e la scrittura di uno stream devono essere
+opportunamente protette (in quanto il sistema assicura l'atomicità solo per le
+system call). Questo viene fatto associando ad ogni stream un opportuno blocco
+che deve essere implicitamente acquisito prima dell'esecuzione di qualunque
+operazione.
+
+Ci sono comunque situazioni in cui questo non basta, come quando un thread
+necessita di compiere più di una operazione sullo stream atomicamente, per
+questo motivo le librerie provvedono anche delle funzioni che permettono la
+gestione esplicita dei blocchi sugli stream; queste funzioni sono disponibili
+definendo \macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro prototipi sono:
 \begin{functions}
   \headdecl{stdio.h}
   
 \begin{functions}
   \headdecl{stdio.h}
   
@@ -1265,16 +1487,50 @@ pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
   \funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
   stream \param{stream}.
 \end{functions}
   \funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
   stream \param{stream}.
 \end{functions}
-
-
-\subsection{Dettagli dell'implementazione}
-\label{sec:file_stream_details}
+\noindent con queste funzioni diventa possibile acquisire un blocco ed
+eseguire tutte le operazioni volute, per poi rilasciarlo. 
+
+Ma vista la complessità delle strutture di dati coinvolte, le operazioni di
+blocco non sono del tutto indolori, e quando il locking dello stream non è
+necessario (come in tutti i programmi che non usano i thread), tutta la
+procedura può comportare dei pesanti costi in termini di prestazioni. Per
+questo motivo abbiamo visto in come per tutte le funzioni di I/O non
+formattato esistano delle versioni \func{\_unlocked} (alcune previste dallo
+standard POSIX stesso, altre aggiunte come estenzioni dalle \acr{glibc}) che
+possono essere usate in tutti questi casi\footnote{in certi casi dette
+  funzioni possono essere usate, visto che sono molto più efficiente, anche in
+  caso di necessità di locking, una volta che questo sia stato acquisito
+  manualmente.} dato che in molti casi (come per esempio \func{getc} e
+\func{putc}) queste versioni possono essere realizzate come macro, e sono
+pertanto in grado di garantire prestazione enormemente più elevate.
+
+La sostituizione di tutte le funzioni di I/O con le relative versioni
+\func{\_unlocked} in un programma che non usa i thread è però un lavoro
+abbastanza noioso, e che appesantisce il codice; per questo motivo le
+\acr{glibc} provvedono un'altra via per poter utilizzare disabilitare il
+locking, anch'essa mutuata da estensioni introdotte in Solaris, cioè l'uso
+della funzione \func{\_\_fsetlocking}, il cui prototipo è:
+\begin{prototype}{stdio\_ext.h}{int \_\_fsetlocking (FILE *stream, int type)}
+  Specifica o richiede a seconda del valore di \param{type} la modalità in cui
+  le operazioni di I/O su \param{stream} vengono effettuate rispetto
+  all'acquisizione implicita del blocco sullo stream.
+
+  \bodydesc{Restituisce lo stato di locking interno dello stream con uno dei
+  valori \macro{FSETLOCKING\_INTERNAL} o \macro{FSETLOCKING\_BYCALLER}.}
+\end{prototype}
+\noindent ed i valori possibili per \param{type} sono i seguenti:
+\begin{basedescript}{\desclabelwidth{4.0cm}}
+\item[\macro{FSETLOCKING\_INTERNAL}] Lo stream userà da ora in poi il blocco
+  implicito di default.
+\item[\macro{FSETLOCKING\_BYCALLER}] Al ritorno della funzione sarà l'utente a
+  dover gestire da solo il locking dello stream.
+\item[\macro{FSETLOCKING\_QUERY}] Restituisce lo stato corrente della modalità
+  di blocco dello stream.
+\end{basedescript}
 
 
 \subsection{File temporanei}
 \label{sec:file_temp_file}
 
 
 
 \subsection{File temporanei}
 \label{sec:file_temp_file}
 
-
-\subsection{Efficienza}
-\label{sec:file_stream_efficiency}
-
+Un'altra serie di funzioni definite dalle librerie standard del C sono quelle
+che riguardano la creazione di file temporanei.