\label{cha:files_std_interface}
Esamineremo in questo capitolo l'interfaccia standard ANSI C per i file,
-quella che viene comunemente detta interfaccia degli \textit{stream}. Dopo
-una breve sezione introduttiva tratteremo le funzioni base per la gestione
-dell'input/output, mentre tratteremo le caratteristiche più avanzate
-dell'interfaccia nell'ultima sezione.
+quella che viene comunemente detta interfaccia dei \textit{file stream} o
+anche più brevemente degli \textit{stream}. Dopo una breve sezione
+introduttiva tratteremo le funzioni base per la gestione dell'input/output,
+mentre tratteremo le caratteristiche più avanzate dell'interfaccia nell'ultima
+sezione.
\section{Introduzione}
Come visto in cap.~\ref{cha:file_unix_interface} le operazioni di I/O sui file
sono gestibili a basso livello con l'interfaccia standard unix, che ricorre
-direttamente alle system call messe a disposizione dal kernel.
+direttamente alle \textit{system call} messe a disposizione dal kernel.
Questa interfaccia però non provvede le funzionalità previste dallo standard
ANSI C, che invece sono realizzate attraverso opportune funzioni di libreria,
\subsection{I \textit{file stream}}
\label{sec:file_stream}
-\index{file!stream|(}
+\itindbeg{file~stream}
Come più volte ribadito, l'interfaccia dei file descriptor è un'interfaccia di
basso livello, che non provvede nessuna forma di formattazione dei dati e
Se il programmatore non si cura di effettuare le operazioni in blocchi di
dimensioni adeguate, le prestazioni sono inferiori. La caratteristica
-principale dell'interfaccia degli stream è che essa provvede da sola alla
-gestione dei dettagli della bufferizzazione e all'esecuzione delle operazioni
-di lettura e scrittura in blocchi di dimensioni appropriate all'ottenimento
-della massima efficienza.
+principale dell'interfaccia degli \textit{stream} è che essa provvede da sola
+alla gestione dei dettagli della bufferizzazione e all'esecuzione delle
+operazioni di lettura e scrittura in blocchi di dimensioni appropriate
+all'ottenimento della massima efficienza.
Per questo motivo l'interfaccia viene chiamata anche interfaccia dei
\textit{file stream}, dato che non è più necessario doversi preoccupare
A parte i dettagli legati alla gestione delle operazioni di lettura e
scrittura (sia per quel che riguarda la bufferizzazione, che le
-formattazioni), i file stream restano del tutto equivalenti ai file descriptor
-(sui quali sono basati), ed in particolare continua a valere quanto visto in
-sez.~\ref{sec:file_sharing} a proposito dell'accesso condiviso ed in
+formattazioni), i \textit{file stream} restano del tutto equivalenti ai file
+descriptor (sui quali sono basati), ed in particolare continua a valere quanto
+visto in sez.~\ref{sec:file_sharing} a proposito dell'accesso condiviso ed in
sez.~\ref{sec:file_access_control} per il controllo di accesso.
-\index{file!stream|)}
+\itindend{file~stream}
\subsection{Gli oggetti \type{FILE}}
\label{sec:file_FILE}
-Per ragioni storiche la struttura di dati che rappresenta uno stream è stata
-chiamata \type{FILE}, questi oggetti sono creati dalle funzioni di libreria e
-contengono tutte le informazioni necessarie a gestire le operazioni sugli
-stream, come la posizione corrente, lo stato del buffer e degli indicatori di
-stato e di fine del file.
+Per ragioni storiche la struttura di dati che rappresenta uno \textit{stream}
+è stata chiamata \type{FILE}, questi oggetti sono creati dalle funzioni di
+libreria e contengono tutte le informazioni necessarie a gestire le operazioni
+sugli \textit{stream}, come la posizione corrente, lo stato del buffer e degli
+indicatori di stato e di fine del file.
Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare
queste strutture (che sono dei \index{tipo!opaco} \textsl{tipi opachi}) ma
usare sempre puntatori del tipo \texttt{FILE *} ottenuti dalla libreria stessa
(tanto che in certi casi il termine di puntatore a file è diventato sinonimo
-di stream). Tutte le funzioni della libreria che operano sui file accettano
-come argomenti solo variabili di questo tipo, che diventa accessibile
-includendo l'header file \file{stdio.h}.
+di \textit{stream}). Tutte le funzioni della libreria che operano sui file
+accettano come argomenti solo variabili di questo tipo, che diventa
+accessibile includendo l'header file \file{stdio.h}.
-\subsection{Gli stream standard}
+\subsection{Gli \textit{stream standard}}
\label{sec:file_std_stream}
-Ai tre file descriptor standard (vedi sez.~\ref{sec:file_std_descr})
-aperti per ogni processo, corrispondono altrettanti stream, che
-rappresentano i canali standard di input/output prestabiliti; anche
-questi tre stream sono identificabili attraverso dei nomi simbolici
-definiti nell'header \file{stdio.h} che sono:
+Ai tre file descriptor standard (vedi sez.~\ref{sec:file_std_descr}) aperti
+per ogni processo, corrispondono altrettanti \textit{stream}, che
+rappresentano i canali standard di input/output prestabiliti; anche questi tre
+\textit{stream} sono identificabili attraverso dei nomi simbolici definiti
+nell'header \file{stdio.h} che sono:
\begin{basedescript}{\desclabelwidth{3.0cm}}
-\item[\var{FILE *stdin}] Lo \textit{standard input} cioè lo stream da
- cui il processo riceve ordinariamente i dati in ingresso. Normalmente
- è associato dalla shell all'input del terminale e prende i caratteri
- dalla tastiera.
-\item[\var{FILE *stdout}] Lo \textit{standard output} cioè lo stream su
- cui il processo invia ordinariamente i dati in uscita. Normalmente è
- associato dalla shell all'output del terminale e scrive sullo schermo.
-\item[\var{FILE *stderr}] Lo \textit{standard error} cioè lo stream su
- cui il processo è supposto inviare i messaggi di errore. Normalmente
- anch'esso è associato dalla shell all'output del terminale e scrive
- sullo schermo.
+\item[\var{FILE *stdin}] Lo \textit{standard input} cioè il \textit{file
+ stream} da cui il processo riceve ordinariamente i dati in
+ ingresso. Normalmente è associato dalla shell all'input del terminale e
+ prende i caratteri dalla tastiera.
+\item[\var{FILE *stdout}] Lo \textit{standard output} cioè il \textit{file
+ stream} su cui il processo invia ordinariamente i dati in
+ uscita. Normalmente è associato dalla shell all'output del terminale e
+ scrive sullo schermo.
+\item[\var{FILE *stderr}] Lo \textit{standard error} cioè il \textit{file
+ stream} su cui il processo è supposto inviare i messaggi di
+ errore. Normalmente anch'esso è associato dalla shell all'output del
+ terminale e scrive sullo schermo.
\end{basedescript}
-Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
+Nella \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
tre variabili di tipo \type{FILE}\texttt{ *} che possono essere usate come
tutte le altre, ad esempio si può effettuare una redirezione dell'output di un
programma con il semplice codice: \includecodesnip{listati/redir_stdout.c} ma
\label{sec:file_buffering}
La bufferizzazione è una delle caratteristiche principali dell'interfaccia
-degli stream; lo scopo è quello di ridurre al minimo il numero di system call
-(\func{read} o \func{write}) eseguite nelle operazioni di input/output. Questa
-funzionalità è assicurata automaticamente dalla libreria, ma costituisce anche
-uno degli aspetti più comunemente fraintesi, in particolare per quello che
-riguarda l'aspetto della scrittura dei dati sul file.
-
-I caratteri che vengono scritti su di uno stream normalmente vengono
+degli \textit{stream}; lo scopo è quello di ridurre al minimo il numero di
+system call (\func{read} o \func{write}) eseguite nelle operazioni di
+input/output. Questa funzionalità è assicurata automaticamente dalla libreria,
+ma costituisce anche uno degli aspetti più comunemente fraintesi, in
+particolare per quello che riguarda l'aspetto della scrittura dei dati sul
+file.
+
+I caratteri che vengono scritti su di uno \textit{stream} normalmente vengono
accumulati in un buffer e poi trasmessi in blocco\footnote{questa operazione
viene usualmente chiamata \textsl{scaricamento} dei dati, dal termine
inglese \textit{flush}.} tutte le volte che il buffer viene riempito, in
Per lo stesso motivo, in tutte le situazioni in cui si sta facendo
dell'input/output interattivo, bisognerà tenere presente le caratteristiche
delle operazioni di scaricamento dei dati, poiché non è detto che ad una
-scrittura sullo stream corrisponda una immediata scrittura sul dispositivo (la
-cosa è particolarmente evidente quando con le operazioni di input/output su
-terminale).
+scrittura sullo \textit{stream} corrisponda una immediata scrittura sul
+dispositivo (la cosa è particolarmente evidente quando con le operazioni di
+input/output su terminale).
Per rispondere ad esigenze diverse, lo standard definisce tre distinte
modalità in cui può essere eseguita la bufferizzazione, delle quali
altrimenti.
Il comportamento specificato per standard input e standard output vale anche
-per tutti i nuovi stream aperti da un processo; la selezione comunque avviene
-automaticamente, e la libreria apre lo stream nella modalità più opportuna a
-seconda del file o del dispositivo scelto.
+per tutti i nuovi \textit{stream} aperti da un processo; la selezione comunque
+avviene automaticamente, e la libreria apre lo \textit{stream} nella modalità
+più opportuna a seconda del file o del dispositivo scelto.
La modalità \textit{line buffered} è quella che necessita di maggiori
chiarimenti e attenzioni per quel che concerne il suo funzionamento. Come già
anche prima che sia stato inviato un carattere di \textit{newline}.
Un secondo punto da tenere presente, particolarmente quando si ha a che fare
-con I/O interattivo, è che quando si effettua una lettura da uno stream che
-comporta l'accesso al kernel\footnote{questo vuol dire che lo stream da cui si
- legge è in modalità \textit{unbuffered}.} viene anche eseguito lo scarico di
-tutti i buffer degli stream in scrittura.
+con I/O interattivo, è che quando si effettua una lettura da uno
+\textit{stream} che comporta l'accesso al kernel\footnote{questo vuol dire che
+ lo \textit{stream} da cui si legge è in modalità \textit{unbuffered}.} viene
+anche eseguito lo scarico di tutti i buffer degli \textit{stream} in
+scrittura.
In sez.~\ref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle
opportune funzioni per controllare le modalità di bufferizzazione e lo scarico
\section{Funzioni base}
\label{sec:file_ansi_base_func}
-Esamineremo in questa sezione le funzioni base dell'interfaccia degli stream,
-analoghe a quelle di sez.~\ref{sec:file_base_func} per i file descriptor. In
-particolare vedremo come aprire, leggere, scrivere e cambiare la posizione
-corrente in uno stream.
+Esamineremo in questa sezione le funzioni base dell'interfaccia degli
+\textit{stream}, analoghe a quelle di sez.~\ref{sec:file_base_func} per i file
+descriptor. In particolare vedremo come aprire, leggere, scrivere e cambiare
+la posizione corrente in uno \textit{stream}.
-\subsection{Apertura e chiusura di uno stream}
+\subsection{Apertura e chiusura di uno \textit{stream}}
\label{sec:file_fopen}
-Le funzioni che si possono usare per aprire uno stream sono solo tre:
+Le funzioni che si possono usare per aprire uno \textit{stream} sono solo tre:
\funcd{fopen}, \funcd{fdopen} e \funcd{freopen},\footnote{\func{fopen} e
\func{freopen} fanno parte dello standard ANSI C, \func{fdopen} è parte
dello standard POSIX.1.} i loro prototipi sono:
\funcdecl{FILE *fopen(const char *path, const char *mode)}
Apre il file specificato da \param{path}.
\funcdecl{FILE *fdopen(int fildes, const char *mode)}
- Associa uno stream al file descriptor \param{fildes}.
+ Associa uno \textit{stream} al file descriptor \param{fildes}.
\funcdecl{FILE *freopen(const char *path, const char *mode, FILE *stream)}
- Apre il file specificato da \param{path} associandolo allo stream
+ Apre il file specificato da \param{path} associandolo allo \textit{stream}
specificato da \param{stream}, se questo è già aperto prima lo chiude.
\bodydesc{Le funzioni ritornano un puntatore valido in caso di successo e
\func{fclose} e \func{fflush} per \func{freopen}.}
\end{functions}
-Normalmente la funzione che si usa per aprire uno stream è \func{fopen},
-essa apre il file specificato nella modalità specificata da
-\param{mode}, che è una stringa che deve iniziare con almeno uno dei
-valori indicati in tab.~\ref{tab:file_fopen_mode} (sono possibili varie
-estensioni che vedremo in seguito).
+Normalmente la funzione che si usa per aprire uno \textit{stream} è
+\func{fopen}, essa apre il file specificato nella modalità specificata da
+\param{mode}, che è una stringa che deve iniziare con almeno uno dei valori
+indicati in tab.~\ref{tab:file_fopen_mode} (sono possibili varie estensioni
+che vedremo in seguito).
L'uso più comune di \func{freopen} è per redirigere uno dei tre file
standard (vedi sez.~\ref{sec:file_std_stream}): il file \param{path} viene
-associato a \param{stream} e se questo è uno stream già aperto viene
+associato a \param{stream} e se questo è uno \textit{stream} già aperto viene
preventivamente chiuso.
-Infine \func{fdopen} viene usata per associare uno stream ad un file
+Infine \func{fdopen} viene usata per associare uno \textit{stream} ad un file
descriptor esistente ottenuto tramite una altra funzione (ad esempio con una
\func{open}, una \func{dup}, o una \func{pipe}) e serve quando si vogliono
-usare gli stream con file come le fifo o i socket, che non possono essere
-aperti con le funzioni delle librerie standard del C.
+usare gli \textit{stream} con file come le fifo o i socket, che non possono
+essere aperti con le funzioni delle librerie standard del C.
\begin{table}[htb]
\centering
\hline
\hline
\texttt{r} & Il file viene aperto, l'accesso viene posto in sola
- lettura, lo stream è posizionato all'inizio del file.\\
+ lettura, lo \textit{stream} è posizionato all'inizio del
+ file.\\
\texttt{r+}& Il file viene aperto, l'accesso viene posto in lettura e
- scrittura, lo stream è posizionato all'inizio del file.\\
+ scrittura, lo \textit{stream} è posizionato all'inizio del
+ file.\\
% \hline
\texttt{w} & Il file viene aperto e troncato a lunghezza nulla (o
creato se non esiste), l'accesso viene posto in sola
- scrittura, lo stream è posizionato all'inizio del file.\\
+ scrittura, lo stream\textit{} è posizionato all'inizio del
+ file.\\
\texttt{w+}& Il file viene aperto e troncato a lunghezza nulla (o
creato se non esiste), l'accesso viene posto in scrittura e
- lettura, lo stream è posizionato all'inizio del file.\\
+ lettura, lo \textit{stream} è posizionato all'inizio del
+ file.\\
% \hline
\texttt{a} & Il file viene aperto (o creato se non esiste) in
\itindex{append~mode} \textit{append mode}, l'accesso viene
\texttt{x} & L'apertura fallisce se il file esiste già. \\
\hline
\end{tabular}
- \caption{Modalità di apertura di uno stream dello standard ANSI C che
- sono sempre presenti in qualunque sistema POSIX.}
+ \caption{Modalità di apertura di uno \textit{stream} dello standard ANSI C
+ che sono sempre presenti in qualunque sistema POSIX.}
\label{tab:file_fopen_mode}
\end{table}
Nel caso si usi \func{fdopen} i valori specificati da \param{mode} devono
essere compatibili con quelli con cui il file descriptor è stato aperto.
Inoltre i modi \cmd{w} e \cmd{w+} non troncano il file. La posizione nello
-stream viene impostata a quella corrente nel file descriptor, e le variabili
-di errore e di fine del file (vedi sez.~\ref{sec:file_io}) sono cancellate. Il
-file non viene duplicato e verrà chiuso alla chiusura dello stream.
+\textit{stream} viene impostata a quella corrente nel file descriptor, e le
+variabili di errore e di fine del file (vedi sez.~\ref{sec:file_io}) sono
+cancellate. Il file non viene duplicato e verrà chiuso alla chiusura dello
+\textit{stream}.
I nuovi file saranno creati secondo quanto visto in
sez.~\ref{sec:file_ownership_management} ed avranno i permessi di accesso
un'operazione nominalmente nulla come \code{fseek(file, 0, SEEK\_CUR)} è
sufficiente a garantire la sincronizzazione.
-Una volta aperto lo stream, si può cambiare la modalità di bufferizzazione
-(si veda sez.~\ref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
-alcuna operazione di I/O sul file.
+Una volta aperto lo \textit{stream}, si può cambiare la modalità di
+bufferizzazione (si veda sez.~\ref{sec:file_buffering_ctrl}) fintanto che non
+si è effettuato alcuna operazione di I/O sul file.
-Uno stream viene chiuso con la funzione \funcd{fclose} il cui prototipo è:
+Uno \textit{stream} viene chiuso con la funzione \funcd{fclose} il cui
+prototipo è:
\begin{prototype}{stdio.h}{int fclose(FILE *stream)}
- Chiude lo stream \param{stream}.
+ Chiude lo \textit{stream} \param{stream}.
\bodydesc{Restituisce 0 in caso di successo e \val{EOF} in caso di errore,
nel qual caso imposta \var{errno} a \errval{EBADF} se il file descriptor
La funzione effettua lo scarico di tutti i dati presenti nei buffer di uscita
e scarta tutti i dati in ingresso; se era stato allocato un buffer per lo
-stream questo verrà rilasciato. La funzione effettua lo scarico solo per i
-dati presenti nei buffer in user space usati dalle \acr{glibc}; se si vuole
-essere sicuri che il kernel forzi la scrittura su disco occorrerà effettuare
-una \func{sync} (vedi sez.~\ref{sec:file_sync}).
+\textit{stream} questo verrà rilasciato. La funzione effettua lo scarico solo
+per i dati presenti nei buffer in user space usati dalle \acr{glibc}; se si
+vuole essere sicuri che il kernel forzi la scrittura su disco occorrerà
+effettuare una \func{sync} (vedi sez.~\ref{sec:file_sync}).
Linux supporta anche una altra funzione, \funcd{fcloseall}, come estensione
GNU implementata dalle \acr{glibc}, accessibile avendo definito
\macro{\_GNU\_SOURCE}, il suo prototipo è:
\begin{prototype}{stdio.h}{int fcloseall(void)}
- Chiude tutti gli stream.
+ Chiude tutti gli \textit{stream}.
\bodydesc{Restituisce 0 se non ci sono errori ed \val{EOF} altrimenti.}
\end{prototype}
provvista solo per i casi di emergenza, quando si è verificato un errore
ed il programma deve essere abortito, ma si vuole compiere qualche altra
operazione dopo aver chiuso i file e prima di uscire (si ricordi quanto
-visto in sez.~\ref{sec:proc_exit}).
+visto in sez.~\ref{sec:proc_conclusion}).
-\subsection{Lettura e scrittura su uno stream}
+\subsection{Lettura e scrittura su uno \textit{stream}}
\label{sec:file_io}
-Una delle caratteristiche più utili dell'interfaccia degli stream è la
-ricchezza delle funzioni disponibili per le operazioni di lettura e
-scrittura sui file. Sono infatti previste ben tre diverse modalità
-modalità di input/output non formattato:
+Una delle caratteristiche più utili dell'interfaccia degli \textit{stream} è
+la ricchezza delle funzioni disponibili per le operazioni di lettura e
+scrittura sui file. Sono infatti previste ben tre diverse modalità modalità di
+input/output non formattato:
\begin{enumerate*}
\item\textsl{binario} in cui legge/scrive un blocco di dati alla
volta, vedi sez.~\ref{sec:file_binary_io}.
\end{enumerate*}
ed inoltre la modalità di input/output formattato.
-A differenza dell'interfaccia dei file descriptor, con gli stream il
+A differenza dell'interfaccia dei file descriptor, con gli \textit{stream} il
raggiungimento della fine del file è considerato un errore, e viene
notificato come tale dai valori di uscita delle varie funzioni. Nella
maggior parte dei casi questo avviene con la restituzione del valore
negativa, le \acr{glibc} usano -1, altre implementazioni possono avere
valori diversi.} definito anch'esso nell'header \file{stdlib.h}.
-Dato che le funzioni dell'interfaccia degli stream sono funzioni di libreria
-che si appoggiano a delle system call, esse non impostano direttamente la
-variabile \var{errno}, che mantiene il valore impostato dalla system call che
-ha riportato l'errore.
+Dato che le funzioni dell'interfaccia degli \textit{stream} sono funzioni di
+libreria che si appoggiano a delle system call, esse non impostano
+direttamente la variabile \var{errno}, che mantiene il valore impostato dalla
+system call che ha riportato l'errore.
Siccome la condizione di end-of-file è anch'essa segnalata come errore, nasce
il problema di come distinguerla da un errore effettivo; basarsi solo sul
una altra occasione, (si veda sez.~\ref{sec:sys_errno} per i dettagli del
funzionamento di \var{errno}).
-Per questo motivo tutte le implementazioni delle librerie standard
-mantengono per ogni stream almeno due flag all'interno dell'oggetto
-\type{FILE}, il flag di \textit{end-of-file}, che segnala che si è
-raggiunta la fine del file in lettura, e quello di errore, che segnala
-la presenza di un qualche errore nelle operazioni di input/output;
-questi due flag possono essere riletti dalle funzioni \funcd{feof} e
-\funcd{ferror}, i cui prototipi sono:
+Per questo motivo tutte le implementazioni delle librerie standard mantengono
+per ogni \textit{stream} almeno due flag all'interno dell'oggetto \type{FILE},
+il flag di \textit{end-of-file}, che segnala che si è raggiunta la fine del
+file in lettura, e quello di errore, che segnala la presenza di un qualche
+errore nelle operazioni di input/output; questi due flag possono essere
+riletti dalle funzioni \funcd{feof} e \funcd{ferror}, i cui prototipi sono:
\begin{functions}
\headdecl{stdio.h}
\funcdecl{int feof(FILE *stream)}
\end{functions}
\noindent si tenga presente comunque che la lettura di questi flag segnala
soltanto che c'è stato un errore, o che si è raggiunta la fine del file in una
-qualunque operazione sullo stream, il controllo quindi deve essere effettuato
-ogni volta che si chiama una funzione di libreria.
+qualunque operazione sullo \textit{stream}, il controllo quindi deve essere
+effettuato ogni volta che si chiama una funzione di libreria.
Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando
la funzione \funcd{clearerr}, il cui prototipo è:
corretta la causa di un errore per evitare di mantenere i flag attivi, così da
poter rilevare una successiva ulteriore condizione di errore. Di questa
funzione esiste una analoga \func{clearerr\_unlocked} che non esegue il blocco
-dello stream (vedi sez.~\ref{sec:file_stream_thread}).
+dello \textit{stream} (vedi sez.~\ref{sec:file_stream_thread}).
\subsection{Input/output binario}
ma il numero di elementi.
La funzione \func{fread} legge sempre un numero intero di elementi, se
-incontra la fine del file l'oggetto letto parzialmente viene scartato
-(lo stesso avviene in caso di errore). In questo caso la posizione dello
-stream viene impostata alla fine del file (e non a quella corrispondente
-alla quantità di dati letti).
+incontra la fine del file l'oggetto letto parzialmente viene scartato (lo
+stesso avviene in caso di errore). In questo caso la posizione dello
+\textit{stream} viene impostata alla fine del file (e non a quella
+corrispondente alla quantità di dati letti).
In caso di errore (o fine del file per \func{fread}) entrambe le
funzioni restituiscono il numero di oggetti effettivamente letti o
Le \acr{glibc} definiscono altre due funzioni per l'I/O binario,
\funcd{fread\_unlocked} e \funcd{fwrite\_unlocked} che evitano il lock
-implicito dello stream, usato per dalla librerie per la gestione delle
+implicito dello \textit{stream}, usato per dalla librerie per la gestione delle
applicazioni \itindex{thread} \textit{multi-thread} (si veda
sez.~\ref{sec:file_stream_thread} per i dettagli), i loro prototipi sono:
\begin{functions}
size\_t nmemb, FILE *stream)}
\bodydesc{Le funzioni sono identiche alle analoghe \func{fread} e
- \func{fwrite} ma non acquisiscono il lock implicito sullo stream.}
+ \func{fwrite} ma non acquisiscono il lock implicito sullo \textit{stream}.}
\end{functions}
\noindent entrambe le funzioni sono estensioni GNU previste solo dalle
\acr{glibc}.
provvedono come estensione, per ciascuna delle funzioni precedenti,
un'ulteriore funzione, il cui nome è ottenuto aggiungendo un
\code{\_unlocked}, che esegue esattamente le stesse operazioni, evitando però
-il lock implicito dello stream.
+il lock implicito dello \textit{stream}.
Per compatibilità con SVID sono inoltre provviste anche due funzioni,
\funcd{getw} e \funcd{putw}, da usare per leggere e scrivere una \textit{word}
Uno degli usi più frequenti dell'input/output a caratteri è nei programmi di
\textit{parsing} in cui si analizza il testo; in questo contesto diventa utile
-poter analizzare il carattere successivo da uno stream senza estrarlo
+poter analizzare il carattere successivo da uno \textit{stream} senza estrarlo
effettivamente (la tecnica è detta \textit{peeking ahead}) in modo che il
programma possa regolarsi avendo dato una \textsl{sbirciatina} a quello che
viene dopo.
lettura si chiama \funcd{ungetc} ed il suo prototipo è:
\begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)}
Rimanda indietro il carattere \param{c}, con un cast a \ctyp{unsigned
- char}, sullo stream \param{stream}.
+ char}, sullo \textit{stream} \param{stream}.
\bodydesc{La funzione ritorna \param{c} in caso di successo e
\val{EOF} in caso di errore.}
\acr{glibc} supportano una serie di altre funzioni, estensioni di tutte quelle
illustrate finora (eccetto \func{gets} e \func{puts}), che eseguono
esattamente le stesse operazioni delle loro equivalenti, evitando però il lock
-implicito dello stream (vedi sez.~\ref{sec:file_stream_thread}). Come per le
-altre forma di I/O, dette funzioni hanno lo stesso nome della loro analoga
-normale, con l'aggiunta dell'estensione \code{\_unlocked}.
+implicito dello \textit{stream} (vedi sez.~\ref{sec:file_stream_thread}). Come
+per le altre forma di I/O, dette funzioni hanno lo stesso nome della loro
+analoga normale, con l'aggiunta dell'estensione \code{\_unlocked}.
Come abbiamo visto, le funzioni di lettura per l'input/output di linea
previste dallo standard ANSI C presentano svariati inconvenienti. Benché
liberare \var{ptr} con una \func{free}.
Il valore di ritorno della funzione indica il numero di caratteri letti
-dallo stream (quindi compreso il newline, ma non lo zero di
+dallo \textit{stream} (quindi compreso il newline, ma non lo zero di
terminazione); questo permette anche di distinguere eventuali zeri letti
-dallo stream da quello inserito dalla funzione per terminare la linea.
+dallo \textit{stream} da quello inserito dalla funzione per terminare la linea.
Se si è alla fine del file e non si è potuto leggere nulla o c'è stato
un errore la funzione restituisce -1.
La parte più complessa delle funzioni di scrittura formattata è il formato
della stringa \param{format} che indica le conversioni da fare, e da cui
deriva anche il numero degli argomenti che dovranno essere passati a seguire
-(si noti come tutte queste funzioni siano \index{variadic} \textit{variadic},
-prendendo un numero di argomenti variabile che dipende appunto da quello che
-si è specificato in \param{format}).
+(si noti come tutte queste funzioni siano \index{funzioni!variadic}
+\textit{variadic}, prendendo un numero di argomenti variabile che dipende
+appunto da quello che si è specificato in \param{format}).
\begin{table}[htb]
\centering
\end{table}
Una versione alternativa delle funzioni di output formattato, che permettono
-di usare il puntatore ad una lista di argomenti (vedi
-sez.~\ref{sec:proc_variadic}), sono \funcd{vprintf}, \funcd{vfprintf} e
-\funcd{vsprintf}, i cui prototipi sono:
+di usare il puntatore ad una lista variabile \index{funzioni!variadic} di
+argomenti (vedi sez.~\ref{sec:proc_variadic}), sono \funcd{vprintf},
+\funcd{vfprintf} e \funcd{vsprintf}, i cui prototipi sono:
\begin{functions}
\headdecl{stdio.h}
\end{functions}
\noindent con queste funzioni diventa possibile selezionare gli argomenti che
si vogliono passare ad una funzione di stampa, passando direttamente la lista
-tramite l'argomento \param{ap}. Per poter far questo ovviamente la lista degli
-argomenti dovrà essere opportunamente trattata (l'argomento è esaminato in
-sez.~\ref{sec:proc_variadic}), e dopo l'esecuzione della funzione l'argomento
+tramite l'argomento \param{ap}. Per poter far questo ovviamente la lista
+variabile\index{funzioni!variadic} degli argomenti dovrà essere opportunamente
+trattata (l'argomento è esaminato in sez.~\ref{sec:proc_variadic}), e dopo
+l'esecuzione della funzione l'argomento
\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
\code{va\_end(ap)} ma in Linux questo non è necessario).
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 \texttt{w}
-davanti a \texttt{print}, sono trattate in dettaglio nella documentazione delle
-\acr{glibc}.
+\func{vdprintf}, che prendono un file descriptor al posto dello
+\textit{stream}. Altre estensioni permettono di scrivere con caratteri
+estesi. Anche queste funzioni, il cui nome è generato dalle precedenti
+funzioni aggiungendo una \texttt{w} davanti a \texttt{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
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 argomento è 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 ecc.), 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 pagine di manuale e nel manuale delle \acr{glibc}.
+Le funzioni leggono i caratteri dallo \textit{stream} (o dalla stringa) di
+input ed eseguono un confronto con quanto indicato in \param{format}, la
+sintassi di questo argomento è 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 ecc.), 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 pagine di manuale 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.
+\textit{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
manuale \cite{bison}.} per generare un parser.
-\subsection{Posizionamento su uno stream}
+\subsection{Posizionamento su uno \textit{stream}}
\label{sec:file_fseek}
-Come per i file descriptor anche per gli stream è possibile spostarsi
+Come per i file descriptor anche per gli \textit{stream} è possibile spostarsi
all'interno di un file per effettuare operazioni di lettura o scrittura in un
punto prestabilito; sempre che l'operazione di riposizionamento sia supportata
-dal file sottostante lo stream, quando cioè si ha a che fare con quello che
-viene detto un file ad \textsl{accesso casuale}.\footnote{dato che in un
- sistema Unix esistono vari tipi di file, come le fifo ed i
+dal file sottostante lo \textit{stream}, quando cioè si ha a che fare con
+quello che viene detto un file ad \textsl{accesso casuale}.\footnote{dato che
+ in un sistema Unix esistono vari tipi di file, come le fifo ed i
\index{file!di~dispositivo} file di dispositivo, non è scontato che questo
sia sempre vero.}
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 è che 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, più l'offset
-rispetto al record corrente).
+\textit{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, più
+l'offset rispetto al record corrente).
Tutto questo comporta la presenza di diverse funzioni che eseguono
sostanzialmente le stesse operazioni, ma usano argomenti di tipo diverso. Le
funzioni tradizionali usate per il riposizionamento della posizione in uno
-stream sono \funcd{fseek} e \funcd{rewind} i cui prototipi sono:
+\textit{stream} sono \funcd{fseek} e \funcd{rewind} i cui prototipi sono:
\begin{functions}
\headdecl{stdio.h}
\funcdecl{int fseek(FILE *stream, long offset, int whence)} Sposta la
- posizione nello stream secondo quanto specificato tramite \param{offset}
- e \param{whence}.
+ posizione nello \textit{stream} secondo quanto specificato
+ tramite \param{offset} e \param{whence}.
- \funcdecl{void rewind(FILE *stream)} Riporta la posizione nello stream
- all'inizio del file.
+ \funcdecl{void rewind(FILE *stream)} Riporta la posizione nello
+ \textit{stream} all'inizio del file.
\end{functions}
L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i file
particolare \param{whence} assume gli stessi valori già visti in
sez.~\ref{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'inizio dello stream, ma non esattamente equivalente ad
-una \code{fseek(stream, 0L, SEEK\_SET)} in quanto vengono cancellati anche i
-flag di errore e fine del file.
+posizione corrente all'inizio dello \textit{stream}, ma non esattamente
+equivalente ad una \code{fseek(stream, 0L, SEEK\_SET)} in quanto vengono
+cancellati anche i flag di errore e fine del file.
Per ottenere la posizione corrente si usa invece la funzione \funcd{ftell}, il
cui prototipo è:
\begin{prototype}{stdio.h}{long ftell(FILE *stream)}
- Legge la posizione attuale nello stream \param{stream}.
+ Legge la posizione attuale nello \textit{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
essere espressa con un \ctyp{long int}}
\end{prototype}
\noindent la funzione restituisce la posizione come numero di byte
-dall'inizio dello stream.
+dall'inizio dello \textit{stream}.
Queste funzioni esprimono tutte la posizione nel file come un \ctyp{long int}.
Dato che (ad esempio quando si usa un filesystem indicizzato a 64 bit) questo
\headdecl{stdio.h}
\funcdecl{int fsetpos(FILE *stream, fpos\_t *pos)} Imposta la posizione
- corrente nello stream \param{stream} al valore specificato da \param{pos}.
+ corrente nello \textit{stream} \param{stream} al valore specificato
+ da \param{pos}.
\funcdecl{int fgetpos(FILE *stream, fpos\_t *pos)} Legge la posizione
- corrente nello stream \param{stream} e la scrive in \param{pos}.
+ corrente nello \textit{stream} \param{stream} e la scrive in \param{pos}.
\bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di
errore.}
\label{sec:file_stream_adv_func}
In questa sezione esamineremo alcune funzioni avanzate che permettono di
-eseguire operazioni particolari sugli stream, come leggerne gli attributi,
-controllarne le modalità di bufferizzazione, gestire direttamente i lock
-impliciti per la programmazione \itindex{thread} \textit{multi-thread}.
+eseguire operazioni particolari sugli \textit{stream}, come leggerne gli
+attributi, controllarne le modalità di bufferizzazione, gestire direttamente i
+lock impliciti per la programmazione \itindex{thread} \textit{multi-thread}.
\subsection{Le funzioni di controllo}
Al contrario di quanto avviene con i file descriptor, le librerie standard del
C non prevedono nessuna funzione come la \func{fcntl} per il controllo degli
-attributi dei file. Però, dato che ogni stream si appoggia ad un file
+attributi dei file. Però, dato che ogni \textit{stream} si appoggia ad un file
descriptor, si può usare la funzione \funcd{fileno} per ottenere quest'ultimo,
il prototipo della funzione è:
\begin{prototype}{stdio.h}{int fileno(FILE *stream)}
- Legge il file descriptor sottostante lo stream \param{stream}.
+ Legge il file descriptor sottostante lo \textit{stream} \param{stream}.
\bodydesc{Restituisce il numero del file descriptor in caso di successo, e
-1 qualora \param{stream} non sia valido, nel qual caso imposta
\noindent ed in questo modo diventa possibile usare direttamente \func{fcntl}.
Questo permette di accedere agli attributi del file descriptor sottostante lo
-stream, ma non ci dà nessuna informazione riguardo alle proprietà dello stream
-medesimo. Le \acr{glibc} però supportano alcune estensioni derivate da
-Solaris, che permettono di ottenere informazioni utili.
-
-Ad esempio in certi casi può essere necessario sapere se un certo stream è
-accessibile in lettura o scrittura. In genere questa informazione non è
-disponibile, e si deve ricordare come il file è stato aperto. La cosa può
-essere complessa se le operazioni vengono effettuate in una subroutine, che a
-questo punto necessiterà di informazioni aggiuntive rispetto al semplice
-puntatore allo stream; questo può essere evitato con le due funzioni
-\funcd{\_\_freadable} e \funcd{\_\_fwritable} i cui prototipi sono:
+\textit{stream}, ma non ci dà nessuna informazione riguardo alle proprietà
+dello \textit{stream} medesimo. Le \acr{glibc} però supportano alcune
+estensioni derivate da Solaris, che permettono di ottenere informazioni utili.
+
+Ad esempio in certi casi può essere necessario sapere se un certo
+\textit{stream} è accessibile in lettura o scrittura. In genere questa
+informazione non è disponibile, e si deve ricordare come il file è stato
+aperto. La cosa può essere complessa se le operazioni vengono effettuate in
+una subroutine, che a questo punto necessiterà di informazioni aggiuntive
+rispetto al semplice puntatore allo \textit{stream}; questo può essere evitato
+con le due funzioni \funcd{\_\_freadable} e \funcd{\_\_fwritable} i cui
+prototipi sono:
\begin{functions}
\headdecl{stdio\_ext.h}
\funcdecl{int \_\_freadable(FILE *stream)}
\end{functions}
\noindent che permettono di ottenere questa informazione.
-La conoscenza dell'ultima operazione effettuata su uno stream aperto è utile
-in quanto permette di trarre conclusioni sullo stato del buffer e del suo
-contenuto. Altre due funzioni, \funcd{\_\_freading} e \funcd{\_\_fwriting}
+La conoscenza dell'ultima operazione effettuata su uno \textit{stream} aperto
+è utile in quanto permette di trarre conclusioni sullo stato del buffer e del
+suo contenuto. Altre due funzioni, \funcd{\_\_freading} e \funcd{\_\_fwriting}
servono a tale scopo, il loro prototipo è:
\begin{functions}
\headdecl{stdio\_ext.h}
\end{functions}
Le due funzioni permettono di determinare di che tipo è stata l'ultima
-operazione eseguita su uno stream aperto in lettura/scrittura; ovviamente se
-uno stream è aperto in sola lettura (o sola scrittura) la modalità dell'ultima
-operazione è sempre determinata; l'unica ambiguità è quando non sono state
-ancora eseguite operazioni, in questo caso le funzioni rispondono come se una
-operazione ci fosse comunque stata.
+operazione eseguita su uno \textit{stream} aperto in lettura/scrittura;
+ovviamente se uno \textit{stream} è aperto in sola lettura (o sola scrittura)
+la modalità dell'ultima operazione è sempre determinata; l'unica ambiguità è
+quando non sono state ancora eseguite operazioni, in questo caso le funzioni
+rispondono come se una operazione ci fosse comunque stata.
\subsection{Il controllo della bufferizzazione}
\label{sec:file_buffering_ctrl}
Come accennato in sez.~\ref{sec:file_buffering} le librerie definiscono una
-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.
+serie di funzioni che permettono di controllare il comportamento degli
+\textit{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
+Però una volta che si sia aperto lo \textit{stream} (ma prima di aver compiuto
operazioni su di esso) è possibile intervenire sulle modalità di buffering; la
funzione che permette di controllare la bufferizzazione è \funcd{setvbuf}, il
suo prototipo è:
\begin{prototype}{stdio.h}{int setvbuf(FILE *stream, char *buf, int mode,
size\_t size)}
- Imposta la bufferizzazione dello stream \param{stream} nella modalità
- indicata da \param{mode}, usando \param{buf} come buffer di lunghezza
+ Imposta la bufferizzazione dello \textit{stream} \param{stream} nella
+ modalità indicata da \param{mode}, usando \param{buf} come buffer di
+ lunghezza
\param{size}.
\bodydesc{Restituisce zero in caso di successo, ed un valore qualunque in
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 \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 \file{stdio.h} è
-definita la macro \const{BUFSIZ}, che indica le dimensioni generiche del
-buffer di uno stream; queste vengono usate dalla funzione \func{setbuf}. Non
-è detto però che tale dimensione corrisponda sempre al valore ottimale (che
-può variare a seconda del dispositivo).
+\textit{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 \index{variabili!automatiche} variabile
+automatica. In \file{stdio.h} è definita la macro \const{BUFSIZ}, che indica
+le dimensioni generiche del buffer di uno \textit{stream}; queste vengono
+usate dalla funzione \func{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
vengono sempre ignorati.
Oltre a \func{setvbuf} le \acr{glibc} definiscono altre tre funzioni per la
-gestione della bufferizzazione di uno stream: \funcd{setbuf}, \funcd{setbuffer}
-e \funcd{setlinebuf}; i loro prototipi sono:
+gestione della bufferizzazione di uno \textit{stream}: \funcd{setbuf},
+\funcd{setbuffer} e \funcd{setlinebuf}; i loro prototipi sono:
\begin{functions}
\headdecl{stdio.h}
la bufferizzazione se \param{buf} è \val{NULL}, altrimenti usa \param{buf}
come buffer di dimensione \param{size} in modalità \textit{fully buffered}.
- \funcdecl{void setlinebuf(FILE *stream)} Pone lo stream in modalità
+ \funcdecl{void setlinebuf(FILE *stream)} Pone lo \textit{stream} in modalità
\textit{line buffered}.
\end{functions}
\noindent tutte queste funzioni sono realizzate con opportune chiamate a
BSD. Infine le \acr{glibc} provvedono le funzioni non standard\footnote{anche
queste funzioni sono originarie di Solaris.} \funcd{\_\_flbf} e
\funcd{\_\_fbufsize} che permettono di leggere le proprietà di bufferizzazione
-di uno stream; i cui prototipi sono:
+di uno \textit{stream}; i cui prototipi sono:
\begin{functions}
\headdecl{stdio\_ext.h}
\funcd{fflush}, il suo prototipo è:
\begin{prototype}{stdio.h}{int fflush(FILE *stream)}
- Forza la scrittura di tutti i dati bufferizzati dello stream \param{stream}.
+ Forza la scrittura di tutti i dati bufferizzati dello
+ \textit{stream} \param{stream}.
\bodydesc{Restituisce zero in caso di successo, ed \val{EOF} in caso di
errore, impostando \var{errno} a \errval{EBADF} se \param{stream} non è
dello stream.
Se \param{stream} è \val{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 \acr{glibc} supportano una estensione di Solaris, la
-funzione \funcd{\_flushlbf}, il cui prototipo è:
+\textit{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 \textit{stream} in modalità
+line buffered; per questo motivo le \acr{glibc} supportano una estensione di
+Solaris, la funzione \funcd{\_flushlbf}, il cui prototipo è:
\begin{prototype}{stdio-ext.h}{void \_flushlbf(void)}
- Forza la scrittura di tutti i dati bufferizzati degli stream in modalità
- line buffered.
+ Forza la scrittura di tutti i dati bufferizzati degli \textit{stream} in
+ modalità line buffered.
\end{prototype}
Si ricordi comunque che lo scarico dei dati dai buffer effettuato da queste
pendente; per questo si può usare \funcd{fpurge}, il cui prototipo è:
\begin{prototype}{stdio.h}{int fpurge(FILE *stream)}
- Cancella i buffer di input e di output dello stream \param{stream}.
+ Cancella i buffer di input e di output dello \textit{stream} \param{stream}.
\bodydesc{Restituisce zero in caso di successo, ed \val{EOF} in caso di
errore.}
\itindbeg{thread}
-Gli stream possono essere usati in applicazioni \textit{multi-thread} allo
-stesso modo in cui sono usati nelle applicazioni normali, ma si deve essere
-consapevoli delle possibili complicazioni anche quando non si usano i
+Gli \textit{stream} possono essere usati in applicazioni \textit{multi-thread}
+allo stesso modo in cui sono usati nelle applicazioni normali, ma si deve
+essere consapevoli delle possibili complicazioni anche quando non si usano i
\textit{thread}, dato che l'implementazione delle librerie è influenzata
pesantemente dalle richieste necessarie per garantirne l'uso con i
\textit{thread}.
Lo standard POSIX richiede che le operazioni sui file siano atomiche rispetto
ai \textit{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.
+funzioni di libreria durante la lettura e la scrittura di uno \textit{stream}
+devono essere opportunamente protette (in quanto il sistema assicura
+l'atomicità solo per le system call). Questo viene fatto associando ad ogni
+\textit{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
-\textit{thread} necessita di compiere più di una operazione sullo stream
-atomicamente, per questo motivo le librerie provvedono anche delle funzioni
-\funcd{flockfile}, \funcd{ftrylockfile} e \funcd{funlockfile}, che permettono
-la gestione esplicita dei blocchi sugli stream; esse sono disponibili
-definendo \macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro prototipi sono:
+\textit{thread} necessita di compiere più di una operazione sullo
+\textit{stream} atomicamente, per questo motivo le librerie provvedono anche
+delle funzioni \funcd{flockfile}, \funcd{ftrylockfile} e \funcd{funlockfile},
+che permettono la gestione esplicita dei blocchi sugli \textit{stream}; esse
+sono disponibili definendo \macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro
+prototipi sono:
\begin{functions}
\headdecl{stdio.h}
\funcdecl{void flockfile(FILE *stream)} Esegue l'acquisizione del lock dello
- stream \param{stream}, bloccandosi se il lock non è disponibile.
+ \textit{stream} \param{stream}, bloccandosi se il lock non è disponibile.
\funcdecl{int ftrylockfile(FILE *stream)} Tenta l'acquisizione del lock
- dello stream \param{stream}, senza bloccarsi se il lock non è disponibile.
- Ritorna zero in caso di acquisizione del lock, diverso da zero altrimenti.
+ dello \textit{stream} \param{stream}, senza bloccarsi se il lock non è
+ disponibile. Ritorna zero in caso di acquisizione del lock, diverso da zero
+ altrimenti.
\funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
- stream \param{stream}.
+ \textit{stream} \param{stream}.
\end{functions}
\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 \textit{thread}), tutta
-la procedura può comportare dei costi pesanti in termini di prestazioni. Per
-questo motivo abbiamo visto come alle usuali funzioni di I/O non formattato
-siano associate delle versioni \code{\_unlocked} (alcune previste dallo stesso
-standard POSIX, altre aggiunte come estensioni dalle \acr{glibc}) che possono
-essere usate quando il locking non serve\footnote{in certi casi dette funzioni
- possono essere usate, visto che sono molto più efficienti, anche in caso di
- necessità di locking, una volta che questo sia stato acquisito manualmente.}
-con prestazioni molto più elevate, dato che spesso queste versioni (come
-accade per \func{getc} e \func{putc}) sono realizzate come macro.
+blocco non sono del tutto indolori, e quando il locking dello \textit{stream}
+non è necessario (come in tutti i programmi che non usano i \textit{thread}),
+tutta la procedura può comportare dei costi pesanti in termini di
+prestazioni. Per questo motivo abbiamo visto come alle usuali funzioni di I/O
+non formattato siano associate delle versioni \code{\_unlocked} (alcune
+previste dallo stesso standard POSIX, altre aggiunte come estensioni dalle
+\acr{glibc}) che possono essere usate quando il locking non serve\footnote{in
+ certi casi dette funzioni possono essere usate, visto che sono molto più
+ efficienti, anche in caso di necessità di locking, una volta che questo sia
+ stato acquisito manualmente.} con prestazioni molto più elevate, dato che
+spesso queste versioni (come accade per \func{getc} e \func{putc}) sono
+realizzate come macro.
La sostituzione di tutte le funzioni di I/O con le relative versioni
\code{\_unlocked} in un programma che non usa i \textit{thread} è però un
lavoro abbastanza noioso; per questo motivo le \acr{glibc} forniscono al
programmatore pigro un'altra via\footnote{anche questa mutuata da estensioni
introdotte in Solaris.} da poter utilizzare per disabilitare in blocco il
-locking degli stream: l'uso della funzione \funcd{\_\_fsetlocking}, il cui
-prototipo è:
+locking degli \textit{stream}: l'uso della funzione \funcd{\_\_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.
+ all'acquisizione implicita del blocco sullo \textit{stream}.
- \bodydesc{Restituisce lo stato di locking interno dello stream con uno dei
- valori \const{FSETLOCKING\_INTERNAL} o \const{FSETLOCKING\_BYCALLER}.}
+ \bodydesc{Restituisce lo stato di locking interno dello \textit{stream} con
+ uno dei valori \const{FSETLOCKING\_INTERNAL} o
+ \const{FSETLOCKING\_BYCALLER}.}
\end{prototype}
-La funzione imposta o legge lo stato della modalità di operazione di uno stream
-nei confronti del locking a seconda del valore specificato con \param{type},
-che può essere uno dei seguenti:
+La funzione imposta o legge lo stato della modalità di operazione di uno
+\textit{stream} nei confronti del locking a seconda del valore specificato
+con \param{type}, che può essere uno dei seguenti:
\begin{basedescript}{\desclabelwidth{4.0cm}}
-\item[\const{FSETLOCKING\_INTERNAL}] Lo stream userà da ora in poi il blocco
- implicito predefinito.
+\item[\const{FSETLOCKING\_INTERNAL}] Lo \textit{stream} userà da ora in poi il
+ blocco implicito predefinito.
\item[\const{FSETLOCKING\_BYCALLER}] Al ritorno della funzione sarà l'utente a
- dover gestire da solo il locking dello stream.
+ dover gestire da solo il locking dello \textit{stream}.
\item[\const{FSETLOCKING\_QUERY}] Restituisce lo stato corrente della modalità
- di blocco dello stream.
+ di blocco dello \textit{stream}.
\end{basedescript}
\itindend{thread}