\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,
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.


\section{Introduzione}
\label{sec:file_stream_intro}

Come visto in \capref{cap:file_unix_interface} le operazioni di I/O sui file
sono gestibili direttamente a basso livello con l'interfaccia standard unix
che ricorre direttamente alle 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,
che vengono a costituire il nucleo essenziale\footnote{queste funzioni sono
  state implementate la prima volta da Ritchie nel 1976 e da allora sono
  rimaste sostanzialmente immutate.} delle \acr{glibc}.


\subsection{I \textit{file stream}}
\label{sec:file_stream}

Come più volte ribadito l'interfaccia dei file descriptor è una interfaccia di
basso livello, che non provvede nessuna forma di formattazione dei dati, e
nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.

In \textit{Advanced Programming in the Unix Environment} Stevens esegue un
raffronto dell'influenza delle dimensioni del blocco di dati (il parametro
\param{buf} di \func{read} e \func{write}) nell'efficienza nelle operazioni di
I/O con i file descriptor, evidenziando come le prestazioni ottimali si
ottengano quando il buffer dei dati ha la stessa dimensione dei blocchi del
filesystem (il valore dato dal campo \var{st\_blksize} di \var{fstat}).

In questo caso se il programmatore non si cura di effettuare le operazioni in
blocchi di dimensioni adeguate, le prestazioni possono deteriorarsi in maniera
evidente. L'interfaccia degli stream provvede da sola la gestione dei dettagli
della bufferizzazione e dell'esecuzione delle operazioni di lettura e
scrittura effettive 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 di
gestire i dettagli della comunicazione con il tipo di hardware sottostante, ed
esso può essere sempre considerato come composto da un flusso (da cui il nome
\textit{stream}) continuo di dati.

Ma a parte le particolarità della gestione delle operazioni di lettura e
scrittura, i file stream restano del tutto equivalenti ai file descriptor sui
quali sono basati, ed in particolare vale quanto visto in
\secref{sec:file_sharing} a proposito dell'accesso condiviso ed in
\secref{sec:file_access_control} per il controllo di accesso.


\subsection{Gli oggetti \type{FILE}}
\label{sec:file_FILE}

Per ragioni storiche la struttura di dati che rappresenta un 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 questo motivo gli utenti non devono mai utilizzare direttamente o allocare
queste strutture, ma usare sempre puntatori del tipo \type{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 parametri
solo variabili di questo tipo, che diventa accessibile includendo l'header
file \file{stdio.h}.



\subsection{Gli stream standard}
\label{sec:file_std_stream}

Ai tre file descriptor standard (vedi \secref{sec:file_std_descr}) aperti per
ogni processo, corrispondono altrettanti stream predefiniti per ogni processo,
che rappresentano i canali standard di input/output prestabiliti; anche questi
tre stream sono definiti nell'header \file{stdio.h} e sono:

\begin{itemize}
\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 input} 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 input} 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.
\end{itemize}

Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente
tre variabili che possono essere usate come tutte le altre, ad esempio si può
effettuare una redirezione dell'output di un programma con il semplice codice:
\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
    fclose (stdout);
    stdout = fopen ("standard-output-file", "w");
\end{lstlisting}
ma in altri sistemi possono essere definite come macro, e deve essere pertanto
usata \func{freopen}.


\subsection{Le modalità di bufferizzazione}
\label{sec:file_buffering}

La bufferizzazione è una delle caratteristiche principali della 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
una degli aspetti più comunemente fraintesi.

I caratteri che vengono scritti su uno stream normalmente vengono accumulati e
poi trasmessi in blocco in maniera asincrona, e molto spesso lo stesso avviene
anche per la lettura (cioè dal file viene letto un blocco di dati).  Se si sta
facendo dell'input/output interattivo però bisogna tenere presente le
caratteristiche con cui viene effettuata la bufferizzazione, pena il rischio
di non vedere apparire l'output o di ottenere degli effetti indesiderati nella
visualizzazione.

Per questo motivo, la libreria definisce tre distinte modalità di
bufferizzazione, adatte a situazioni diverse, di cui occorre essere ben
consapevoli:
\begin{itemize}
\item \textit{unbuffered}: in questa modalità i caratteri non sono
  bufferizzati e vengono trasmessi individualmente al file non appena
  possibile (effettuando immediatamente una \func{write}).
\item \textit{line unbuffered}: in questo caso i caratteri vengono trasmessi
  al file in blocco ogni volta che viene incontrato un carattere di
  \textit{newline} (il carattere ASCII \verb|\n|).
\item 
\end{itemize}


\section{Funzioni base}
\label{sec:file_ansi_base_func}

Esamineremo in questa sezione le funzioni base dell'interfaccia degli stream,
analoghe a quelle di \secref{} per i file descriptor. In particolare vedremo
come aprire, leggere, scrivere e cambiare la posizione corrente in uno stream.


\subsection{Apertura di uno stream}
\label{sec:file_fopen}


\subsection{Lettura e scrittura su uno stream}
\label{sec:file_io}


\subsection{Posizionamento su uno stream}
\label{sec:file_fseek}


\subsection{Input/output binario}
\label{sec:file_binary_io}


\subsection{Input/output di linea}
\label{sec:file_line_io}


\subsection{Input/output formattato}
\label{sec:file_formatted_io}


\subsection{Chiusura di uno stream}
\label{sec:file_fclose}


\section{Funzioni avanzate}
\label{sec:file_stream_adv_func}


\subsection{Il controllo della bufferizzazione}
\label{sec:file_buffering-ctrl}


\subsection{Dettagli dell'implementazione}
\label{sec:file_stream_details}


\subsection{File temporanei}
\label{sec:file_temp_file}


\subsection{Efficienza}
\label{sec:file_stream_efficiency}









