From: Simone Piccardi Date: Sun, 8 Jan 2012 23:52:00 +0000 (+0000) Subject: Reindicizzazioni varie e riscrittura totale della sezione sul X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=94b4d603807121b40eef06d22d2b6cd6e06ec7fd;p=gapil.git Reindicizzazioni varie e riscrittura totale della sezione sul funzionamento del VFS. Eliminato definitivamente fileintro.tex --- diff --git a/fileadv.tex b/fileadv.tex index 86a0aca..a4692ad 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -24,7 +24,7 @@ controllo più dettagliato delle modalità di I/O. \section{Il \textit{file locking}} \label{sec:file_locking} -\index{file!locking|(} +\itindbeg{file~locking} In sez.~\ref{sec:file_sharing} abbiamo preso in esame le modalità in cui un sistema unix-like gestisce la condivisione dei file da parte di processi @@ -799,7 +799,7 @@ affatto equivalente a \func{flock}). \subsection{Il \textit{mandatory locking}} \label{sec:file_mand_locking} -\itindbeg{mandatory~locking|(} +\itindbeg{mandatory~locking} Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4, per introdurre un \textit{file locking} che, come dice il nome, fosse @@ -890,9 +890,9 @@ soltanto quando si chiama \func{mmap} con l'opzione \const{MAP\_SHARED} (nel qual caso la funzione fallisce con il solito \errcode{EAGAIN}) che comporta la possibilità di modificare il file. -\index{file!locking|)} +\itindend{file~locking} -\itindend{mandatory~locking|(} +\itindend{mandatory~locking} \section{L'\textit{I/O multiplexing}} @@ -1521,7 +1521,7 @@ sono: nel sistema. \item[\errcode{EMFILE}] si è raggiunto il limite sul numero massimo di istanze di \textit{epoll} per utente stabilito da - \procfile{/proc/sys/fs/epoll/max\_user\_instances}. + \sysctlfile{fs/epoll/max\_user\_instances}. \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare l'istanza. \end{errlist} @@ -1576,7 +1576,7 @@ controllare, per questo si deve usare la seconda funzione dell'interfaccia, \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}. \item[\errcode{ENOSPC}] si è raggiunto il limite massimo di registrazioni per utente di file descriptor da osservare imposto da - \procfile{/proc/sys/fs/epoll/max\_user\_watches}. + \sysctlfile{fs/epoll/max\_user\_watches}. \end{errlist} } \end{prototype} @@ -2560,8 +2560,8 @@ diventati attivi. L'unico modo per essere sicuri che questo non avvenga è di impostare la lunghezza della coda dei segnali real-time ad una dimensione identica al valore massimo del numero di file descriptor utilizzabili.\footnote{vale a dire impostare il contenuto di - \procfile{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di - \procfile{/proc/sys/fs/file-max}.} + \sysctlfile{kernel/rtsig-max} allo stesso valore del contenuto di + \sysctlfile{fs/file-max}.} % TODO fare esempio che usa O_ASYNC @@ -2613,7 +2613,7 @@ partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}. -\index{file!lease|(} +\itindbeg{file~lease} La prima di queste funzionalità è quella del cosiddetto \textit{file lease}; questo è un meccanismo che consente ad un processo, detto \textit{lease @@ -2711,7 +2711,7 @@ operazione di lettura, declassando il \textit{lease} a lettura con Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro il numero di secondi specificato dal parametro di sistema mantenuto in -\procfile{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o +\sysctlfile{fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per evitare che un processo blocchi indefinitamente l'accesso ad un file acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato @@ -2745,7 +2745,7 @@ come in precedenza, si potrà ottenere nel gestore del segnale il file descriptor che è stato modificato tramite il contenuto della struttura \struct{siginfo\_t}. -\index{file!lease|)} +\itindend{file~lease} \begin{table}[htb] \centering @@ -2857,7 +2857,7 @@ effettuate le operazioni di notifica;\footnote{per evitare abusi delle risorse di sistema è previsto che un utente possa utilizzare un numero limitato di istanze di \textit{inotify}; il valore di default del limite è di 128, ma questo valore può essere cambiato con \func{sysctl} o usando il file - \procfile{/proc/sys/fs/inotify/max\_user\_instances}.} si tratta di un file + \sysctlfile{fs/inotify/max\_user\_instances}.} si tratta di un file descriptor speciale che non è associato a nessun file su disco, e che viene utilizzato solo per notificare gli eventi che sono stati posti in osservazione. Dato che questo file descriptor non è associato a nessun file o @@ -2918,7 +2918,7 @@ modalità della stessa. L'operazione può essere ripetuta per tutti i file e le directory che si vogliono tenere sotto osservazione,\footnote{anche in questo caso c'è un limite massimo che di default è pari a 8192, ed anche questo valore può essere cambiato con \func{sysctl} o usando il file - \procfile{/proc/sys/fs/inotify/max\_user\_watches}.} e si utilizzerà sempre + \sysctlfile{fs/inotify/max\_user\_watches}.} e si utilizzerà sempre un solo file descriptor. Il tipo di evento che si vuole osservare deve essere specificato @@ -3152,7 +3152,7 @@ aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di \end{table} \footnotetext{la coda di notifica ha una dimensione massima specificata dal - parametro di sistema \procfile{/proc/sys/fs/inotify/max\_queued\_events} che + parametro di sistema \sysctlfile{fs/inotify/max\_queued\_events} che indica il numero massimo di eventi che possono essere mantenuti sulla stessa; quando detto valore viene ecceduto gli ulteriori eventi vengono scartati, ma viene comunque generato un evento di tipo diff --git a/filedir.tex b/filedir.tex index 281f818..514705b 100644 --- a/filedir.tex +++ b/filedir.tex @@ -19,12 +19,12 @@ illustrando le principali caratteristiche di un filesystem e le interfacce che consentono di controllarne il montaggio e lo smontaggio. Esamineremo poi le funzioni di libreria che si usano per copiare, spostare e -cambiare i nomi di file e directory ed esamineremo l'interfaccia che permette -la manipolazione dei loro attributi. Tratteremo inoltre la struttura di base -del sistema delle protezioni e del controllo dell'accesso ai file e le -successive estensioni (\textit{Extended Attributes}, ACL, quote disco, -\textit{capabilities}). Tutto quello che riguarda invece la manipolazione del -contenuto dei file è lasciato ai capitoli successivi. +cambiare i nomi di file e directory e l'interfaccia che permette la +manipolazione dei loro attributi. Tratteremo inoltre la struttura di base del +sistema delle protezioni e del controllo dell'accesso ai file e le successive +estensioni (\textit{Extended Attributes}, ACL, quote disco, +\textit{capabilities}). Tutto quello che riguarda invece la gestione dell'I/O +sui file è lasciato al capitolo successivo. @@ -35,8 +35,8 @@ In questa sezione tratteremo con maggiori dettagli rispetto a quanto visto in sez.~\ref{sec:file_arch_overview} il \textit{Virtual File System} di Linux e come il kernel può gestire diversi tipi di filesystem, descrivendo prima le caratteristiche generali di un filesystem di un sistema unix-like, per poi -trattare in maniera un po' più dettagliata il filesystem più usato con Linux, -l'\acr{ext2} (e derivati). +fare una panoramica sul filesystem più usato con Linux, l'\acr{ext2} ed i suoi +successori. \subsection{Il funzionamento del \textit{Virtual File System} di Linux} @@ -51,96 +51,237 @@ Come illustrato brevemente in sez.~\ref{sec:file_arch_overview} in Linux il concetto di \textit{everything is a file} è stato implementato attraverso il \textit{Virtual File System}, la cui struttura generale è illustrata in fig.~\ref{fig:file_VFS_scheme}. Il VFS definisce un insieme di funzioni che -tutti i filesystem devono implementare. L'interfaccia comprende tutte le -funzioni che riguardano i file e le operazioni sono suddivise su tre tipi di -oggetti: \textit{filesystem}, \itindex{inode} \textit{inode} e \textit{file}, -corrispondenti a tre apposite strutture definite nel kernel. +tutti i filesystem devono implementare per l'accesso ai file che contengono e +l'interfaccia che consente di eseguire l'I/O sui file, che questi siano di +dati o dispositivi. + +L'interfaccia fornita dal VFS comprende in sostanza tutte le funzioni che +riguardano i file, le operazioni implementate dal VFS sono realizzate con una +astrazione che prevede quattro tipi di oggetti strettamente correlati: i +filesystem, le \textit{dentry}, gli \textit{inode} ed i file. A questi oggetti +corrispondono una serie di apposite strutture definite dal kernel che +contengono come campi le funzioni di gestione e realizzano l'infrastruttura +del VFS. L'interfaccia è estremamente complessa, ne faremo pertanto una +trattazione estremamente semplificata che consenta di comprenderne i principi +difunzionamento. Il VFS usa una tabella mantenuta dal kernel che contiene il nome di ciascun -filesystem supportato: quando si vuole inserire il supporto di un nuovo +filesystem supportato, quando si vuole inserire il supporto di un nuovo filesystem tutto quello che occorre è chiamare la funzione -\code{register\_filesystem} passandole un'apposita struttura -\code{file\_system\_type} che contiene i dettagli per il riferimento -all'implementazione del medesimo, che sarà aggiunta alla citata tabella. - -In questo modo quando viene effettuata la richiesta di montare un nuovo disco -o di qualunque altro dispositivo che può contenere un filesystem, il VFS può -ricavare dalla citata tabella il puntatore alle funzioni da chiamare nelle -operazioni di montaggio. Queste sono responsabili inizializzare tutte le -variabili interne e restituire uno speciale descrittore dei filesystem montati -al VFS; attraverso quest'ultimo diventa possibile accedere alle funzioni -specifiche per l'uso di quel filesystem. - -Il primo oggetto usato dal VFS è il descrittore di filesystem (o -\textit{filesystem descriptor}), un puntatore ad una apposita struttura che -contiene vari dati come le informazioni comuni ad ogni filesystem, i dati -privati relativi a quel filesystem specifico, e i puntatori alle funzioni del -kernel relative al filesystem. Il VFS può così usare le funzioni contenute nel -\textit{filesystem descriptor} per accedere alle funzioni specifiche di quel +\code{register\_filesystem} passando come argomento la struttura +\kstruct{file\_system\_type} (la cui definizione è riportata in +fig.~\ref{fig:kstruct_file_system_type}) relativa a quel filesystem. Questa +verrà inserita nella tabella, ed il nuovo filesystem comparirà in +\procfile{/proc/filesystems}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/file_system_type.h} + \end{minipage} + \normalsize + \caption{Estratto della struttura \kstructd{file\_system\_type} usata dal + VFS (da \texttt{include/linux/fs.h}).} + \label{fig:kstruct_file_system_type} +\end{figure} + +La struttura \kstruct{file\_system\_type}, oltre ad una serie di dati interni, +come il nome del tipo di filesystem nel campo \var{name},\footnote{quello che + viene riportato in \procfile{/proc/filesystems} e che viene usato come + parametro dell'opzione \texttt{-t} del comando \texttt{mount}.} contiene i +riferimenti alle funzioni di base che consentono l'utilizzo di quel +filesystem. In particolare la funzione \code{mount} del quarto campo è quella +che verrà invocata tutte le volte che si dovrà effettuare il montaggio di un +filesystem di quel tipo. Per ogni nuovo filesystem si dovrà allocare una di +queste strutture ed inizializzare i relativi campi con i dati specifici diquel +filesystem, ed in particolare si dovra creare anche la relativa versione della +funzione \code{mount}. + +Come illustrato in fig.~\ref{fig:kstruct_file_system_type} questa funzione +restituisce una \textit{dentry}, abbreviazione che sta per \textit{directory + entry}. Le \textit{dentry} sono gli oggetti che il kernel usa per eseguire +la \textit{pathname resolution}, ciascuna di esse corrisponde ad un +\textit{pathname} e contiene il riferimento ad un \textit{inode}, che come +vedremo a breve è l'oggetto usato dal kernel per identificare un un +file.\footnote{in questo caso si parla di file come di un qualunque oggetto + generico che sta sul filesystem.} La \textit{dentry} ottenuta dalla chiamata +alla funzione \code{mount} sarà inserita in corrispondenza al +\textit{pathname} della directory in cui il filesystem è stato montato. + +% NOTA: struct dentry è dichiarata in include/linux/dcache.h + +Le \textit{dentry} sono oggetti del VFS che vivono esclusivamente in memoria, +nella cosiddetta \textit{directory entry cache} (spesso chiamata in breve +\textit{dcache}). Ogni volta che una \textit{system call} specifica un +\textit{pathname} viene effettuata una ricerca nella \textit{dcache} per +ottenere immediatamente la \textit{dentry} corrispondente,\footnote{il buon + funzionamento della \textit{dcache} è in effetti di una delle parti più + critiche per le prestazioni del sistema.} che a sua ci darà, tramite +l'\textit{inode}, il riferimento al file. + +Dato che normalmente non è possibile mantenere nella \textit{dcache} le +informazioni relative a tutto l'albero dei file la procedura della +\textit{pathname resolution} richiede un meccanismo con cui riempire gli +eventuali vuoti. Il meccanismo prevede che tutte le volte che si arriva ad una +\textit{dentry} mancante venga invocata la funzione \texttt{lookup} dell'inode +associato alla \textit{dentry} precedente nella risoluzione del +\textit{pathname},\footnote{che a questo punto è una directory, per cui si può + cercare al suo interno il nome di un file.} il cui scopo è risolvere il nome +mancante e fornire la sua \textit{dentry} che a questo punto verrà inserita +nella cache. + +Dato che tutte le volte che si monta un filesystem la funzione \texttt{mount} +della corrispondente \kstruct{file\_system\_type} inserisce la \textit{dentry} +iniziale nel \itindex{mount~point} \textit{mount point} dello stesso si avrà +comunque un punto di partenza. Inoltre essendo questa \textit{dentry} relativa +a quel tipo di filesystem essa farà riferimento ad un \textit{inode} di quel +filesystem, e come vedremo questo farà sì che venga eseguita una +\texttt{lookup} adatta per effettuare la risoluzione dei nomi per quel filesystem. -Gli altri due descrittori usati dal VFS sono relativi agli altri due oggetti -su cui è strutturata l'interfaccia. Ciascuno di essi contiene le informazioni -relative al file in uso, insieme ai puntatori alle funzioni dello specifico -filesystem usate per l'accesso dal VFS. In particolare il descrittore -\itindex{inode} dell'\textit{inode} contiene i puntatori alle funzioni che -possono essere usate su qualunque file (come \func{link}, \func{stat} e -\func{open}), mentre il descrittore di file contiene i puntatori alle funzioni -che vengono usate sui file già aperti. - -La funzione più importante implementata dal VFS è la \textit{system call} -\func{open} che permette di aprire un file. Dato un \itindex{pathname} -\textit{pathname} viene eseguita una ricerca dentro la \textit{directory entry - cache} (in breve \textit{dcache}), una tabella che contiene tutte le -\textit{directory entry} (in breve \textit{dentry}) che permette di associare -in maniera rapida ed efficiente il \textit{pathname} a una specifica -\textit{dentry}. - -Una singola \textit{dentry} contiene in genere il puntatore ad un -\itindex{inode} \textit{inode}; quest'ultimo è la struttura base che sta sul -disco e che identifica un singolo oggetto del VFS sia esso un file ordinario, -una directory, un link simbolico, una FIFO, un file di -\index{file!di~dispositivo} dispositivo, o una qualsiasi altra cosa che possa -essere rappresentata dal VFS (i tipi di file riportati in -tab.~\ref{tab:file_file_types}). A ciascuno di essi è associata pure una -struttura che sta in memoria, e che, oltre alle informazioni sullo specifico -file, contiene anche il riferimento alle funzioni (i \textsl{metodi} del VFS) -da usare per poterlo manipolare. - -Le \textit{dentry} ``vivono'' in memoria e non vengono mai salvate su disco, -vengono usate per motivi di velocità, gli \itindex{inode} \textit{inode} invece -stanno su disco e vengono copiati in memoria quando serve, ed ogni cambiamento -viene copiato all'indietro sul disco (aggiornando i cosiddetti -\textsl{metadati} del file), gli \itindex{inode} inode che stanno in memoria -sono \itindex{inode} inode del VFS ed è ad essi che puntano le singole -\textit{dentry}. - -La \textit{dcache} costituisce perciò una sorta di vista completa di tutto -l'albero dei file, ovviamente per non riempire tutta la memoria questa vista è -parziale (la \textit{dcache} cioè contiene solo le \textit{dentry} per i file -per i quali è stato richiesto l'accesso), quando si vuole risolvere un nuovo -\itindex{pathname} \textit{pathname} il VFS deve creare una nuova -\textit{dentry} e caricare \itindex{inode} l'inode corrispondente in memoria. - -Questo procedimento viene eseguito dal metodo \code{lookup()} \itindex{inode} -dell'inode della directory che contiene il file; questo viene installato nelle -relative strutture in memoria quando si effettua il montaggio lo specifico -filesystem su cui l'inode va a vivere. - -Una volta che il VFS ha a disposizione la \textit{dentry} (ed il relativo -\textit{inode}) diventa possibile accedere alle varie operazioni sul file come -la \func{open} per aprire il file o la \func{stat} per leggere i dati -\itindex{inode} dell'inode e passarli in user space. - -L'apertura di un file richiede comunque un'altra operazione, l'allocazione di -una struttura di tipo \struct{file} in cui viene inserito un puntatore alla -\textit{dentry} e una struttura \struct{f\_ops} che contiene i puntatori ai -metodi che implementano le operazioni disponibili sul file. In questo modo i -processi in \textit{user space} possono accedere alle operazioni attraverso -detti metodi, che saranno diversi a seconda del tipo di file (o dispositivo) -aperto (su questo torneremo in dettaglio in sez.~\ref{sec:file_fd}). Un elenco -delle operazioni previste dal kernel è riportato in -tab.~\ref{tab:file_file_operations}. +% Un secondo effetto della chiamata funzione \texttt{mount} di +% \kstruct{file\_system\_type} è quello di allocare una struttura +% \kstruct{super\_block} per ciascuna istanza montata, che contiene le +% informazioni generali di un qualunque filesystem montato, come le opzioni di +% montaggio, le dimensioni dei blocchi, quando il filesystem è stato montato +% ecc. Fra queste però viene pure inserta, nel campo \var{s\_op}, una ulteriore +% struttura \kstruct{super\_operations}, il cui contenuto sono i puntatori +% alle funzioni di gestione di un filesystem, anche inizializzata in modo da +% utilizzare le versioni specifiche di quel filesystem. + +L'oggetto più importante per il funzionamento del VFS è probabilmente +l'\textit{inode}, ma con questo nome si può fare riferimento a due cose +diverse. La prima è la struttura su disco (su cui torneremo anche in +sez.~\ref{sec:file_filesystem}) che fa parte della organizzazione dei dati +realizzata dal filesystem e che contiene le informazioni relative alle +proprietà (i cosiddetti \textsl{metadati}) di ogni oggetto presente su di esso +(si intende al solito uno qualunque dei tipi di file di +tab.~\ref{tab:file_file_types}). + +La seconda è la corrispondente struttura \kstruct{inode}, della cui +definizione si è riportato un estratto in +fig.~\ref{fig:kstruct_inode}.\footnote{l'estratto fa riferimento alla versione + del kernel 2.6.37.} Questa struttura viene mantenuta in memoria ed è a +questa che facevamo riferimento quando parlavamo dell'\textit{inode} associato +a ciascuna \textit{dentry}. Nella struttura in memoria sono presenti gli +stessi \textsl{metadati} memorizzati su disco, che vengono letti quando questa +struttura viene allocata e trascritti all'indietro se modificati. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/inode.h} + \end{minipage} + \normalsize + \caption{Estratto della struttura \kstructd{inode} del kernel (da + \texttt{include/linux/fs.h}).} + \label{fig:kstruct_inode} +\end{figure} + +Il fatto che la struttura \kstruct{inode} sia mantenuta in memoria, +direttamente associata ad una \textit{dentry}, rende sostanzialmente immediate +le operazioni che devono semplicemente effettuare un accesso ai dati in essa +contenuti: è così ad esempio che viene realizzata la \textit{system call} +\func{stat} che vedremo in sez.~\ref{sec:file_stat}. Rispetto ai dati salvati +sul disco questa struttura contiene però anche quanto necessario alla +implementazione del VFS, ed in particolare è importante il campo \var{i\_op} +che, come illustrato in fig.~\ref{fig:kstruct_inode}, contiene il puntatore ad +una struttura di tipo \kstruct{inode\_operation}, la cui definizione si può +trovare nel file \texttt{include/kernel/fs.h} dei sorgenti del kernel. + +Questa struttura non è altro che una tabella di funzioni, ogni suo membro cioè +è un puntatore ad una funzione, e, come suggerisce il nome della struttura +stessa, queste funzioni, le principali delle quali sono riportate in +tab.~\ref{tab:file_inode_operations}) sono quelle che definiscono le +operazioni che il VFS può compiere su un \textit{inode}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Funzione} & \textbf{Operazione} \\ + \hline + \hline + \textsl{\code{create}} & Chiamata per creare un nuovo file (vedi + sez.~\ref{sec:file_open}).\\ + \textsl{\code{link}} & Crea un \textit{hard link} (vedi + sez.~\ref{sec:file_link}).\\ + \textsl{\code{unlink}} & Cancella un \textit{hard link} (vedi + sez.~\ref{sec:file_link}).\\ + \textsl{\code{symlink}}& Crea un link simbolico (vedi + sez.~\ref{sec:file_symlink}).\\ + \textsl{\code{mkdir}} & Crea una directory (vedi + sez.~\ref{sec:file_dir_creat_rem}).\\ + \textsl{\code{rmdir}} & Rimuove una directory (vedi + sez.~\ref{sec:file_dir_creat_rem}).\\ + \textsl{\code{mknod}} & Crea un file speciale (vedi + sez.~\ref{sec:file_mknod}).\\ + \textsl{\code{rename}} & Cambia il nome di un file (vedi + sez.~\ref{sec:file_remove}).\\ + \textsl{\code{lookup}}& Risolve il nome di un file.\\ + \hline + \end{tabular} + \caption{Le principali operazioni sugli \textit{inode} definite tramite + \kstruct{inode\_operation}.} + \label{tab:file_inode_operations} +\end{table} + +Possiamo notare come molte di queste funzioni abbiano nomi sostanzialmente +identici alle varie \textit{system call} con le quali si gestiscono file e +directory che tratteremo nel resto del capitolo. Quello che succede è che +tutte le volte che deve essere eseguita una \textit{system call}, o una +qualunque altra operazione su un \textit{inode} (come \texttt{lookup}) il VFS +andrà ad utilizzare la funzione corrispondente attraverso il puntatore +\var{i\_op}. + +Sarà allora sufficiente che nella realizzazione di un filesystem si crei una +opportuna istanza di \kstruct{inode\_operation} contenente i puntatori alla +implementazione di queste funzioni per quel filesystem e quel punto le +strutture \kstruct{inode} usate per gli oggetti di quel filesystem otterranno +il puntatore a detta istanza di \kstruct{inode\_operation} e verranno +automaticamente usate le funzioni corrette. + +Si noti però come in tab.~\ref{tab:file_inode_operations} non sia presente la +funzione \texttt{open} che invece è citata in +tab.~\ref{tab:file_file_operations}.\footnote{essa può essere comunque + invocata dato che nella struttura \kstruct{inode} è presente anche il + puntatore \func{i\_fop} alla struttura \kstruct{file\_operation} che + fornisce detta funzione.} Questo avviene perché su Linux l'apertura di un +file richiede comunque un'altra operazione: l'allocazione di una struttura di +tipo \kstruct{file} che viene associata ad ogni file aperto nel sistema. + +I motivi per cui viene usata una struttura a parte sono diversi, anzitutto, +come illustrato in sez.~\ref{sec:file_fd}, questa è necessaria per le +operazioni eseguite dai processi con l'interfaccia dei file descriptor; ogni +processo infatti mantiene il riferimento ad una struttura \kstruct{file} per +ogni file che ha aperto, ed è tramite essa che esegue le operazioni di I/O. + +Inoltre se le operazioni relative agli \textit{inode} fanno riferimento ad +oggetti posti all'interno di un filesystem e vi si applicano quindi le +funzioni fornite nell'implementazione di quest'ultimo, quando si apre un file +questo può essere anche un file di dispositivo, ed in questo caso il VFS +invece di usare le operazioni fornite dal filesystem (come farebbe per un file +di dati) dovrà invece ricorrere a quelle fornite dal driver del dispositivo. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/file.h} + \end{minipage} + \normalsize + \caption{Estratto della struttura \kstructd{file} del kernel (da + \texttt{include/linux/fs.h}).} + \label{fig:kstruct_file} +\end{figure} + +Come si può notare dall'estratto di fig.~\ref{fig:kstruct_file}, la struttura +contiene, oltre ad alcune informazioni usate dall'interfaccia dei file +descriptor il cui significato emergerà più avanti, il puntatore \struct{f\_op} +ad una struttura \kstruct{file\_operation}. Questa è l'analoga per i file di +\kstruct{inode\_operation}, e definisce le operazioni generiche fornite dal +VFS per i file. Si sono riportate in tab.~\ref{tab:file_file_operations} le +più significative. \begin{table}[htb] \centering @@ -172,21 +313,30 @@ tab.~\ref{tab:file_file_operations}. sez.~\ref{sec:file_asyncronous_io}) sul file.\\ \hline \end{tabular} - \caption{Operazioni sui file definite nel VFS.} + \caption{Operazioni sui file definite tramite \kstruct{file\_operation}.} \label{tab:file_file_operations} \end{table} -In questo modo per ciascun file diventano possibili una serie di operazioni -(non è detto che tutte siano disponibili), che costituiscono l'interfaccia -astratta del VFS. Qualora se ne voglia eseguire una, il kernel andrà ad -utilizzare l'opportuna funzione dichiarata in \struct{f\_ops} appropriata al -tipo di file in questione. - -Pertanto è possibile scrivere allo stesso modo sulla porta seriale come su un -normale file di dati; ovviamente certe operazioni (nel caso della seriale ad -esempio la \code{seek}) non saranno disponibili, però con questo sistema -l'utilizzo di diversi filesystem (come quelli usati da Windows o MacOS) è -immediato e relativamente trasparente per l'utente ed il programmatore. +Anche in questo caso tutte le volte che deve essere eseguita una +\textit{system call} o una qualunque altra operazione sul file il VFS andrà ad +utilizzare la funzione corrispondente attraverso il puntatore +\var{f\_op}. Dato che è cura del VFS quando crea la struttura all'apertura del +file, assegnare a \var{f\_op} il puntatore alla versione di +\kstruct{file\_operation} corretta per quel file, sarà possibile scrivere allo +stesso modo sulla porta seriale come su un normale file di dati, e lavorare +sui file allo stesso modo indipendentemente dal filesystem. + +Il VFS realizza la quasi totalità delle operazioni relative ai file grazie +alle funzioni presenti nelle due strutture \kstruct{inode\_operation} +\kstruct{file\_operation}. Ovviamente non è detto che tutte le operazioni +possibili siano poi disponibili in tutti i casi, ad esempio una \code{seek} +non è realizzabile per un dispositivo come la porta seriale o per una fifo, +mentre sui file del filesystem \texttt{vfat} non sono disponibili i permessi, +ma resta il fatto che grazie al VFS le \textit{system call} per le operazioni +sui file restano sempre le stesse nonostante le enormi differenze che possono +esserci negli oggetti a cui si applicano. + + \itindend{Virtual~File~System} @@ -197,22 +347,24 @@ Come già accennato in sez.~\ref{sec:file_arch_overview} Linux (ed ogni sistema unix-like) organizza i dati che tiene su disco attraverso l'uso di un filesystem. Una delle caratteristiche di Linux rispetto agli altri Unix è quella di poter supportare, grazie al VFS, una enorme quantità di filesystem -diversi, ognuno dei quali ha una sua particolare struttura e funzionalità -proprie. Per questo per il momento non entreremo nei dettagli di un -filesystem specifico, ma daremo una descrizione a grandi linee che si adatta -alle caratteristiche comuni di qualunque filesystem di un sistema unix-like. +diversi, ognuno dei quali avrà una sua particolare struttura e funzionalità +proprie. Per questo non entreremo nei dettagli di un filesystem specifico, ma +daremo una descrizione a grandi linee che si adatta alle caratteristiche +comuni di qualunque filesystem di un sistema unix-like. Lo spazio fisico di un disco viene usualmente diviso in partizioni; ogni -partizione può contenere un filesystem. La strutturazione tipica +partizione può contenere un filesystem. Una possibile strutturazione dell'informazione su un disco è riportata in fig.~\ref{fig:file_disk_filesys}, -in essa si fa riferimento alla struttura del filesystem \acr{ext2}, che -prevede una separazione dei dati in \textit{block group} che replicano il -cosiddetto \textit{superblock} (ma sulle caratteristiche di \acr{ext2} e -derivati torneremo in sez.~\ref{sec:file_ext2}). È comunque caratteristica -comune di tutti i filesystem per Unix, indipendentemente da come poi viene -strutturata nei dettagli questa informazione, prevedere una divisione fra la -lista degli \itindex{inode} inode e lo spazio a disposizione per i dati e le -directory. +in essa per semplicità si è fatto riferimento alla struttura del filesystem +\acr{ext2}, che prevede una separazione dei dati in \textit{block group} che +replicano il cosiddetto \textit{superblock} (sulle caratteristiche di +\acr{ext2} e derivati torneremo in sez.~\ref{sec:file_ext2}). È comunque +caratteristica comune di tutti i filesystem per Unix, indipendentemente da +come poi viene strutturata nei dettagli questa informazione, prevedere una +divisione fra la lista degli \itindex{inode} \textit{inode} e lo spazio a +disposizione per i dati e le directory.\footnote{questo non è del tutto vero + per filesystem evoluti come \textsl{btrfs}, ma per il momento limitiamoci + alla implementazione classica.} \begin{figure}[!htb] \centering @@ -223,9 +375,9 @@ directory. \end{figure} Se si va ad esaminare con maggiore dettaglio la strutturazione -dell'informazione all'interno del singolo filesystem (tralasciando i dettagli +dell'informazione all'interno del singolo filesystem, tralasciando i dettagli relativi al funzionamento del filesystem stesso come la strutturazione in -gruppi dei blocchi, il superblock e tutti i dati di gestione) possiamo +gruppi dei blocchi, il superblock e tutti i dati di gestione possiamo esemplificare la situazione con uno schema come quello esposto in fig.~\ref{fig:file_filesys_detail}. @@ -248,11 +400,12 @@ particolare è opportuno ricordare sempre che: cosiddetti \textsl{metadati}) riguardanti il file: il tipo di file, i permessi di accesso, le dimensioni, i puntatori ai blocchi fisici che contengono i dati e così via. Le informazioni che la funzione \func{stat} - fornisce provengono dall'\textit{inode}; dentro una directory si troverà - solo il nome del file e il numero \itindex{inode} dell'\textit{inode} ad esso - associato, cioè quella che da qui in poi chiameremo una \textsl{voce} (come - traduzione dell'inglese \textit{directory entry}, che non useremo anche per - evitare confusione con le \textit{dentry} del kernel di cui si parlava in + (vedi sez.~\ref{sec:file_stat}) fornisce provengono dall'\textit{inode}. + Dentro una directory si troverà solo il nome del file e il numero + \itindex{inode} dell'\textit{inode} ad esso associato, cioè quella che da + qui in poi chiameremo una \textsl{voce} (come traduzione dell'inglese + \textit{directory entry}, che non useremo anche per evitare confusione con + le \textit{dentry} del kernel di cui si parlava in sez.~\ref{sec:file_vfs_work}). \item Come mostrato in fig.~\ref{fig:file_filesys_detail} si possono avere più @@ -260,10 +413,10 @@ particolare è opportuno ricordare sempre che: contatore che contiene il numero di riferimenti che sono stati fatti ad esso (il cosiddetto \textit{link count}); solo quando questo contatore si annulla i dati del file vengono effettivamente rimossi dal disco. Per questo la - funzione per cancellare un file si chiama \func{unlink}, ed in realtà non - cancella affatto i dati del file, ma si limita ad eliminare la relativa voce - da una directory e decrementare il numero di riferimenti \itindex{inode} - nell'\textit{inode}. + funzione per cancellare un file si chiama \func{unlink} (vedi + sez.~\ref{sec:file_link}), ed in realtà non cancella affatto i dati del + file, ma si limita ad eliminare la relativa voce da una directory e + decrementare il numero di riferimenti \itindex{inode} nell'\textit{inode}. \item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode} nello stesso filesystem e non ci può essere una directory che contiene @@ -275,9 +428,10 @@ particolare è opportuno ricordare sempre che: del file non viene spostato fisicamente, viene semplicemente creata una nuova voce per \itindex{inode} l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità in cui opera normalmente il comando \cmd{mv} - attraverso la funzione \func{rename}). Questa operazione non modifica - minimamente neanche l'\textit{inode} del file dato che non si opera su - questo ma sulla directory che lo contiene. + attraverso la funzione \func{rename}, vedi + sez.~\ref{sec:file_remove}). Questa operazione non modifica minimamente + neanche l'\textit{inode} del file dato che non si opera su questo ma sulla + directory che lo contiene. \item Gli \textit{inode} dei file, che contengono i \textsl{metadati} ed i blocchi di spazio disco, che contengono i dati, sono risorse indipendenti ed @@ -452,8 +606,9 @@ sulla directory \param{target}. \item[\errcode{EINVAL}] il device \param{source} presenta un \textit{superblock} non valido, o si è cercato di rimontare un filesystem non ancora montato, o di montarlo senza che \param{target} sia un - \textit{mount point} o di spostarlo quando \param{target} non è un - \textit{mount point} o è \file{/}. + \itindex{mount~point} \textit{mount point} o di spostarlo + quando \param{target} non è un \itindex{mount~point} \textit{mount point} + o è \file{/}. \item[\errcode{EACCES}] non si ha il permesso di accesso su uno dei componenti del \itindex{pathname} \textit{pathname}, o si è cercato di montare un filesystem disponibile in sola lettura senza averlo @@ -467,11 +622,11 @@ sulla directory \param{target}. \errval{ENAMETOOLONG}, \errval{ENOENT} o \errval{ELOOP}.} \end{prototype} -La funzione monta sulla directory \param{target}, detta \textit{mount point}, -il filesystem contenuto in \param{source}. In generale un filesystem è -contenuto su un disco, e l'operazione di montaggio corrisponde a rendere -visibile al sistema il contenuto del suddetto disco, identificato attraverso -il file di dispositivo ad esso associato. +La funzione monta sulla directory \param{target}, detta \itindex{mount~point} +\textit{mount point}, il filesystem contenuto in \param{source}. In generale +un filesystem è contenuto su un disco, e l'operazione di montaggio corrisponde +a rendere visibile al sistema il contenuto del suddetto disco, identificato +attraverso il file di dispositivo ad esso associato. Ma la struttura del \textit{Virtual File System} vista in sez.~\ref{sec:file_vfs_work} è molto più flessibile e può essere usata anche @@ -488,14 +643,15 @@ indicato uno dei filesystem virtuali, il contenuto di \param{source} viene ignorato. Dopo l'esecuzione della funzione il contenuto del filesystem viene resto -disponibile nella directory specificata come \textit{mount point}, il -precedente contenuto di detta directory viene mascherato dal contenuto della -directory radice del filesystem montato. +disponibile nella directory specificata come \itindex{mount~point} +\textit{mount point}, il precedente contenuto di detta directory viene +mascherato dal contenuto della directory radice del filesystem montato. Dal kernel 2.4.x inoltre è divenuto possibile sia spostare atomicamente un -\textit{mount point} da una directory ad un'altra, sia montare in diversi -\textit{mount point} lo stesso filesystem, sia montare più filesystem sullo -stesso \textit{mount point} (nel qual caso vale quanto appena detto, e solo il +\itindex{mount~point} \textit{mount point} da una directory ad un'altra, sia +montare in diversi \itindex{mount~point} \textit{mount point} lo stesso +filesystem, sia montare più filesystem sullo stesso \itindex{mount~point} +\textit{mount point} (nel qual caso vale quanto appena detto, e solo il contenuto dell'ultimo filesystem montato sarà visibile). Ciascun filesystem è dotato di caratteristiche specifiche che possono essere @@ -504,12 +660,12 @@ disponibili in ogni filesystem), e vengono specificate come opzioni di montaggio con l'argomento \param{mountflags}. In Linux \param{mountflags} deve essere un intero a 32 bit i cui 16 più -significativi sono un \textit{magic number}\footnote{cioè un numero speciale - usato come identificativo, che nel caso è \code{0xC0ED}; si può usare la - costante \const{MS\_MGC\_MSK} per ottenere la parte di \param{mountflags} - riservata al \textit{magic number}.} mentre i 16 meno significativi sono -usati per specificare le opzioni; essi sono usati come maschera binaria e -vanno impostati con un OR aritmetico della costante \const{MS\_MGC\_VAL} con i +significativi sono un \itindex{magic~number} \textit{magic + number}\footnote{che nel caso è \code{0xC0ED}, si può usare la costante + \const{MS\_MGC\_MSK} per ottenere la parte di \param{mountflags} riservata + al \textit{magic number}.} mentre i 16 meno significativi sono usati per +specificare le opzioni; essi sono usati come maschera binaria e vanno +impostati con un OR aritmetico della costante \const{MS\_MGC\_VAL} con i valori riportati in tab.~\ref{tab:sys_mount_flags}. \begin{table}[htb] @@ -586,14 +742,14 @@ montato e non il file o il dispositivo che è stato montato,\footnote{questo è separate e la funzione poteva essere usata anche specificando il file di dispositivo.} in quanto con il kernel 2.4.x è possibile montare lo stesso dispositivo in più punti. Nel caso più di un filesystem sia stato montato -sullo stesso \textit{mount point} viene smontato quello che è stato montato -per ultimo. +sullo stesso \itindex{mount~point} \textit{mount point} viene smontato quello +che è stato montato per ultimo. Si tenga presente che la funzione fallisce quando il filesystem è \textsl{occupato}, questo avviene quando ci sono ancora file aperti sul filesystem, se questo contiene la directory di lavoro corrente di un qualunque -processo o il mount point di un altro filesystem; in questo caso l'errore -restituito è \errcode{EBUSY}. +processo o il \itindex{mount~point} \textit{mount point} di un altro +filesystem; in questo caso l'errore restituito è \errcode{EBUSY}. Linux provvede inoltre una seconda funzione, \funcd{umount2}, che in alcuni casi permette di forzare lo smontaggio di un filesystem, anche quando questo @@ -735,7 +891,8 @@ diretto, o \textit{hard link}. Il prototipo della funzione è il seguente: errore nel qual caso \var{errno} viene impostata ai valori: \begin{errlist} \item[\errcode{EXDEV}] i file \param{oldpath} e \param{newpath} non fanno - riferimento ad un filesystem montato sullo stesso \textit{mount point}. + riferimento ad un filesystem montato sullo stesso \itindex{mount~point} + \textit{mount point}. \item[\errcode{EPERM}] il filesystem che contiene \param{oldpath} e \param{newpath} non supporta i link diretti o è una directory. \item[\errcode{EEXIST}] un file (o una directory) di nome \param{newpath} @@ -765,9 +922,9 @@ supportare i collegamenti diretti (il meccanismo non è disponibile ad esempio con il filesystem \acr{vfat} di Windows). In realtà la funzione ha un ulteriore requisito, e cioè che non solo che i due file siano sullo stesso filesystem, ma anche che si faccia riferimento ad essi sullo stesso -\textit{mount point}.\footnote{si tenga presente infatti (vedi - sez.~\ref{sec:sys_file_config}) che a partire dal kernel 2.4 uno stesso - filesystem può essere montato più volte su directory diverse.} +\itindex{mount~point} \textit{mount point}.\footnote{si tenga presente infatti + (vedi sez.~\ref{sec:sys_file_config}) che a partire dal kernel 2.4 uno + stesso filesystem può essere montato più volte su directory diverse.} La funzione inoltre opera sia sui file ordinari che sugli altri oggetti del filesystem, con l'eccezione delle directory. In alcune versioni di Unix solo @@ -944,7 +1101,7 @@ nello stesso filesystem) si usa invece la funzione \funcd{rename},\footnote{la non vuota. \item[\errcode{EBUSY}] o \param{oldpath} o \param{newpath} sono in uso da parte di qualche processo (come directory di lavoro o come radice) o del - sistema (come mount point). + sistema (come \itindex{mount~point} \textit{mount point}). \item[\errcode{EINVAL}] \param{newpath} contiene un prefisso di \param{oldpath} o più in generale si è cercato di creare una directory come sotto-directory di se stessa. @@ -2307,13 +2464,13 @@ riportato in tab.~\ref{tab:file_type_macro}. \textbf{Macro} & \textbf{Tipo del file} \\ \hline \hline - \macro{S\_ISREG(m)} & file normale.\\ - \macro{S\_ISDIR(m)} & directory.\\ - \macro{S\_ISCHR(m)} & dispositivo a caratteri.\\ - \macro{S\_ISBLK(m)} & dispositivo a blocchi.\\ - \macro{S\_ISFIFO(m)} & fifo.\\ - \macro{S\_ISLNK(m)} & link simbolico.\\ - \macro{S\_ISSOCK(m)} & socket.\\ + \macro{S\_ISREG}\texttt{(m)} & file normale.\\ + \macro{S\_ISDIR}\texttt{(m)} & directory.\\ + \macro{S\_ISCHR}\texttt{(m)} & dispositivo a caratteri.\\ + \macro{S\_ISBLK}\texttt{(m)} & dispositivo a blocchi.\\ + \macro{S\_ISFIFO}\texttt{(m)} & fifo.\\ + \macro{S\_ISLNK}\texttt{(m)} & link simbolico.\\ + \macro{S\_ISSOCK}\texttt{(m)} & socket.\\ \hline \end{tabular} \caption{Macro per i tipi di file (definite in \texttt{sys/stat.h}).} @@ -5366,7 +5523,7 @@ casistica assai complessa. Per i kernel fino al 2.6.25, o se non si attiva il supporto per le \textit{file capabilities}, il \textit{capabilities bounding set} è un parametro generale di sistema, il cui valore viene riportato nel file -\procfile{/proc/sys/kernel/cap-bound}. Il suo valore iniziale è definito in +\sysctlfile{kernel/cap-bound}. Il suo valore iniziale è definito in sede di compilazione del kernel, e da sempre ha previsto come default la presenza di tutte le \textit{capabilities} eccetto \const{CAP\_SETPCAP}. In questa situazione solo il primo processo eseguito nel sistema (quello con @@ -5391,7 +5548,7 @@ tutti, compreso l'amministratore.\footnote{la qual cosa, visto il default Con il kernel 2.6.25 e le \textit{file capabilities} il \textit{bounding set} è diventato una proprietà di ciascun processo, che viene propagata invariata sia attraverso una \func{fork} che una \func{exec}. In questo caso il file -\procfile{/proc/sys/kernel/cap-bound} non esiste e \texttt{init} non ha nessun +\sysctlfile{kernel/cap-bound} non esiste e \texttt{init} non ha nessun ruolo speciale, inoltre in questo caso all'avvio il valore iniziale prevede la presenza di tutte le capacità (compresa \const{CAP\_SETPCAP}). @@ -5627,7 +5784,7 @@ che è opportuno dettagliare maggiormente. \begin{table}[!h!btp] \centering \footnotesize - \begin{tabular}{|l|p{11.9cm}|} + \begin{tabular}{|l|p{10.5cm}|} \hline \textbf{Capacità}&\textbf{Descrizione}\\ \hline @@ -5695,7 +5852,7 @@ che è opportuno dettagliare maggiormente. intercomunicazione fra processi (vedi sez.~\ref{sec:ipc_sysv}).\\ \const{CAP\_LEASE} & La capacità di creare dei \textit{file lease} - \index{file!lease} (vedi + \itindex{file~lease} (vedi sez.~\ref{sec:file_asyncronous_lease}) pur non essendo proprietari del file (dal kernel 2.4).\\ @@ -5827,7 +5984,7 @@ sez.~\ref{sec:socket_credential_xxx}), assegnare classi privilegiate (\const{IOPRIO\_CLASS\_RT} e prima del kernel 2.6.25 anche \const{IOPRIO\_CLASS\_IDLE}) per lo scheduling dell'I/O (vedi sez.~\ref{sec:io_priority}), superare il limite di sistema sul numero massimo -di file aperti,\footnote{quello indicato da \procfile{/proc/sys/fs/file-max}.} +di file aperti,\footnote{quello indicato da \sysctlfile{fs/file-max}.} effettuare operazioni privilegiate sulle chiavi mantenute dal kernel (vedi sez.~\ref{sec:keyctl_management}), usare la funzione \func{lookup\_dcookie}, usare \const{CLONE\_NEWNS} con \func{unshare} e \func{clone}, (vedi diff --git a/fileintro.tex b/fileintro.tex deleted file mode 100644 index 9951291..0000000 --- a/fileintro.tex +++ /dev/null @@ -1,33 +0,0 @@ -%% fileintro.tex -%% -%% Copyright (C) 2000-2011 Simone Piccardi. Permission is granted to -%% copy, distribute and/or modify this document under the terms of the GNU Free -%% Documentation License, Version 1.1 or any later version published by the -%% Free Software Foundation; with the Invariant Sections being "Prefazione", -%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the -%% license is included in the section entitled "GNU Free Documentation -%% License". -%% - -%\chapter{L'architettura dei file} -%\label{cha:file_intro} - -% capitolo eliminato, inglobando altrove - -% LocalWords: everything is device kernel filesystem sez pathname root glibc -% LocalWords: path filename bootloader proc name components fifo socket dev LF -% LocalWords: resolution chroot parent Virtual System like tab cap l'I regular -% LocalWords: inode symbolic char block VFS VMS Windows dell'I raw access Mac -% LocalWords: CR dos HFS l'XFS SGI magic number descriptor system call int ext -% LocalWords: nell'header unistd stream dall'ANSI stdio locking POSIX fig type -% LocalWords: register superblock dell'inode stat entry cache dcache dentry ln -% LocalWords: l'inode lookup ops read write llseek ioctl readdir poll nell'I -% LocalWords: multiplexing mmap fsync fasync seek group dall' dell' img -% LocalWords: count unlink nell' rename gapil second Tb attributes BSD SVr gid -% LocalWords: sgid append only log fs linux extented linked list third MacOS - - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "gapil" -%%% End: diff --git a/filestd.tex b/filestd.tex index 9d1c689..8645c5d 100644 --- a/filestd.tex +++ b/filestd.tex @@ -38,7 +38,7 @@ costituire il nucleo\footnote{queste funzioni sono state implementate la prima \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 @@ -54,10 +54,10 @@ dimensioni dei settori fisici in cui è suddiviso il disco. 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 @@ -68,41 +68,41 @@ cui il nome \textit{stream}) di dati. 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è il \textit{file @@ -132,13 +132,14 @@ usare la funzione \func{freopen}. \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 @@ -153,9 +154,9 @@ scritte, e non quelle ancora presenti nel buffer. 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 @@ -187,9 +188,9 @@ altro dispositivo interattivo) ed in modalità \textit{fully buffered} 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à @@ -200,10 +201,11 @@ dalle librerie sono fisse, se le si eccedono si può avere uno scarico dei dati 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 @@ -214,16 +216,16 @@ dei dati. \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: @@ -232,9 +234,9 @@ Le funzioni che si possono usare per aprire uno stream sono solo tre: \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 @@ -247,22 +249,22 @@ Le funzioni che si possono usare per aprire uno stream sono solo tre: \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 @@ -273,16 +275,20 @@ aperti con le funzioni delle librerie standard del C. \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 @@ -295,8 +301,8 @@ aperti con le funzioni delle librerie standard del C. \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} @@ -326,9 +332,10 @@ opportune funzioni di conversione in lettura e scrittura. 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 @@ -352,13 +359,14 @@ usare una delle funzioni \func{fseek}, \func{fsetpos} o \func{rewind}. Anche 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 @@ -369,16 +377,16 @@ Uno stream viene chiuso con la funzione \funcd{fclose} il cui prototipo è: 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} @@ -390,13 +398,13 @@ operazione dopo aver chiuso i file e prima di uscire (si ricordi quanto 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}. @@ -408,7 +416,7 @@ modalità di input/output non formattato: \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 @@ -416,10 +424,10 @@ intero (di tipo \ctyp{int}) \val{EOF}\footnote{la costante deve essere 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 @@ -428,13 +436,12 @@ infatti non basta, dato che quest'ultimo potrebbe essere stato impostato in 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)} @@ -447,8 +454,8 @@ questi due flag possono essere riletti dalle funzioni \funcd{feof} e \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 è: @@ -459,7 +466,7 @@ 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} @@ -507,10 +514,10 @@ differenza è che le funzioni non ritornano il numero di byte scritti, 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 @@ -542,7 +549,7 @@ eventuali differenze. 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} @@ -555,7 +562,7 @@ sez.~\ref{sec:file_stream_thread} per i dettagli), i loro prototipi sono: 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}. @@ -653,7 +660,7 @@ Come nel caso dell'I/O binario con \func{fread} e \func{fwrite} le \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} @@ -676,7 +683,7 @@ valore -1 da una condizione di errore che restituisce \val{EOF}. 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. @@ -687,7 +694,7 @@ disponibile per una lettura successiva; la funzione che inverte la 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.} @@ -828,9 +835,9 @@ Come per l'I/O binario e quello a caratteri, anche per l'I/O di linea le \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é @@ -887,9 +894,9 @@ e per evitare \itindex{memory~leak} \textit{memory leak} occorre ricordarsi di 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. @@ -950,9 +957,9 @@ motivo si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo 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 @@ -1088,9 +1095,9 @@ manuale di \func{printf} e nella documentazione delle \acr{glibc}. \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} @@ -1110,9 +1117,10 @@ sez.~\ref{sec:proc_variadic}), sono \funcd{vprintf}, \funcd{vfprintf} e \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). @@ -1158,11 +1166,11 @@ la stringa non serve più, onde evitare \itindex{memory~leak} \textit{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 \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 @@ -1194,23 +1202,24 @@ 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 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 @@ -1229,40 +1238,40 @@ facile utilizzare uno strumento come \cmd{flex}\footnote{il programma 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 @@ -1270,14 +1279,14 @@ descriptor, e gli argomenti, a parte il tipo, hanno lo stesso significato; in 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 @@ -1285,7 +1294,7 @@ cui prototipo è: 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 @@ -1296,10 +1305,11 @@ può non essere possibile lo standard POSIX ha introdotto le nuove funzioni \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.} @@ -1319,9 +1329,9 @@ sistemi più moderni. \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} @@ -1329,11 +1339,11 @@ impliciti per la programmazione \itindex{thread} \textit{multi-thread}. 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 @@ -1342,17 +1352,18 @@ il prototipo della funzione è: \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)} @@ -1364,9 +1375,9 @@ puntatore allo stream; questo può essere evitato con le due funzioni \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} @@ -1380,31 +1391,32 @@ servono a tale scopo, il loro prototipo è: \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 @@ -1418,13 +1430,14 @@ sistema passandone alla funzione l'indirizzo in \param{buf} e la dimensione 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 +\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 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). +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 @@ -1462,8 +1475,8 @@ specifichi la modalità non bufferizzata i valori di \param{buf} e \param{size} 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} @@ -1475,7 +1488,7 @@ e \funcd{setlinebuf}; i loro prototipi sono: 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 @@ -1483,7 +1496,7 @@ e \funcd{setlinebuf}; i loro prototipi sono: 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} @@ -1499,7 +1512,8 @@ scelta, si può forzare lo scarico dei dati sul file con la funzione \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 è @@ -1512,14 +1526,14 @@ scelta, si può forzare lo scarico dei dati sul file con la funzione 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 @@ -1531,7 +1545,7 @@ Infine esistono anche circostanze in cui si vuole scartare tutto l'output 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.} @@ -1547,82 +1561,86 @@ compresi gli eventuali caratteri rimandati indietro con \func{ungetc}. \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} diff --git a/fileunix.tex b/fileunix.tex index dad3b0f..4003f95 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -14,7 +14,7 @@ Esamineremo in questo capitolo la prima delle due interfacce di programmazione -per i file, quella dei \index{file!descriptor} \textit{file descriptor}, +per i file, quella dei \itindex{file~descriptor} \textit{file descriptor}, nativa di Unix. Questa è l'interfaccia di basso livello provvista direttamente dalle system call, che non prevede funzionalità evolute come la bufferizzazione o funzioni di lettura o scrittura formattata, e sulla quale è @@ -35,7 +35,7 @@ tutte le implementazione di un sistema unix-like. \subsection{L'architettura dei \textit{file descriptor}} \label{sec:file_fd} -\index{file!descriptor|(} +\itindbeg{file~descriptor} Per poter accedere al contenuto di un file occorre creare un canale di comunicazione con il kernel che renda possibile operare su di esso (si ricordi @@ -61,11 +61,11 @@ un elenco dei processi attivi nella cosiddetta \itindex{process~table} La \itindex{process~table} \textit{process table} è una tabella che contiene una voce per ciascun processo attivo nel sistema. In Linux ciascuna voce è -costituita da una struttura di tipo \struct{task\_struct} nella quale sono +costituita da una struttura di tipo \kstruct{task\_struct} nella quale sono raccolte tutte le informazioni relative al processo; fra queste informazioni c'è anche il puntatore ad una ulteriore struttura di tipo -\struct{files\_struct}, in cui sono contenute le informazioni relative ai file -che il processo ha aperto, ed in particolare: +\kstruct{files\_struct}, in cui sono contenute le informazioni relative ai +file che il processo ha aperto, ed in particolare: \begin{itemize*} \item i flag relativi ai file descriptor. \item il numero di file aperti. @@ -99,8 +99,6 @@ Ritorneremo su questo schema più volte, dato che esso è fondamentale per capire i dettagli del funzionamento dell'interfaccia dei \textit{file descriptor}. -\index{file!descriptor|)} - \begin{figure}[!htb] \centering \includegraphics[width=13cm]{img/procfile} @@ -109,6 +107,7 @@ capire i dettagli del funzionamento dell'interfaccia dei \textit{file \label{fig:file_proc_file} \end{figure} +\itindend{file~descriptor} \subsection{I file standard} @@ -121,7 +120,7 @@ stato chiuso nessuno in precedenza). In tutti i sistemi unix-like esiste una convenzione generale per cui ogni processo viene lanciato dalla shell con almeno tre file aperti. Questi, per -quanto appena detto, avranno come \index{file!descriptor} \textit{file +quanto appena detto, avranno come \itindex{file~descriptor} \textit{file descriptor} i valori 0, 1 e 2. Benché questa sia soltanto una convenzione, essa è seguita dalla gran parte delle applicazioni, e non aderirvi potrebbe portare a gravi problemi di interoperabilità. @@ -167,7 +166,7 @@ stesso \itindex{inode} inode). Nelle vecchie versioni di Unix (ed anche in Linux fino al kernel 2.0.x) il numero di file aperti era anche soggetto ad un limite massimo dato dalle dimensioni del vettore di puntatori con cui era realizzata la tabella dei file -descriptor dentro \struct{file\_struct}; questo limite intrinseco nei kernel +descriptor dentro \kstruct{files\_struct}; questo limite intrinseco nei kernel più recenti non sussiste più, dato che si è passati da un vettore ad una lista, ma restano i limiti imposti dall'amministratore (vedi sez.~\ref{sec:sys_limits}). @@ -191,7 +190,7 @@ usando direttamente le system call del kernel. La funzione \funcd{open} è la funzione fondamentale per accedere ai file, ed è quella che crea l'associazione fra un \itindex{pathname} \textit{pathname} ed -un \index{file!descriptor} file descriptor, il suo prototipo è: +un \itindex{file~descriptor} file descriptor, il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/stat.h} @@ -475,7 +474,7 @@ descriptor ritorna disponibile; il suo prototipo è: \end{prototype} La chiusura di un file rilascia ogni blocco (il \textit{file locking} -\index{file!locking} è trattato in sez.~\ref{sec:file_locking}) che il +\itindex{file~locking} è trattato in sez.~\ref{sec:file_locking}) che il processo poteva avere acquisito su di esso; se \param{fd} è l'ultimo riferimento (di eventuali copie) ad un file aperto, tutte le risorse nella \itindex{file~table} \textit{file table} vengono rilasciate. Infine se il file @@ -917,7 +916,7 @@ problema, quando si andrà a scrivere le operazioni potranno mescolarsi in maniera imprevedibile. Il sistema però fornisce in alcuni casi la possibilità di eseguire alcune operazioni di scrittura in maniera coordinata anche senza utilizzare meccanismi di sincronizzazione più complessi (come il -\index{file!locking} \textit{file locking}, che esamineremo in +\itindex{file~locking} \textit{file locking}, che esamineremo in sez.~\ref{sec:file_locking}). Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui @@ -992,7 +991,7 @@ valore tradizionale, usato da BSD, per l'update dei dati è ogni 30 secondi, ma in Linux il valore utilizzato è di 5 secondi; con le nuove versioni\footnote{a partire dal kernel 2.2.8} poi, è il kernel che si occupa direttamente di tutto quanto attraverso il demone interno \cmd{bdflush}, il cui comportamento -può essere controllato attraverso il file \procfile{/proc/sys/vm/bdflush} (per +può essere controllato attraverso il file \sysctlfile{vm/bdflush} (per il significato dei valori si può leggere la documentazione allegata al kernel in \file{Documentation/sysctl/vm.txt}). @@ -1376,7 +1375,7 @@ descriptor, che non riguardano la normale lettura e scrittura di dati, ma la gestione sia delle loro proprietà, che di tutta una serie di ulteriori funzionalità che il kernel può mettere a disposizione.\footnote{ad esempio si gestiscono con questa funzione varie modalità di I/O asincrono (vedi - sez.~\ref{sec:file_asyncronous_operation}) e il \index{file!locking} + sez.~\ref{sec:file_asyncronous_operation}) e il \itindex{file~locking} \textit{file locking} (vedi sez.~\ref{sec:file_locking}).} Per queste operazioni di manipolazione e di controllo delle varie proprietà e @@ -1498,7 +1497,7 @@ per \var{cmd} è riportata di seguito: (come vedremo in sez.~\ref{sec:file_asyncronous_io}).\footnote{i due comandi \const{F\_SETSIG} e \const{F\_GETSIG} sono una estensione specifica di Linux.} -\item[\const{F\_SETLEASE}] imposta o rimuove un \index{file!lease} +\item[\const{F\_SETLEASE}] imposta o rimuove un \itindex{file~lease} \textit{file lease}\footnote{questa è una nuova funzionalità, specifica di Linux, e presente solo a partire dai kernel della serie 2.4.x, in cui il processo che detiene un \textit{lease} su un file riceve una notifica @@ -1508,7 +1507,7 @@ per \var{cmd} è riportata di seguito: valore nullo in caso di successo o $-1$ in caso di errore. Questa funzionalità avanzata è trattata in dettaglio in sez.~\ref{sec:file_asyncronous_lease}. -\item[\const{F\_GETLEASE}] restituisce il tipo di \index{file!lease} +\item[\const{F\_GETLEASE}] restituisce il tipo di \itindex{file~lease} \textit{file lease} che il processo detiene nei confronti del file descriptor \var{fd} o $-1$ in caso di errore. Con questo comando il terzo argomento può essere omesso. Questa funzionalità avanzata è trattata in @@ -1528,7 +1527,7 @@ pertanto riprese più avanti quando affronteremo le problematiche ad esse relative. In particolare le tematiche relative all'I/O asincrono e ai vari meccanismi di notifica saranno trattate in maniera esaustiva in sez.~\ref{sec:file_asyncronous_access} mentre quelle relative al -\index{file!locking} \textit{file locking} saranno esaminate in +\itindex{file~locking} \textit{file locking} saranno esaminate in sez.~\ref{sec:file_locking}). L'uso di questa funzione con i socket verrà trattato in sez.~\ref{sec:sock_ctrl_func}. diff --git a/gapil.tex b/gapil.tex index 7f41e17..b237d38 100644 --- a/gapil.tex +++ b/gapil.tex @@ -168,7 +168,6 @@ hyperfootnotes=false]{hyperref} \include{intro} \include{process} \include{prochand} -%\include{fileintro} \include{filedir} \include{fileunix} \include{filestd} diff --git a/intro.tex b/intro.tex index 9ebfc9b..1e9423b 100644 --- a/intro.tex +++ b/intro.tex @@ -382,23 +382,24 @@ attraverso un'interfaccia astratta che tratta le periferiche allo stesso modo dei normali file di dati. In questa sezione forniremo una descrizione a grandi linee dell'architettura -della gestione file in Linux, partendo da una introduzione ai concetti di -base, per poi illustrare l'organizzazione di file e directory, i tipi di file -concludendo con una panoramica sulle caratteristiche principali delle -interfacce con cui i processi accedono ai file. +della gestione dei file in Linux, partendo da una introduzione ai concetti di +base, per poi illustrare la struttura dell'albero dei file ed il significato +dei tipi di file, concludendo con una panoramica sulle caratteristiche +principali delle due interfacce con cui i processi possono effettuare l'I/O su +file. \subsection{Una panoramica generale} \label{sec:file_arch_overview} Per poter accedere ai file, il kernel deve mettere a disposizione dei -programmi delle opportune interfacce che consentano di leggerne il -contenuto. Questo ha due aspetti: il primo è che il kernel, per il concetto -dell'\textit{everything is a file}, deve fornire una interfaccia che consenta -di operare sui file, sia che questi corrispondano ai normali file di dati, sia -che siano quei file speciali (i cosiddetti \index{file!di~dispositivo} file di -dispositivo, o \textit{device file}) che permettono di accedere alle -periferiche. +programmi delle opportune \textit{system call} che consentano di leggere e +scrivere il contenuto. Tutto ciò ha due aspetti: il primo è che il kernel, per +il concetto dell'\textit{everything is a file}, deve fornire una interfaccia +che consenta di operare sui file, sia che questi corrispondano ai normali file +di dati, sia che siano quei file speciali (i cosiddetti +\index{file!di~dispositivo} file di dispositivo, o \textit{device file}) che +permettono di accedere alle periferiche. Il secondo aspetto è che per poter utilizzare dei normali file di dati il kernel deve provvedere ad organizzare e rendere accessibile in maniera @@ -410,27 +411,30 @@ disponibile ai processi attraverso quello che viene chiamato il ``\textsl{montaggio}'' del filesystem nell'albero dei file, dove il contenuto sarà accessibile nella forma ordinaria di file e directory. +\itindbeg{Virtual~File~System} + In Linux il concetto di \textit{everything is a file} è stato implementato attraverso il \textit{Virtual File System} (che da qui in poi abbrevieremo in VFS) che è uno strato intermedio che il kernel usa per accedere ai più -svariati filesystem mantenendo la stessa interfaccia per i programmi in user -space. +svariati filesystem mantenendo la stessa interfaccia per i programmi in +\textit{user space}. -Il VFS fornisce cioè quel livello di indirezione che permette di collegare le +Il VFS fornisce cioè quel livello di astrazione che permette di collegare le operazioni interne del kernel per la manipolazione sui file con le -\textit{system call} relative alle operazioni di I/O, e gestisce -l'organizzazione dette operazioni nei vari modi in cui i diversi filesystem le -effettuano, permettendo la coesistenza di filesystem differenti all'interno +\textit{system call} relative alle operazioni di I/O, e gestisce poi +l'organizzazione di dette operazioni nei vari modi in cui i diversi filesystem +le effettuano, permettendo la coesistenza di filesystem differenti all'interno dello stesso albero delle directory. Torneremo su questa interfaccia generica -fornita dal \textit{Virtual File System} in sez.~\ref{sec:file_vfs_work}. +fornita dal VFS in sez.~\ref{sec:file_vfs_work}. -In sostanza quando un processo esegue una \textit{system call} che opera su un -file, il kernel chiama sempre una funzione implementata nel VFS; la funzione -eseguirà le manipolazioni sulle strutture generiche e utilizzerà poi la -chiamata alle opportune funzioni del filesystem specifico a cui si fa -riferimento. Saranno queste a chiamare le funzioni di più basso livello che -eseguono le operazioni di I/O sul dispositivo fisico, secondo lo schema -riportato in fig.~\ref{fig:file_VFS_scheme}. +In sostanza quello che accade è che quando un processo esegue una +\textit{system call} che opera su un file, il kernel chiama sempre una +funzione implementata nel VFS; la funzione eseguirà le manipolazioni sulle +strutture generiche e utilizzerà poi la chiamata alle opportune funzioni del +filesystem specifico a cui si fa riferimento. Saranno queste a chiamare le +funzioni di più basso livello che eseguono le operazioni di I/O sul +dispositivo fisico, secondo lo schema riportato in +fig.~\ref{fig:file_VFS_scheme}. \begin{figure}[!htb] \centering @@ -445,13 +449,15 @@ di dispositivo, solo che in questo caso invece di usare il codice del filesystem che accede al disco, il \textit{Virtual File System} eseguirà direttamente il codice del kernel che permette di accedere alla periferica. -Come accennato all'inizio una delle funzioni essenziali per il funzionamento -dell'interfaccia dei file è quella che consente di montare un filesystem -nell'albero dei file, e rendere così visibili i suoi contenuti. In un sistema -unix-like infatti, a differenza di quanto avviene in altri sistemi operativi, -tutti i file vengono mantenuti all'interno di un unico albero la cui radice -(quella che viene chiamata \textit{root directory}) viene montata all'avvio -direttamente dal kernel. +\itindend{Virtual~File~System} + +Come accennato in precedenza una delle funzioni essenziali per il +funzionamento dell'interfaccia dei file è quella che consente di montare un +filesystem nell'albero dei file, e rendere così visibili i suoi contenuti. In +un sistema unix-like infatti, a differenza di quanto avviene in altri sistemi +operativi, tutti i file vengono mantenuti all'interno di un unico albero la +cui radice (quella che viene chiamata \textit{root directory}) viene montata +all'avvio direttamente dal kernel. Come accennato in sez.~\ref{sec:intro_kern_and_sys}) montare la radice è, insieme al lancio di \cmd{init},\footnote{l'operazione è ovviamente anche @@ -464,7 +470,8 @@ viene posto alla radice dell'albero dei file. Tutti gli ulteriori filesystem che possono essere disponibili su altri dispositivi dovranno a loro volta essere inseriti nell'albero, montandoli su -altrettante directory del filesystem radice. Questo comunque avverrà sempre in +altrettante directory del filesystem radice, su quelli che vengono chiamati +\index{mount~point} \textit{mount point}. Questo comunque avverrà sempre in un secondo tempo, in genere a cura dei programmi eseguiti nella procedura di inizializzazione del sistema, grazie alle funzioni che tratteremo in sez.~\ref{sec:sys_file_config}. @@ -475,27 +482,26 @@ sez.~\ref{sec:sys_file_config}. \itindbeg{pathname} -Come appena illustrato sez.~\ref{sec:file_arch_overview} una delle -caratteristiche distintive di un sistema unix-like è quella di avere un unico -albero dei file. Un file deve essere identificato dall'utente usando quello -che viene chiamato il suo \textit{pathname},\footnote{il manuale della - \acr{glibc} depreca questa nomenclatura, che genererebbe confusione poiché - \textit{path} indica anche un insieme di directory su cui effettuare una - ricerca (come quello in cui la shell cerca i comandi). Al suo posto viene - proposto l'uso di \textit{filename} e di componente per il nome del file - all'interno della directory. Non seguiremo questa scelta dato che l'uso - della parola \textit{pathname} è ormai così comune che mantenerne l'uso è - senz'altro più chiaro dell'alternativa proposta.} vale a dire tramite il -percorso che si deve fare per accedere al file a partire da una certa -``\textit{directory}''. - -Una directory, come vedremo in maggior dettaglio in -sez.~\ref{sec:file_vfs_work}, è anch'essa un file (è cioè un oggetto di un -filesystem), solo che è un file speciale che il kernel riconosce appunto come -directory. Il suo scopo è quello di contenere una lista di nomi di file e le -informazioni che associano ciascun nome al suo contenuto. - -Dato che questi nomi possono corrispondere ad un qualunque oggetto del +Come illustrato sez.~\ref{sec:file_arch_overview} una delle caratteristiche +distintive di un sistema unix-like è quella di avere un unico albero dei +file. Un file deve essere identificato dall'utente usando quello che viene +chiamato il suo \textit{pathname},\footnote{il manuale della \acr{glibc} + depreca questa nomenclatura, che genererebbe confusione poiché \textit{path} + indica anche un insieme di directory su cui effettuare una ricerca (come + quello in cui la shell cerca i comandi). Al suo posto viene proposto l'uso + di \textit{filename} e di componente per il nome del file all'interno della + directory. Non seguiremo questa scelta dato che l'uso della parola + \textit{pathname} è ormai così comune che mantenerne l'uso è senz'altro più + chiaro dell'alternativa proposta.} vale a dire tramite il percorso che si +deve fare per accedere al file a partire da una certa ``\textit{directory}''. + +Una directory in realta è anch'essa un file, nel senso che è anch'essa un +oggetto di un filesystem, solo che è un file particolare che il kernel +riconosce appositamente come tale per poterlo utilizzare come directory. Il +suo scopo è quello di contenere una lista di nomi di file e le informazioni +che associano ciascuno di questi nomi al relativo contenuto. + +Dato che questi nomi possono corrispondere ad un qualunque altro oggetto del filesystem, compresa un'altra directory, si ottiene naturalmente un'organizzazione ad albero inserendo nomi di directory dentro altre directory. All'interno dello stesso albero si potranno poi inserire anche @@ -536,12 +542,12 @@ ricerca parte dalla directory di lavoro corrente del processo (su cui torneremo in sez.~\ref{sec:file_work_dir}) ed il \textit{pathname} è detto \itindsub{pathname}{relativo} \textsl{pathname relativo}. -Infine nomi di directory ``\file{.}'' e ``\file{..}'' hanno un significato +Infine i nomi di directory ``\file{.}'' e ``\file{..}'' hanno un significato speciale e vengono inseriti in ogni directory quando questa viene creata (vedi sez.~\ref{sec:file_dir_creat_rem}). Il primo fa riferimento alla directory corrente e il secondo alla directory \textsl{genitrice} (o \textit{parent directory}) cioè la directory che contiene il riferimento alla directory -corrente. +corrente. In questo modo con ``\file{..}'' si può usare un \textsl{pathname relativo} per indicare un file posto al di sopra della directory corrente, tornando @@ -603,12 +609,12 @@ completo in tab.~\ref{tab:file_file_types}. Si tenga ben presente che questa classificazione non ha nulla a che fare con una classificazione dei file in base al tipo loro del contenuto, dato che in -tal caso si avrebbe a che fare sempre e solo con dei file di dati, e neanche -con le eventuali diverse modalità con cui si potrebbe accedere al contenuto. -La classificazione di tab.~\ref{tab:file_file_types} riguarda invece il tipo -di oggetti gestiti dal \itindex{Virtual~File~System} \textit{Virtual File - System}, ed è da notare la presenza dei cosiddetti file -``\textsl{speciali}''. +tal caso si avrebbe a che fare sempre e solo con dei file di dati. E non ha +niente a che fare neanche con le eventuali diverse modalità con cui si +potrebbe accedere al contenuto dei file di dati. La classificazione di +tab.~\ref{tab:file_file_types} riguarda il tipo di oggetti gestiti dal +\itindex{Virtual~File~System} \textit{Virtual File System}, ed è da notare la +presenza dei cosiddetti file ``\textsl{speciali}''. Alcuni di essi, come le \textit{fifo} (che tratteremo in sez.~\ref{sec:ipc_named_pipe}) ed i \textit{socket} (che tratteremo in @@ -616,19 +622,20 @@ cap.~\ref{cha:socket_intro}) non sono altro che dei riferimenti per utilizzare alcune funzionalità di comunicazione fornite dal kernel. Gli altri sono proprio quei \index{file!di~dispositivo} \textsl{file di dispositivo} che costituiscono una interfaccia diretta per leggere e scrivere sui dispositivi -fisici. Anche se finora li abbiamo messi insieme essi sono tradizionalmente -suddivisi in due grandi categorie, \textsl{a blocchi} e \textsl{a caratteri} a -seconda delle modalità in cui il dispositivo sottostante effettua le -operazioni di I/O. +fisici. Anche se finora li abbiamo chiamati genericamente così, essi sono +tradizionalmente suddivisi in due grandi categorie, \textsl{a blocchi} e +\textsl{a caratteri} a seconda delle modalità in cui il dispositivo +sottostante effettua le operazioni di I/O. I dispositivi a blocchi (ad esempio i dischi) sono quelli corrispondono a periferiche per le quali è richiesto che l'I/O venga effettuato per blocchi di -dati di dimensioni fissate (ad esempio le dimensioni di un settore), mentre i -dispositivi a caratteri sono quelli per cui l'I/O può essere effettuato senza -nessuna particolare struttura. +dati di dimensioni fissate (nel caso dei dischi le dimensioni di un settore), +mentre i dispositivi a caratteri sono quelli per cui l'I/O può essere +effettuato senza nessuna particolare struttura, ed in generale anche un byte +alla volta, da cui il nome. -Una delle differenze principali con altri sistemi operativi (come il VMS o -Windows) è che per Unix tutti i file di dati sono identici e contengono un +Una delle differenze principali con altri sistemi operativi come il VMS o +Windows è che per Unix tutti i file di dati sono identici e contengono un flusso continuo di byte. Non esiste cioè differenza per come vengono visti dal sistema file di diverso contenuto o formato, come nel caso di quella fra file di testo e binari che c'è in Windows. Non c'è neanche una strutturazione a @@ -667,7 +674,7 @@ questo tipo avviene sempre in \textit{user-space}. Gli unici file di cui il kernel deve essere in grado di capire il contenuto sono i binari dei programmi, per i quali sono supportati solo alcuni formati, anche se oggi viene usato quasi esclusivamente l'ELF.\footnote{il nome è l'acronimo di - \textit{Executable and Linkable Format} un formato per eseguibili binari + \textit{Executable and Linkable Format}, un formato per eseguibili binari molto flessibile ed estendibile definito nel 1995 dal \textit{Tool Interface Standard} che per le sue caratteristiche di non essere legato a nessun tipo di processore o architettura è stato adottato da molti sistemi @@ -678,56 +685,64 @@ del contenuto dei file di dati, molti programmi adottano comunque delle convenzioni per i nomi dei file, ad esempio il codice C normalmente si mette in file con l'estensione \file{.c}. Inoltre una tecnica molto usata per classificare i contenuti da parte dei programmi è quella di utilizzare i primi -4 byte del file per memorizzare un \textit{magic number} che classifichi il -contenuto. Entrambe queste tecniche, per quanto usate ed accettate in maniera -diffusa, restano solo delle convenzioni il cui rispetto è demandato alle -applicazioni stesse. +byte del file per memorizzare un \itindex{magic~number} ``\textit{magic + number}''\footnote{il concetto è quello di un numero intero, solitamente fra + 2 e 10 byte, che identifichi il contenuto seguente, dato che questi sono + anche caratteri è comune trovare espresso tale numero con stringhe come + ``\texttt{\%PDF}'' per i PDF o ``\texttt{\#!}'' per gli script.} che ne +classifichi il contenuto. Entrambe queste tecniche, per quanto usate ed +accettate in maniera diffusa, restano solo delle convenzioni il cui rispetto è +demandato alle applicazioni stesse. \subsection{Le due interfacce per l'accesso ai file} \label{sec:file_io_api} -In Linux le interfacce di programmazione per l'accesso al contenuto dei file -due. La prima è l'interfaccia nativa del sistema, quella che il manuale delle -\textsl{glibc} chiama interfaccia dei descrittori di file (o \textit{file - descriptor}). Si tratta di un'interfaccia specifica dei sistemi unix-like e -fornisce un accesso non bufferizzato. - -L'interfaccia è primitiva ed essenziale, l'accesso viene detto non -bufferizzato in quanto la lettura e la scrittura vengono eseguite chiamando -direttamente le \textit{system call} del kernel (in realtà il kernel effettua -al suo interno alcune bufferizzazioni per aumentare l'efficienza nell'accesso -ai dispositivi). L'accesso viene gestito attraverso i \index{file!descriptor} -\textit{file descriptor} che sono rappresentati da numeri interi (cioè -semplici variabili di tipo \ctyp{int}). L'interfaccia è definita -nell'\textit{header file} \file{unistd.h} e la tratteremo in dettaglio in + +\itindbeg{file~descriptor} + +In Linux le interfacce di programmazione per l'I/O su file due. La prima è +l'interfaccia nativa del sistema, quella che il manuale delle \textsl{glibc} +chiama interfaccia dei ``\textit{file descriptor}'' (in italiano +\textsl{descrittori di file}). Si tratta di un'interfaccia specifica dei +sistemi unix-like che fornisce un accesso non bufferizzato. + +L'interfaccia è essenziale, l'accesso viene detto non bufferizzato in quanto +la lettura e la scrittura vengono eseguite chiamando direttamente le +\textit{system call} del kernel, anche se in realtà il kernel effettua al suo +interno alcune bufferizzazioni per aumentare l'efficienza nell'accesso ai +dispositivi. L'accesso viene gestito attraverso i \textit{file descriptor} che +sono rappresentati da numeri interi (cioè semplici variabili di tipo +\ctyp{int}). L'interfaccia è definita nell'\textit{header file} +\file{unistd.h} e la tratteremo in dettaglio in cap.~\ref{cha:file_unix_interface}. +\itindbeg{file~stream} + La seconda interfaccia è quella che il manuale della \acr{glibc} chiama dei -\index{file!stream} \textit{file stream} o più semplicemente -\textit{stream}.\footnote{in realtà una interfaccia con lo stesso nome è stata - introdotta a livello di kernel negli Unix derivati da \textit{System V}, - come strato di astrazione per file e socket; in Linux questa interfaccia, - che comunque ha avuto poco successo, non esiste, per cui facendo riferimento - agli \index{file!stream} \textit{stream} useremo il significato adottato dal - manuale delle \acr{glibc}.} Essa fornisce funzioni più evolute e un accesso -bufferizzato, controllato dalla implementazione fatta nella \acr{glibc}. -Questa è l'interfaccia standard specificata dall'ANSI C e perciò si trova -anche su tutti i sistemi non Unix. Gli \index{file!stream} \textit{stream} -sono oggetti complessi e sono rappresentati da puntatori ad un opportuna -struttura definita dalle librerie del C, ad essi si accede sempre in maniera -indiretta utilizzando il tipo \type{FILE *}. L'interfaccia è definita -nell'\textit{header file} \file{stdio.h} e la tratteremo in dettaglio nel -cap.~\ref{cha:files_std_interface}. +\textit{file stream} o più semplicemente degli \textit{stream}.\footnote{in + realtà una interfaccia con lo stesso nome è stata introdotta a livello di + kernel negli Unix derivati da \textit{System V}, come strato di astrazione + per file e socket; in Linux questa interfaccia, che comunque ha avuto poco + successo, non esiste, per cui facendo riferimento agli \textit{stream} + useremo il significato adottato dal manuale delle \acr{glibc}.} Essa +fornisce funzioni più evolute e un accesso bufferizzato, controllato dalla +implementazione fatta nella \acr{glibc}. Questa è l'interfaccia standard +specificata dall'ANSI C e perciò si trova anche su tutti i sistemi non +Unix. Gli \textit{stream} sono oggetti complessi e sono rappresentati da +puntatori ad un opportuna struttura definita dalle librerie del C, ad essi si +accede sempre in maniera indiretta utilizzando il tipo \code{FILE *}. +L'interfaccia è definita nell'\textit{header file} \file{stdio.h} e la +tratteremo in dettaglio nel cap.~\ref{cha:files_std_interface}. Entrambe le interfacce possono essere usate per l'accesso ai file come agli altri oggetti del VFS, ma per poter accedere alle operazioni di controllo (descritte in sez.~\ref{sec:file_fcntl} e sez.~\ref{sec:file_ioctl}) su un qualunque tipo di oggetto del VFS occorre usare l'interfaccia standard di Unix -con i \textit{file descriptor}. Allo stesso modo devono essere usati i -\index{file!descriptor} \textit{file descriptor} se si vuole ricorrere a -modalità speciali di I/O come il \index{file!locking} \textit{file locking} o -l'I/O non-bloccante (vedi cap.~\ref{cha:file_advanced}). +con i file descriptor. Allo stesso modo devono essere usati i file descriptor +se si vuole ricorrere a modalità speciali di I/O come il +\itindex{file~locking} \textit{file locking} o l'I/O non-bloccante (vedi +cap.~\ref{cha:file_advanced}). Gli \textit{stream} forniscono un'interfaccia di alto livello costruita sopra quella dei \textit{file descriptor}, che permette di poter scegliere tra @@ -735,24 +750,24 @@ diversi stili di bufferizzazione. Il maggior vantaggio degli \textit{stream} è che l'interfaccia per le operazioni di input/output è molto più ricca di quella dei \textit{file descriptor}, che forniscono solo funzioni elementari per la lettura/scrittura diretta di blocchi di byte. In particolare gli -\index{file!stream} \textit{stream} dispongono di tutte le funzioni di -formattazione per l'input e l'output adatte per manipolare anche i dati in -forma di linee o singoli caratteri. +\textit{stream} dispongono di tutte le funzioni di formattazione per l'input e +l'output adatte per manipolare anche i dati in forma di linee o singoli +caratteri. In ogni caso, dato che gli \textit{stream} sono implementati sopra l'interfaccia standard di Unix, è sempre possibile estrarre il \textit{file - descriptor} da uno \textit{stream} ed eseguirvi operazioni di basso livello, -o associare in un secondo tempo uno \index{file!stream} \textit{stream} ad un -\index{file!descriptor} \textit{file descriptor} per usare l'interfaccia più -ricca. + descriptor} da uno \textit{stream} ed eseguirvi sopra operazioni di basso +livello, o associare in un secondo tempo uno \textit{stream} ad un +\textit{file descriptor} per usare l'interfaccia più sofisticata. In generale, se non necessitano specificatamente le funzionalità di basso -livello, è opportuno usare sempre gli \index{file!stream} \textit{stream} per -la loro maggiore portabilità, essendo questi ultimi definiti nello standard -ANSI C; l'interfaccia con i \index{file!descriptor} \textit{file descriptor} -infatti segue solo lo standard POSIX.1 dei sistemi Unix, ed è pertanto di -portabilità più limitata. +livello, è opportuno usare sempre gli \textit{stream} per la loro maggiore +portabilità, essendo questi ultimi definiti nello standard ANSI C; +l'interfaccia con i \textit{file descriptor} infatti segue solo lo standard +POSIX.1 dei sistemi Unix, ed è pertanto di portabilità più limitata. +\itindend{file~descriptor} +\itindend{file~stream} \section{Gli standard} \label{sec:intro_standard} diff --git a/ipc.tex b/ipc.tex index 5841c54..4b569aa 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1021,8 +1021,8 @@ Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino altri limiti relativi al \textit{SysV IPC}) solo con una ricompilazione del kernel, andando a modificarne la definizione nei relativi header file. A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo - scrivendo sui file \procrelfile{/proc/sys/kernel}{shmmni}, - \procrelfile{/proc/sys/kernel}{msgmni} e \procrelfile{/proc/sys/kernel}{sem} + scrivendo sui file \sysctlrelfile{kernel}{shmmni}, + \sysctlrelfile{kernel}{msgmni} e \sysctlrelfile{kernel}{sem} di \file{/proc/sys/kernel} o con l'uso di \func{sysctl}.} e per ciascuno di essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene incrementato di uno ogni volta che l'oggetto viene cancellato. Quando @@ -1182,9 +1182,9 @@ Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti negli header e corrispondenti alle prime tre costanti riportate in tab.~\ref{tab:ipc_msg_limits}, come accennato però in Linux è possibile modificare questi limiti attraverso l'uso di \func{sysctl} o scrivendo nei -file \procrelfile{/proc/sys/kernel}{msgmax}, -\procrelfile{/proc/sys/kernel}{msgmnb} e -\procrelfile{/proc/sys/kernel}{msgmni} di \file{/proc/sys/kernel/}. +file \sysctlrelfile{kernel}{msgmax}, +\sysctlrelfile{kernel}{msgmnb} e +\sysctlrelfile{kernel}{msgmni} di \file{/proc/sys/kernel/}. \begin{figure}[!htb] \centering \includegraphics[width=13cm]{img/mqstruct} @@ -1888,7 +1888,7 @@ Come per le code di messaggi anche per gli insiemi di semafori esistono una serie di limiti, i cui valori sono associati ad altrettante costanti, che si sono riportate in tab.~\ref{tab:ipc_sem_limits}. Alcuni di questi limiti sono al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo -direttamente nel file \procfile{/proc/sys/kernel/sem}. +direttamente nel file \sysctlfile{kernel/sem}. La funzione che permette di effettuare le varie operazioni di controllo sui semafori (fra le quali, come accennato, è impropriamente compresa anche la @@ -2319,7 +2319,7 @@ controllare il valore dei mutex prima di proseguire in una operazione di sblocco non servirebbe comunque, dato che l'operazione non sarebbe atomica. Vedremo in sez.~\ref{sec:ipc_lock_file} come sia possibile ottenere un'interfaccia analoga a quella appena illustrata, senza incorrere in questi -problemi, usando il \index{file!locking} \textit{file locking}. +problemi, usando il \itindex{file~locking} \textit{file locking}. \subsection{Memoria condivisa} @@ -2434,14 +2434,14 @@ che permettono di cambiarne il valore. & \textbf{Significato} \\ \hline \hline - \const{SHMALL}& 0x200000&\procrelfile{/proc/sys/kernel}{shmall} + \const{SHMALL}& 0x200000&\sysctlrelfile{kernel}{shmall} & Numero massimo di pagine che possono essere usate per i segmenti di memoria condivisa.\\ - \const{SHMMAX}&0x2000000&\procrelfile{/proc/sys/kernel}{shmmax} + \const{SHMMAX}&0x2000000&\sysctlrelfile{kernel}{shmmax} & Dimensione massima di un segmento di memoria condivisa.\\ - \const{SHMMNI}& 4096&\procrelfile{/proc/sys/kernel}{msgmni} + \const{SHMMNI}& 4096&\sysctlrelfile{kernel}{msgmni} & Numero massimo di segmenti di memoria condivisa presenti nel kernel.\\ \const{SHMMIN}& 1& --- & Dimensione minima di un segmento di @@ -3117,9 +3117,9 @@ accedere alla seriale si limita a segnalare che la risorsa non è disponibile. Dato che i \index{file!di lock} file di lock presentano gli inconvenienti illustrati in precedenza, la tecnica alternativa di sincronizzazione più -comune è quella di fare ricorso al \index{file!locking} \textit{file locking} -(trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un file -creato per l'occasione per ottenere un write lock. In questo modo potremo +comune è quella di fare ricorso al \itindex{file~locking} \textit{file + locking} (trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un +file creato per l'occasione per ottenere un write lock. In questo modo potremo usare il lock come un \textit{mutex}: per bloccare la risorsa basterà acquisire il lock, per sbloccarla basterà rilasciare il lock. Una richiesta fatta con un write lock metterà automaticamente il processo in stato di @@ -3141,12 +3141,12 @@ leggermente più lento. \end{minipage} \normalsize \caption{Il codice delle funzioni che permettono per la gestione dei - \textit{mutex} con il \index{file!locking} \textit{file locking}.} + \textit{mutex} con il \itindex{file~locking} \textit{file locking}.} \label{fig:ipc_flock_mutex} \end{figure} Il codice delle varie funzioni usate per implementare un mutex utilizzando il -\textit{file locking} \index{file!locking} è riportato in +\textit{file locking} \itindex{file~locking} è riportato in fig.~\ref{fig:ipc_flock_mutex}; si è mantenuta volutamente una struttura analoga alle precedenti funzioni che usano i semafori, anche se le due interfacce non possono essere completamente equivalenti, specie per quanto @@ -3163,7 +3163,7 @@ mutex. La seconda funzione (\texttt{\small 6--10}) è \func{FindMutex}, che, come la precedente, è stata definita per mantenere una analogia con la corrispondente funzione basata sui semafori. Anch'essa si limita (\texttt{\small 9}) ad -aprire il file da usare per il \index{file!locking} \textit{file locking}, +aprire il file da usare per il \itindex{file~locking} \textit{file locking}, solo che in questo caso le opzioni di \func{open} sono tali che il file in questione deve esistere di già. @@ -3180,7 +3180,7 @@ La quarta funzione (\texttt{\small 24--34}) è \func{UnlockMutex} e serve a rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo caso si inizializza (\texttt{\small 28--31}) la struttura \var{lock} per il rilascio del lock, che viene effettuato (\texttt{\small 33}) con la opportuna -chiamata a \func{fcntl}. Avendo usato il \index{file!locking} \textit{file +chiamata a \func{fcntl}. Avendo usato il \itindex{file~locking} \textit{file locking} in semantica POSIX (si riveda quanto detto sez.~\ref{sec:file_posix_lock}) solo il processo che ha precedentemente eseguito il lock può sbloccare il mutex. diff --git a/listati/file_operations.h b/listati/file_operations.h new file mode 100644 index 0000000..3658273 --- /dev/null +++ b/listati/file_operations.h @@ -0,0 +1,27 @@ +struct file_operations { + struct module *owner; + loff_t (*llseek) (struct file *, loff_t, int); + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); + ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); + ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); + int (*readdir) (struct file *, void *, filldir_t); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + long (*compat_ioctl) (struct file *, unsigned int, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); + int (*open) (struct inode *, struct file *); + int (*flush) (struct file *, fl_owner_t id); + int (*release) (struct inode *, struct file *); + int (*fsync) (struct file *, int datasync); + int (*aio_fsync) (struct kiocb *, int datasync); + int (*fasync) (int, struct file *, int); + int (*lock) (struct file *, int, struct file_lock *); + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + int (*check_flags)(int); + int (*flock) (struct file *, int, struct file_lock *); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); + int (*setlease)(struct file *, long, struct file_lock **); +}; diff --git a/listati/file_system_type.h b/listati/file_system_type.h new file mode 100644 index 0000000..4f4ceb9 --- /dev/null +++ b/listati/file_system_type.h @@ -0,0 +1,15 @@ +struct file_system_type { + const char *name; + int fs_flags; + int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); + struct dentry *(*mount) (struct file_system_type *, int, + const char *, void *); + void (*kill_sb) (struct super_block *); + struct module *owner; + struct file_system_type * next; + struct list_head fs_supers; + + struct lock_class_key s_lock_key; + ... +}; diff --git a/listati/inode.h b/listati/inode.h new file mode 100644 index 0000000..e132fd8 --- /dev/null +++ b/listati/inode.h @@ -0,0 +1,20 @@ +struct inode { + ... + unsigned long i_ino; + atomic_t i_count; + unsigned int i_nlink; + uid_t i_uid; + gid_t i_gid; + dev_t i_rdev; + unsigned int i_blkbits; + u64 i_version; + loff_t i_size; + struct timespec i_atime; + struct timespec i_mtime; + struct timespec i_ctime; + ... + const struct inode_operations *i_op; + const struct file_operations *i_fop; + ... +}; + diff --git a/listati/inode_operations.h b/listati/inode_operations.h new file mode 100644 index 0000000..189fd3c --- /dev/null +++ b/listati/inode_operations.h @@ -0,0 +1,28 @@ +struct inode_operations { + int (*create) (struct inode *,struct dentry *,int, struct nameidata *); + struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); + int (*link) (struct dentry *,struct inode *,struct dentry *); + int (*unlink) (struct inode *,struct dentry *); + int (*symlink) (struct inode *,struct dentry *,const char *); + int (*mkdir) (struct inode *,struct dentry *,int); + int (*rmdir) (struct inode *,struct dentry *); + int (*mknod) (struct inode *,struct dentry *,int,dev_t); + int (*rename) (struct inode *, struct dentry *, + struct inode *, struct dentry *); + int (*readlink) (struct dentry *, char __user *,int); + void * (*follow_link) (struct dentry *, struct nameidata *); + void (*put_link) (struct dentry *, struct nameidata *, void *); + void (*truncate) (struct inode *); + int (*permission) (struct inode *, int); + int (*check_acl)(struct inode *, int); + int (*setattr) (struct dentry *, struct iattr *); + int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); + int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); + int (*removexattr) (struct dentry *, const char *); + void (*truncate_range)(struct inode *, loff_t, loff_t); + long (*fallocate)(struct inode *inode, int mode, loff_t offset, + loff_t len); + int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, + u64 len); +}; diff --git a/macro.tex b/macro.tex index 797bc17..939cc74 100644 --- a/macro.tex +++ b/macro.tex @@ -183,7 +183,25 @@ %\index{#1@{{\tt {#1}} (direttiva)}}\texttt{#1}% } +\newcommand{\sysctlfile}[1]{% +\index{file!file di controllo (sotto \texttt{/proc/sys})!{#1}@{{\tt {#1}}}}\texttt{/proc/sys/#1}% +%\index{#1@{{\tt {#1}} (direttiva)}}\texttt{#1}% +} % /proc/sys file name + +\newcommand{\sysctlrelfile}[2]{% +\index{file!file di controllo (sotto \texttt{/proc/sys})!{#1/#2}@{{\tt {#1/#2}}}}\texttt{#2}% +%\index{#1@{{\tt {#1}} (direttiva)}}\texttt{#1}% +} % /proc/sys file name + +\newcommand{\kstruct}[1]{% +\index{struttura dati del kernel!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (struttura dati)}}\texttt{#1}% +} % struttura dati +\newcommand{\kstructd}[1]{% +\index{struttura dati del kernel!{#1}@{{\tt {#1}}}!definizione di}\texttt{#1}% +%\index{#1@{{\tt {#1}} (struttura dati)}!definizione di}\texttt{#1}% +} % struttura dati \newcommand{\type}[1]{% \index{tipo di dato!{#1}@{{\tt {#1}}}}\texttt{#1}% %\index{#1@{{\tt {#1}} (tipo)}}\texttt{#1}% diff --git a/process.tex b/process.tex index d9b2c68..8c7dc49 100644 --- a/process.tex +++ b/process.tex @@ -2302,12 +2302,14 @@ usando variabili globali o dichiarate come \direct{extern},\footnote{la \subsection{Il passaggio di un numero variabile di argomenti} \label{sec:proc_variadic} +\index{funzioni!variadic|(} + Come vedremo nei capitoli successivi, non sempre è possibile specificare un numero fisso di argomenti per una funzione. Lo standard ISO C prevede nella -sua sintassi la possibilità di definire delle \index{variadic} -\textit{variadic function} che abbiano un numero variabile di argomenti, -attraverso l'uso nella dichiarazione della funzione dello speciale costrutto -``\texttt{...}'', che viene chiamato \textit{ellipsis}. +sua sintassi la possibilità di definire delle \textit{variadic function} che +abbiano un numero variabile di argomenti, attraverso l'uso nella dichiarazione +della funzione dello speciale costrutto ``\texttt{...}'', che viene chiamato +\textit{ellipsis}. Lo standard però non provvede a livello di linguaggio alcun meccanismo con cui dette funzioni possono accedere ai loro argomenti. L'accesso viene pertanto @@ -2323,11 +2325,11 @@ adeguati. L'uso di una \textit{variadic function} prevede quindi tre punti: a seguire quelli addizionali. \end{itemize*} -Lo standard ISO C prevede che una \index{variadic} \textit{variadic function} -abbia sempre almeno un argomento fisso. Prima di effettuare la dichiarazione -deve essere incluso l'apposito \textit{header file} \file{stdarg.h}; un -esempio di dichiarazione è il prototipo della funzione \func{execl} che -vedremo in sez.~\ref{sec:proc_exec}: +Lo standard ISO C prevede che una \textit{variadic function} abbia sempre +almeno un argomento fisso. Prima di effettuare la dichiarazione deve essere +incluso l'apposito \textit{header file} \file{stdarg.h}; un esempio di +dichiarazione è il prototipo della funzione \func{execl} che vedremo in +sez.~\ref{sec:proc_exec}: \includecodesnip{listati/exec_sample.c} in questo caso la funzione prende due argomenti fissi ed un numero variabile di altri argomenti, che andranno a costituire gli elementi successivi al primo @@ -2515,6 +2517,7 @@ valore speciale per l'ultimo argomento, come fa ad esempio \func{execl} che usa un puntatore \val{NULL} per indicare la fine della lista degli argomenti (vedi sez.~\ref{sec:proc_exec}). +\index{funzioni!variadic|)} \subsection{Il controllo di flusso non locale} \label{sec:proc_longjmp} diff --git a/prochand.tex b/prochand.tex index 1638ea8..5c6a408 100644 --- a/prochand.tex +++ b/prochand.tex @@ -136,7 +136,7 @@ che è progenitore di tutti gli altri processi.\footnote{in realtà questo non Il kernel mantiene una tabella dei processi attivi, la cosiddetta \itindex{process~table} \textit{process table}. Per ciascun processo viene mantenuta una voce in questa tabella, costituita da una struttura -\struct{task\_struct}, che contiene tutte le informazioni rilevanti per quel +\kstruct{task\_struct}, che contiene tutte le informazioni rilevanti per quel processo. Tutte le strutture usate a questo scopo sono dichiarate nell'\textit{header file} \file{linux/sched.h}, ed uno schema semplificato, che riporta la struttura delle principali informazioni contenute nella @@ -208,7 +208,7 @@ riparte dal numero più basso disponibile a partire da un minimo di kernel, con il 2.6.x e la nuova interfaccia per i \itindex{thread} \textit{thread} anche il meccanismo di allocazione dei \acr{pid} è stato modificato ed il valore massimo è impostabile attraverso il file - \procfile{/proc/sys/kernel/pid\_max} e di default vale 32768.} che serve a + \sysctlfile{kernel/pid\_max} e di default vale 32768.} che serve a riservare i \acr{pid} più bassi ai processi eseguiti direttamente dal kernel. Per questo motivo, come visto in sez.~\ref{sec:proc_hierarchy}, il processo di avvio (\cmd{init}) ha sempre il \acr{pid} uguale a uno. @@ -1137,38 +1137,43 @@ anomala), uno per indicare se è stato generato un \itindex{core~dump} \textbf{Macro} & \textbf{Descrizione}\\ \hline \hline - \macro{WIFEXITED(s)} & Condizione vera (valore non nullo) per un processo - figlio che sia terminato normalmente. \\ - \macro{WEXITSTATUS(s)} & Restituisce gli otto bit meno significativi dello - stato di uscita del processo (passato attraverso - \func{\_exit}, \func{exit} o come valore di - ritorno di \func{main}); può essere valutata solo - se \val{WIFEXITED} ha restituito un valore non - nullo.\\ - \macro{WIFSIGNALED(s)} & Condizione vera se il processo figlio è terminato - in maniera anomala a causa di un segnale che non - è stato catturato (vedi - sez.~\ref{sec:sig_notification}).\\ - \macro{WTERMSIG(s)} & Restituisce il numero del segnale che ha causato - la terminazione anomala del processo; può essere - valutata solo se \val{WIFSIGNALED} ha restituito - un valore non nullo.\\ - \macro{WCOREDUMP(s)} & Vera se il processo terminato ha generato un - file di \itindex{core~dump} \textit{core - dump}; può essere valutata solo se - \val{WIFSIGNALED} ha restituito un valore non - nullo.\footnotemark \\ - \macro{WIFSTOPPED(s)} & Vera se il processo che ha causato il ritorno di - \func{waitpid} è bloccato; l'uso è possibile solo - con \func{waitpid} avendo specificato l'opzione - \const{WUNTRACED}.\\ - \macro{WSTOPSIG(s)} & Restituisce il numero del segnale che ha bloccato - il processo; può essere valutata solo se - \val{WIFSTOPPED} ha restituito un valore non - nullo. \\ - \macro{WIFCONTINUED(s)}& Vera se il processo che ha causato il ritorno è - stato riavviato da un \signal{SIGCONT} - (disponibile solo a partire dal kernel 2.6.10).\\ + \macro{WIFEXITED}\texttt{(s)} & Condizione vera (valore non nullo) per + un processo figlio che sia terminato + normalmente. \\ + \macro{WEXITSTATUS}\texttt{(s)} & Restituisce gli otto bit meno + significativi dello stato di uscita del + processo (passato attraverso + \func{\_exit}, \func{exit} o come valore + di ritorno di \func{main}); può essere + valutata solo se \val{WIFEXITED} ha + restituito un valore non nullo.\\ + \macro{WIFSIGNALED}\texttt{(s)} & Condizione vera se il processo figlio è + terminato in maniera anomala a causa di + un segnale che non è stato catturato + (vedi sez.~\ref{sec:sig_notification}).\\ + \macro{WTERMSIG}\texttt{(s)} & Restituisce il numero del segnale che ha + causato la terminazione anomala del + processo; può essere valutata solo se + \val{WIFSIGNALED} ha restituito un + valore non nullo.\\ + \macro{WCOREDUMP}\texttt{(s)} & Vera se il processo terminato ha + generato un file di \itindex{core~dump} + \textit{core dump}; può essere valutata + solo se \val{WIFSIGNALED} ha restituito + un valore non nullo.\footnotemark \\ + \macro{WIFSTOPPED}\texttt{(s)} & Vera se il processo che ha causato il + ritorno di \func{waitpid} è bloccato; + l'uso è possibile solo con + \func{waitpid} avendo specificato + l'opzione \const{WUNTRACED}.\\ + \macro{WSTOPSIG}\texttt{(s)} & Restituisce il numero del segnale che ha + bloccato il processo; può essere + valutata solo se \val{WIFSTOPPED} ha + restituito un valore non nullo. \\ + \macro{WIFCONTINUED}\texttt{(s)}& Vera se il processo che ha causato il + ritorno è stato riavviato da un + \signal{SIGCONT} (disponibile solo a + partire dal kernel 2.6.10).\\ \hline \end{tabular} \caption{Descrizione delle varie macro di preprocessore utilizzabili per @@ -1437,7 +1442,7 @@ argomenti all'esecuzione del nuovo programma. I loro prototipi sono: \fdecl{int execvp(const char *file, char *const argv[])} \fdesc{Eseguono un programma.} } -{Le funzioni ritorna solo in caso di errore, restituendo $-1$, i codici di +{Le funzioni ritornano solo in caso di errore, restituendo $-1$, i codici di errore sono gli stessi di \func{execve}. } \end{funcproto} @@ -1654,7 +1659,7 @@ Infine nel caso il programma che si vuole eseguire sia uno script e non un binario, questo deve essere un file di testo che deve iniziare con una linea nella forma: \begin{Example} -\#!/path/to/interpreter [argomenti] +#!/path/to/interpreter [argomenti] \end{Example} dove l'interprete indicato deve essere un eseguibile binario e non un altro script, che verrà chiamato come se si fosse eseguito il comando @@ -2862,7 +2867,7 @@ stato \textit{runnable} viene sempre inserito in coda alla lista. Se la politica scelta è \const{SCHED\_FIFO} quando il processo viene eseguito viene automaticamente rimesso in coda alla lista, e la sua esecuzione continua fintanto che non viene bloccato da una richiesta di I/O, o non rilascia -volontariamente la CPU (in tal caso, tornando nello stato \textbf{Runnable} +volontariamente la CPU (in tal caso, tornando nello stato \textit{runnable} sarà reinserito in coda alla lista); l'esecuzione viene ripresa subito solo nel caso che esso sia stato interrotto da un processo a priorità più alta. @@ -3020,7 +3025,7 @@ l'introduzione del \textit{Completely Fair Scheduler} questo comportamento è cambiato ed un processo che chiama la funzione viene inserito nella lista dei processi inattivo, con un tempo molto maggiore.\footnote{è comunque possibile ripristinare un comportamento analogo al precedente scrivendo il valore 1 - nel file \texttt{/proc/sys/kernel/sched\_compat\_yield}.} + nel file \sysctlfile{kernel/sched\_compat\_yield}.} L'uso delle funzione nella programmazione ordinaria può essere utile e migliorare le prestazioni generali del sistema quando si è appena rilasciata @@ -3167,12 +3172,12 @@ permette di identificare un insieme di processori. Il dato è normalmente una maschera binaria: nei casi più comuni potrebbe bastare un intero a 32 bit, in cui ogni bit corrisponde ad un processore, ma oggi esistono architetture in cui questo numero può non essere sufficiente, e per questo è stato creato -questo \itindex{tipo!opaco} tipo opaco e una interfaccia di gestione che +questo \index{tipo!opaco} tipo opaco e una interfaccia di gestione che permette di usare a basso livello un tipo di dato qualunque rendendosi indipendenti dal numero di bit e dalla loro disposizione. Per questo le funzioni richiedono anche che oltre all'insieme di processori si indichi anche -la dimensione dello stesso con l'argomento \param{setsize}, per il quale, -se non si usa l'allocazione dinamica che vedremo a breve, ed è in genere +la dimensione dello stesso con l'argomento \param{setsize}, per il quale, se +non si usa l'allocazione dinamica che vedremo a breve, ed è in genere sufficiente passare il valore \code{sizeof(cpu\_set\_t)}. L'interfaccia di gestione degli insiemi di processori, oltre alla definizione @@ -3842,7 +3847,7 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. Il comportamento di default prevede che per tutti i processi si applichi la politica generale di sistema definita nel file - \procfile{/proc/sys/vm/memory\_failure\_early\_kill}, ma specificando + \sysctlfile{vm/memory\_failure\_early\_kill}, ma specificando per \param{arg2} il valore \const{PR\_MCE\_KILL\_SET} è possibile impostare con il contenuto di \param{arg3} una politica specifica del processo chiamante. Si può tornare alla politica di default del sistema utilizzando @@ -3908,9 +3913,10 @@ indicare la unità di esecuzione generica messa a disposizione del kernel che Oltre a questo la funzione consente, ad uso delle nuove funzionalità di virtualizzazione dei processi, di creare nuovi \textit{namespace} per una serie di proprietà generali dei processi (come l'elenco dei PID, l'albero dei -file, i \textit{mount point}, la rete, ecc.), che consentono di creare gruppi -di processi che vivono in una sorta di spazio separato dagli altri, che -costituisce poi quello che viene chiamato un \textit{container}. +file, i \itindex{mount~point} \textit{mount point}, la rete, ecc.), che +consentono di creare gruppi di processi che vivono in una sorta di spazio +separato dagli altri, che costituisce poi quello che viene chiamato un +\textit{container}. La \textit{system call} richiede soltanto due argomenti: il primo, \param{flags}, consente di controllare le modalità di creazione del diff --git a/session.tex b/session.tex index eba2f1c..2d1b69e 100644 --- a/session.tex +++ b/session.tex @@ -922,7 +922,7 @@ Una funzione sostanzialmente identica a \func{syslog}, la cui sola differenza è prendere invece di una lista esplicita di argomenti un unico argomento finale nella forma di una lista di argomenti passato come \macro{va\_list}, utile qualora si ottengano questi nella invocazione di una funzione -\index{variadic} \textit{variadic} (si rammenti quanto visto in +\index{funzioni!variadic} \textit{variadic} (si rammenti quanto visto in sez.~\ref{sec:proc_variadic}), è \funcd{vsyslog},\footnote{la funzione è originaria di BSD e per utilizzarla deve essere definito \macro{\_BSD\_SOURCE}.} il suo prototipo è: @@ -957,10 +957,10 @@ valore nullo per \param{mask} la maschera corrente non viene modificata; in questo modo si può leggere il valore della maschera corrente. Indicando un valore non nullo per \param{mask} la registrazione dei messaggi viene disabilitata per tutte quelle priorità che non rientrano nella maschera. In -genere il valore viene impostato usando la macro \macro{LOG\_MASK(p)} dove -\code{p} è una delle costanti di tab.~\ref{tab:sess_syslog_priority}. É -inoltre disponibile anche la macro \macro{LOG\_UPTO(p)} che permette di -specificare automaticamente tutte le priorità fino a quella indicata da +genere il valore viene impostato usando la macro \macro{LOG\_MASK}\texttt{(p)} +dove \code{p} è una delle costanti di tab.~\ref{tab:sess_syslog_priority}. É +inoltre disponibile anche la macro \macro{LOG\_UPTO}\texttt{(p)} che permette +di specificare automaticamente tutte le priorità fino a quella indicata da \code{p}. Una volta che si sia certi che non si intende registrare più nessun messaggio @@ -1022,7 +1022,7 @@ vederli anche in caso di blocco totale del sistema (nell'assunzione che la console sia collegata). In particolare la stampa dei messaggi sulla console è controllata dal -contenuto del file \procfile{/proc/sys/kernel/printk} (o con l'equivalente +contenuto del file \sysctlfile{kernel/printk} (o con l'equivalente parametro di \func{sysctl}) che prevede quattro valori numerici interi: il primo (\textit{console\_loglevel}) indica la priorità corrente oltre la quale vengono stampati i messaggi sulla console, il secondo @@ -1143,7 +1143,7 @@ e la funzione ritorna un valore nullo. Le operazioni corrispondenti ai valori 6, 7 ed 8 consentono di modificare la priorità oltre la quale i messaggi vengono stampati direttamente sulla \textit{console} e fanno riferimento ai parametri del kernel gestiti con le -variabili contenute in \procfile{/proc/sys/kernel/printk} di cui abbiamo +variabili contenute in \sysctlfile{kernel/printk} di cui abbiamo parlato prima, ed in particolare con 6 si imposta come corrente il valore minimo della terza variabile (\textit{minimum\_console\_level}), ottenendo l'effetto di ridurre al minimo i messaggi che arrivano in console, mentre con diff --git a/signal.tex b/signal.tex index d1c76cb..64beb3f 100644 --- a/signal.tex +++ b/signal.tex @@ -2496,7 +2496,7 @@ Secondo lo standard POSIX la profondità della coda è indicata dalla costante \const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32. Nel caso di Linux la coda ha una dimensione variabile; fino alla versione 2.6.7 c'era un limite massimo globale che poteva essere impostato come parametro del kernel in -\procfile{/proc/sys/kernel/rtsig-max};\footnote{ed il valore predefinito era +\sysctlfile{kernel/rtsig-max};\footnote{ed il valore predefinito era pari a 1024.} a partire dal kernel 2.6.8 il valore globale è stato rimosso e sostituito dalla risorsa \const{RLIMIT\_SIGPENDING} associata al singolo utente, che può essere modificata con \func{setrlimit} come illustrato in diff --git a/sockctrl.tex b/sockctrl.tex index 7d946bb..5ec3d43 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -2272,10 +2272,10 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni: per mantenere dati amministrativi e strutture interne, e solo una parte viene usata come buffer per i dati, mentre il valore letto da \func{getsockopt} e quello riportato nei vari parametri di - \textit{sysctl}\footnote{cioè \procrelfile{/proc/sys/net/core}{wmem\_max} e - \procrelfile{/proc/sys/net/core}{rmem\_max} in \texttt{/proc/sys/net/core} - e \procrelfile{/proc/sys/net/ipv4}{tcp\_wmem} e - \procrelfile{/proc/sys/net/ipv4}{tcp\_rmem} in + \textit{sysctl}\footnote{cioè \sysctlrelfile{net/core}{wmem\_max} e + \sysctlrelfile{net/core}{rmem\_max} in \texttt{/proc/sys/net/core} + e \sysctlrelfile{net/ipv4}{tcp\_wmem} e + \sysctlrelfile{net/ipv4}{tcp\_rmem} in \texttt{/proc/sys/net/ipv4}, vedi sez.~\ref{sec:sock_sysctl}.} indica la memoria effettivamente impiegata. Si tenga presente inoltre che le modifiche alle dimensioni dei buffer di ricezione e trasmissione, per poter @@ -4035,19 +4035,19 @@ socket. Quelli descritti anche nella pagina di manuale, accessibile con \texttt{man 7 socket} sono i seguenti: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} -\item[\procrelfile{/proc/sys/net/core}{rmem\_default}] imposta la dimensione +\item[\sysctlrelfile{net/core}{rmem\_default}] imposta la dimensione di default del buffer di ricezione (cioè per i dati in ingresso) dei socket. -\item[\procrelfile{/proc/sys/net/core}{rmem\_max}] imposta la dimensione +\item[\sysctlrelfile{net/core}{rmem\_max}] imposta la dimensione massima che si può assegnare al buffer di ricezione dei socket attraverso l'uso dell'opzione \const{SO\_RCVBUF}. -\item[\procrelfile{/proc/sys/net/core}{wmem\_default}] imposta la dimensione +\item[\sysctlrelfile{net/core}{wmem\_default}] imposta la dimensione di default del buffer di trasmissione (cioè per i dati in uscita) dei socket. -\item[\procrelfile{/proc/sys/net/core}{wmem\_max}] imposta la dimensione +\item[\sysctlrelfile{net/core}{wmem\_max}] imposta la dimensione massima che si può assegnare al buffer di trasmissione dei socket attraverso l'uso dell'opzione \const{SO\_SNDBUF}. -\item[\procrelfile{/proc/sys/net/core}{message\_cost}, - \procrelfile{/proc/sys/net/core}{message\_burst}] contengono le impostazioni +\item[\sysctlrelfile{net/core}{message\_cost}, + \sysctlrelfile{net/core}{message\_burst}] contengono le impostazioni del \itindex{bucket~filter} \textit{bucket filter} che controlla l'emissione di messaggi di avviso da parte del kernel per eventi relativi a problemi sulla rete, imponendo un limite che consente di prevenire eventuali attacchi @@ -4077,10 +4077,10 @@ socket. Quelli descritti anche nella pagina di manuale, accessibile con emissione (verranno accettati inizialmente fino ad un massimo di \texttt{message\_cost/message\_burst} messaggi). -\item[\procrelfile{/proc/sys/net/core}{netdev\_max\_backlog}] numero massimo +\item[\sysctlrelfile{net/core}{netdev\_max\_backlog}] numero massimo di pacchetti che possono essere contenuti nella coda di ingresso generale. -\item[\procrelfile{/proc/sys/net/core}{optmem\_max}] lunghezza massima dei +\item[\sysctlrelfile{net/core}{optmem\_max}] lunghezza massima dei dati ancillari e di controllo (vedi sez.~\ref{sec:net_ancillary_data}). \end{basedescript} @@ -4089,31 +4089,31 @@ file, la cui documentazione dovrebbe essere mantenuta nei sorgenti del kernel, nel file \texttt{Documentation/networking/ip-sysctl.txt}; la maggior parte di questi però non è documentato: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} -\item[\procrelfile{/proc/sys/net/core}{dev\_weight}] blocco di lavoro +\item[\sysctlrelfile{net/core}{dev\_weight}] blocco di lavoro (\textit{work quantum}) dello scheduler di processo dei pacchetti. % TODO da documentare meglio -\item[\procrelfile{/proc/sys/net/core}{lo\_cong}] valore per l'occupazione +\item[\sysctlrelfile{net/core}{lo\_cong}] valore per l'occupazione della coda di ricezione sotto la quale si considera di avere una bassa congestione. -\item[\procrelfile{/proc/sys/net/core}{mod\_cong}] valore per l'occupazione +\item[\sysctlrelfile{net/core}{mod\_cong}] valore per l'occupazione della coda di ricezione sotto la quale si considera di avere una congestione moderata. -\item[\procrelfile{/proc/sys/net/core}{no\_cong}] valore per l'occupazione +\item[\sysctlrelfile{net/core}{no\_cong}] valore per l'occupazione della coda di ricezione sotto la quale si considera di non avere congestione. -\item[\procrelfile{/proc/sys/net/core}{no\_cong\_thresh}] valore minimo +\item[\sysctlrelfile{net/core}{no\_cong\_thresh}] valore minimo (\textit{low water mark}) per il riavvio dei dispositivi congestionati. - % \item[\procrelfile{/proc/sys/net/core}{netdev\_fastroute}] è presente + % \item[\sysctlrelfile{net/core}{netdev\_fastroute}] è presente % soltanto quando si è compilato il kernel con l'apposita opzione di % ottimizzazione per l'uso come router. -\item[\procrelfile{/proc/sys/net/core}{somaxconn}] imposta la dimensione +\item[\sysctlrelfile{net/core}{somaxconn}] imposta la dimensione massima utilizzabile per il \textit{backlog} della funzione \func{listen} (vedi sez.~\ref{sec:TCP_func_listen}), e corrisponde al valore della costante \const{SOMAXCONN}; il suo valore di default è 128. @@ -4135,7 +4135,7 @@ protocollo IP in quanto tale, che sono descritti anche nella relativa pagina di manuale accessibile con \texttt{man 7 ip}, sono i seguenti: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_default\_ttl}] imposta il valore di +\item[\sysctlrelfile{net/ipv4}{ip\_default\_ttl}] imposta il valore di default per il campo TTL (vedi sez.~\ref{sec:IP_header}) di tutti i pacchetti uscenti, stabilendo così il numero massimo di router che i pacchetti possono attraversare. Il valore può essere modificato anche per il @@ -4148,12 +4148,12 @@ di manuale accessibile con \texttt{man 7 ip}, sono i seguenti: quanto in caso di problemi di routing si allunga inutilmente il numero di ritrasmissioni. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_forward}] abilita l'inoltro dei +\item[\sysctlrelfile{net/ipv4}{ip\_forward}] abilita l'inoltro dei pacchetti da una interfaccia ad un altra, e può essere impostato anche per la singola interfaccia. Prende un valore logico (0 disabilita, diverso da zero abilita), di default è disabilitato. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_dynaddr}] abilita la riscrittura +\item[\sysctlrelfile{net/ipv4}{ip\_dynaddr}] abilita la riscrittura automatica degli indirizzi associati ad un socket quando una interfaccia cambia indirizzo. Viene usato per le interfacce usate nei collegamenti in dial-up, il cui indirizzo IP viene assegnato dinamicamente dal provider, e @@ -4162,13 +4162,13 @@ di manuale accessibile con \texttt{man 7 ip}, sono i seguenti: diverso dai precedenti) la si abilità in modalità \textsl{prolissa}; di default la funzionalità è disabilitata. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_autoconfig}] specifica se +\item[\sysctlrelfile{net/ipv4}{ip\_autoconfig}] specifica se l'indirizzo IP è stato configurato automaticamente dal kernel all'avvio attraverso DHCP, BOOTP o RARP. Riporta un valore logico (0 falso, 1 vero) accessibile solo in lettura, è inutilizzato nei kernel recenti ed eliminato a partire dal kernel 2.6.18. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_local\_port\_range}] imposta +\item[\sysctlrelfile{net/ipv4}{ip\_local\_port\_range}] imposta l'intervallo dei valori usati per l'assegnazione delle porte effimere, permette cioè di modificare i valori illustrati in fig.~\ref{fig:TCP_port_alloc}; prende due valori interi separati da spazi, @@ -4179,7 +4179,7 @@ di manuale accessibile con \texttt{man 7 ip}, sono i seguenti: valore iniziale maggiore di 1024 (o meglio ancora di 4096) per evitare conflitti con le porte usate dai servizi noti. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_no\_pmtu\_disc}] permette di +\item[\sysctlrelfile{net/ipv4}{ip\_no\_pmtu\_disc}] permette di disabilitare per i socket \const{SOCK\_STREAM} la ricerca automatica della \itindex{Maximum~Transfer~Unit} \textit{Path MTU} (vedi sez.~\ref{sec:net_lim_dim} e sez.~\ref{sec:sock_ipv4_options}). Prende un @@ -4195,7 +4195,7 @@ di manuale accessibile con \texttt{man 7 ip}, sono i seguenti: perché disabilitare globalmente il procedimento con questo parametro ha pesanti ripercussioni in termini di prestazioni di rete. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_always\_defrag}] fa si che tutti i +\item[\sysctlrelfile{net/ipv4}{ip\_always\_defrag}] fa si che tutti i pacchetti IP frammentati siano riassemblati, anche in caso in successivo immediato inoltro.\footnote{introdotto con il kernel 2.2.13, nelle versioni precedenti questo comportamento poteva essere solo stabilito un volta per @@ -4206,17 +4206,17 @@ di manuale accessibile con \texttt{man 7 ip}, sono i seguenti: \itindex{netfilter} \textit{netfilter}, e questo parametro non è più presente. -\item[\procrelfile{/proc/sys/net/ipv4}{ipfrag\_high\_thresh}] indica il limite +\item[\sysctlrelfile{net/ipv4}{ipfrag\_high\_thresh}] indica il limite massimo (espresso in numero di byte) sui pacchetti IP frammentati presenti in coda; quando questo valore viene raggiunta la coda viene ripulita fino al valore \texttt{ipfrag\_low\_thresh}. Prende un valore intero. -\item[\procrelfile{/proc/sys/net/ipv4}{ipfrag\_low\_thresh}] soglia bassa +\item[\sysctlrelfile{net/ipv4}{ipfrag\_low\_thresh}] soglia bassa (specificata in byte) a cui viene riportata la coda dei pacchetti IP frammentati quando si raggiunge il valore massimo dato da \texttt{ipfrag\_high\_thresh}. Prende un valore intero. -\item[\procrelfile{/proc/sys/net/ipv4}{ip\_nonlocal\_bind}] se abilitato rende +\item[\sysctlrelfile{net/ipv4}{ip\_nonlocal\_bind}] se abilitato rende possibile ad una applicazione eseguire \func{bind} anche su un indirizzo che non è presente su nessuna interfaccia locale. Prende un valore logico e di default è disabilitato. @@ -4237,7 +4237,7 @@ caratteristiche specifiche del protocollo TCP, elencati anche nella rispettiva pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_abort\_on\_overflow}] indica al +\item[\sysctlrelfile{net/ipv4}{tcp\_abort\_on\_overflow}] indica al kernel di azzerare le connessioni quando il programma che le riceve è troppo lento ed incapace di accettarle. Prende un valore logico ed è disabilitato di default. Questo consente di recuperare le connessioni se si è avuto un @@ -4246,9 +4246,9 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: quando si è sicuri che non è possibile ottimizzare il server in modo che sia in grado di accettare connessioni più rapidamente. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_adv\_win\_scale}] indica al kernel +\item[\sysctlrelfile{net/ipv4}{tcp\_adv\_win\_scale}] indica al kernel quale frazione del buffer associato ad un socket\footnote{quello impostato - con \procrelfile{/proc/sys/net/ipv4}{tcp\_rmem}.} deve essere utilizzata + con \sysctlrelfile{net/ipv4}{tcp\_rmem}.} deve essere utilizzata per la finestra del protocollo TCP\footnote{in sostanza il valore che costituisce la \itindex{advertised~window} \textit{advertised window} annunciata all'altro capo del socket.} e quale come buffer applicativo per @@ -4259,7 +4259,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: negativo. Il default è 2 che significa che al buffer dell'applicazione viene riservato un quarto del totale. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_app\_win}] indica la frazione +\item[\sysctlrelfile{net/ipv4}{tcp\_app\_win}] indica la frazione della finestra TCP che viene riservata per gestire l'overhaed dovuto alla bufferizzazione. Prende un valore valore intero che consente di calcolare la dimensione in byte come il massimo fra la \itindex{Maximum~Segment~Size} @@ -4272,7 +4272,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: % \item[\texttt{tcp\_bic\_low\_window}] % \item[\texttt{tcp\_bic\_fast\_convergence}] -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_dsack}] abilita il supporto, +\item[\sysctlrelfile{net/ipv4}{tcp\_dsack}] abilita il supporto, definito nell'\href{http://www.ietf.org/rfc/rfc2884.txt}{RFC~2884}, per il cosiddetto \textit{Duplicate SACK}.\footnote{si indica con SACK (\textit{Selective Acknowledgement}) un'opzione TCP, definita @@ -4284,7 +4284,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: % mettere riferimento nelle appendici -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_ecn}] abilita il meccanismo della +\item[\sysctlrelfile{net/ipv4}{tcp\_ecn}] abilita il meccanismo della \textit{Explicit Congestion Notification} (in breve ECN) nelle connessioni TCP. Prende valore logico che di default è disabilitato. La \textit{Explicit Congestion Notification} \itindex{Explicit~Congestion~Notification} è un @@ -4305,14 +4305,14 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: % mettere riferimento nelle appendici -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_fack}] abilita il supporto per il +\item[\sysctlrelfile{net/ipv4}{tcp\_fack}] abilita il supporto per il \textit{TCP Forward Acknowledgement}, un algoritmo per il controllo della congestione del traffico. Prende un valore logico e di default è abilitato. % TODO documentare o descrivere che cos'è il TCP Forward Acknowledgement o % mettere riferimento nelle appendici -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_fin\_timeout}] specifica il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_fin\_timeout}] specifica il numero di secondi da passare in stato \texttt{FIN\_WAIT2} nell'attesa delle ricezione del pacchetto FIN conclusivo, passati quali il socket viene comunque chiuso forzatamente. Prende un valore intero che indica i secondi @@ -4322,26 +4322,26 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: ma è utile per fronteggiare alcuni attacchi di \itindex{Denial~of~Service~(DoS)} \textit{Denial of Service}. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_frto}] abilita il supporto per +\item[\sysctlrelfile{net/ipv4}{tcp\_frto}] abilita il supporto per l'algoritmo F-RTO, un algoritmo usato per la ritrasmissione dei timeout del protocollo TCP, che diventa molto utile per le reti wireless dove la perdita di pacchetti è usualmente dovuta a delle interferenze radio, piuttosto che alla congestione dei router. Prende un valore logico e di default è disabilitato. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_keepalive\_intvl}] indica il +\item[\sysctlrelfile{net/ipv4}{tcp\_keepalive\_intvl}] indica il numero di secondi che deve trascorrere fra l'emissione di due successivi pacchetti di test quando è abilitata la funzionalità del \textit{keepalive} (vedi sez.~\ref{sec:sock_options_main}). Prende un valore intero che di default è 75. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_keepalive\_probes}] indica il +\item[\sysctlrelfile{net/ipv4}{tcp\_keepalive\_probes}] indica il massimo numero pacchetti di \textit{keepalive} (vedi sez.~\ref{sec:sock_options_main}) che devono essere inviati senza ricevere risposta prima che il kernel decida che la connessione è caduta e la termini. Prende un valore intero che di default è 9. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_keepalive\_time}] indica il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_keepalive\_time}] indica il numero di secondi che devono passare senza traffico sulla connessione prima che il kernel inizi ad inviare pacchetti di pacchetti di \textit{keepalive}.\footnote{ha effetto solo per i socket per cui si è @@ -4349,7 +4349,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: sez.~\ref{sec:sock_options_main}.} Prende un valore intero che di default è 7200, pari a due ore. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_low\_latency}] indica allo stack +\item[\sysctlrelfile{net/ipv4}{tcp\_low\_latency}] indica allo stack TCP del kernel di ottimizzare il comportamento per ottenere tempi di latenza più bassi a scapito di valori più alti per l'utilizzo della banda. Prende un valore logico che di default è disabilitato in quanto un maggior utilizzo @@ -4357,7 +4357,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: riduzione della latenza è più importante (ad esempio per i cluster di calcolo parallelo) nelle quali lo si può abilitare. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_max\_orphans}] indica il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_max\_orphans}] indica il numero massimo di socket TCP ``\textsl{orfani}'' (vale a dire non associati a nessun file descriptor) consentito nel sistema.\footnote{trattasi in genere delle connessioni relative a socket chiusi che non hanno completato il @@ -4373,7 +4373,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: % TODO verificare la spiegazione di connessione orfana. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_max\_syn\_backlog}] indica la +\item[\sysctlrelfile{net/ipv4}{tcp\_max\_syn\_backlog}] indica la lunghezza della coda delle connessioni incomplete, cioè delle connessioni per le quali si è ricevuto un SYN di richiesta ma non l'ACK finale del \itindex{three~way~handshake} \textit{three way handshake} (si riveda quanto @@ -4390,7 +4390,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: del kernel, in modo che sia $\mathtt{tcp\_max\_syn\_backlog} \ge \mathtt{16*TCP\_SYNQ\_HSIZE}$, per poi ricompilare il kernel.} -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_max\_tw\_buckets}] indica il +\item[\sysctlrelfile{net/ipv4}{tcp\_max\_tw\_buckets}] indica il numero massimo di socket in stato \texttt{TIME\_WAIT} consentito nel sistema. Prende un valore intero di default è impostato al doppio del valore del parametro \texttt{NR\_FILE}, ma che viene aggiustato automaticamente a @@ -4399,7 +4399,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: prevenire alcuni semplici attacchi di \textit{denial of service}. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_mem}] viene usato dallo stack TCP +\item[\sysctlrelfile{net/ipv4}{tcp\_mem}] viene usato dallo stack TCP per gestire le modalità con cui esso utilizzerà la memoria. Prende una tripletta di valori interi, che indicano un numero di pagine: @@ -4419,12 +4419,12 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: ogni altro valore specificato dagli altri limiti del kernel. \end{itemize*} -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_orphan\_retries}] indica il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_orphan\_retries}] indica il numero massimo di volte che si esegue un tentativo di controllo sull'altro capo di una connessione che è stata già chiusa dalla nostra parte. Prende un valore intero che di default è 8. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_reordering}] indica il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_reordering}] indica il numero massimo di volte che un pacchetto può essere riordinato nel flusso di dati, prima che lo stack TCP assuma che è andato perso e si ponga nello stato di \textit{slow start} (si veda sez.~\ref{sec:tcp_protocol_xxx}) viene usata @@ -4432,7 +4432,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: ritrasmissioni provocate dal riordinamento. Prende un valore intero che di default che è 3, e che non è opportuno modificare. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_retrans\_collapse}] in caso di +\item[\sysctlrelfile{net/ipv4}{tcp\_retrans\_collapse}] in caso di pacchetti persi durante una connessione, per ottimizzare l'uso della banda il kernel cerca di eseguire la ritrasmissione inviando pacchetti della massima dimensione possibile; in sostanza dati che in precedenza erano stati @@ -4440,7 +4440,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: pacchetto (o su un numero minore di pacchetti di dimensione maggiore). Prende un valore logico e di default è abilitato. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_retries1}] imposta il massimo +\item[\sysctlrelfile{net/ipv4}{tcp\_retries1}] imposta il massimo numero di volte che protocollo tenterà la ritrasmissione si un pacchetto su una connessione stabilita prima di fare ricorso ad ulteriori sforzi che coinvolgano anche il livello di rete. Passato questo numero di @@ -4448,7 +4448,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: aggiornamento della rotta verso la destinazione prima di eseguire ogni successiva ritrasmissione. Prende un valore intero che di default è 3. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_retries2}] imposta il numero di +\item[\sysctlrelfile{net/ipv4}{tcp\_retries2}] imposta il numero di tentativi di ritrasmissione di un pacchetto inviato su una connessione già stabilita per il quale non si sia ricevuto una risposta di ACK (si veda anche quanto illustrato in sez.~\ref{sec:TCP_server_crash}). Prende un @@ -4457,7 +4457,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: nell'\href{http://www.ietf.org/rfc/rfc1122.txt}{RFC~1122} dove è indicato un massimo di 100 secondi, che però è un valore considerato troppo basso. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_rfc1337}] indica al kernel di +\item[\sysctlrelfile{net/ipv4}{tcp\_rfc1337}] indica al kernel di abilitare il comportamento richiesto nell'\href{http://www.ietf.org/rfc/rfc1337.txt}{RFC~1337}. Prende un valore logico e di default è disabilitato, il che significa che alla ricezione di @@ -4465,7 +4465,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: immediatamente senza attendere la conclusione del periodo di \texttt{TIME\_WAIT}. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_rmem}] viene usato dallo stack TCP +\item[\sysctlrelfile{net/ipv4}{tcp\_rmem}] viene usato dallo stack TCP per controllare dinamicamente le dimensioni dei propri buffer di ricezione, anche in rapporto alla memoria disponibile. Prende una tripletta di valori interi separati da spazi che indicano delle dimensioni in byte: @@ -4476,7 +4476,7 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: in sistemi con poca memoria viene automaticamente ridotto a \const{PAGE\_SIZE}. Questo valore viene usato per assicurare che anche in situazioni di pressione sulla memoria (vedi quanto detto per - \procrelfile{/proc/sys/net/ipv4}{tcp\_rmem}) le allocazioni al di sotto di + \sysctlrelfile{net/ipv4}{tcp\_rmem}) le allocazioni al di sotto di questo limite abbiamo comunque successo. Questo valore non viene comunque ad incidere sulla dimensione del buffer di ricezione di un singolo socket dichiarata con l'opzione \const{SO\_RCVBUF}. @@ -4484,31 +4484,31 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: \item il secondo valore, denominato \textit{default} nelle pagine di manuale, indica la dimensione di default, in byte, del buffer di ricezione di un socket TCP. Questo valore sovrascrive il default iniziale impostato - per tutti i socket con \procfile{/proc/sys/net/core/mem\_default} che vale + per tutti i socket con \sysctlfile{net/core/mem\_default} che vale per qualunque protocollo. Il default è 87380 byte, ridotto a 43689 per sistemi con poca memoria. Se si desiderano dimensioni più ampie per tutti i socket si può aumentare questo valore, ma se si vuole che in corrispondenza aumentino anche le dimensioni usate per la finestra TCP si deve abilitare il \itindex{TCP~window~scaling} \textit{TCP window scaling} (di default è abilitato, vedi più avanti - \procrelfile{/proc/sys/net/ipv4}{tcp\_window\_scaling}). + \sysctlrelfile{net/ipv4}{tcp\_window\_scaling}). \item il terzo valore, denominato \textit{max} nelle pagine di manuale, indica la dimensione massima in byte del buffer di ricezione di un socket TCP; il default è 174760 byte, che viene ridotto automaticamente a 87380 per sistemi con poca memoria. Il valore non può comunque eccedere il limite generale per tutti i socket posto con - \procfile{/proc/sys/net/core/rmem\_max}. Questo valore non viene ad + \sysctlfile{net/core/rmem\_max}. Questo valore non viene ad incidere sulla dimensione del buffer di ricezione di un singolo socket dichiarata con l'opzione \const{SO\_RCVBUF}. \end{itemize} -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_sack}] indica al kernel di +\item[\sysctlrelfile{net/ipv4}{tcp\_sack}] indica al kernel di utilizzare il meccanismo del \textit{TCP selective acknowledgement} definito nell'\href{http://www.ietf.org/rfc/rfc2018.txt}{RFC~2018}. Prende un valore logico e di default è abilitato. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_stdurg}] indica al kernel di +\item[\sysctlrelfile{net/ipv4}{tcp\_stdurg}] indica al kernel di utilizzare l'interpretazione che viene data dall'\href{http://www.ietf.org/rfc/rfc1122.txt}{RFC~1122} del puntatore dei \textit{dati urgenti} (vedi sez.~\ref{sec:TCP_urgent_data}) in cui questo @@ -4517,12 +4517,12 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: Prende un valore logico e di default è disabilitato, perché abilitarlo può dar luogo a problemi di interoperabilità. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_synack\_retries}] indica il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_synack\_retries}] indica il numero massimo di volte che verrà ritrasmesso il segmento SYN/ACK nella creazione di una connessione (vedi sez.~\ref{sec:TCP_conn_cre}). Prende un valore intero ed il valore di default è 5; non si deve superare il valore massimo di 255. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_syncookies}] abilita i \textit{TCP +\item[\sysctlrelfile{net/ipv4}{tcp\_syncookies}] abilita i \textit{TCP syncookies}.\footnote{per poter usare questa funzionalità è necessario avere abilitato l'opzione \texttt{CONFIG\_SYN\_COOKIES} nella compilazione del kernel.} Prende un valore logico, e di default è disabilitato. Questa @@ -4532,18 +4532,18 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: con altre funzionalità come le estensioni e può causare problemi per i client ed il reinoltro dei pacchetti. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_syn\_retries}] imposta il numero +\item[\sysctlrelfile{net/ipv4}{tcp\_syn\_retries}] imposta il numero di tentativi di ritrasmissione dei pacchetti SYN di inizio connessione del \itindex{three~way~handshake} \textit{three way handshake} (si ricordi quanto illustrato in sez.~\ref{sec:TCP_func_connect}). Prende un valore intero che di default è 5; non si deve superare il valore massimo di 255. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_timestamps}] abilita l'uso dei +\item[\sysctlrelfile{net/ipv4}{tcp\_timestamps}] abilita l'uso dei \textit{TCP timestamps}, come definiti nell'\href{http://www.ietf.org/rfc/rfc1323.txt}{RFC~1323}. Prende un valore logico e di default è abilitato. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_tw\_recycle}] abilita il +\item[\sysctlrelfile{net/ipv4}{tcp\_tw\_recycle}] abilita il riutilizzo rapido dei socket in stato \texttt{TIME\_WAIT}. Prende un valore logico e di default è disabilitato. Non è opportuno abilitare questa opzione che può causare problemi con il NAT.\footnote{il \textit{Network Address @@ -4553,11 +4553,11 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: \textit{netfilter}, per maggiori dettagli si consulti il cap.~2 di \cite{FwGL}.} -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_tw\_reuse}] abilita il riutilizzo +\item[\sysctlrelfile{net/ipv4}{tcp\_tw\_reuse}] abilita il riutilizzo dello stato \texttt{TIME\_WAIT} quando questo è sicuro dal punto di vista del protocollo. Prende un valore logico e di default è disabilitato. -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_window\_scaling}] un valore +\item[\sysctlrelfile{net/ipv4}{tcp\_window\_scaling}] un valore logico, attivo di default, che abilita la funzionalità del \itindex{TCP~window~scaling} \textit{TCP window scaling} definita dall'\href{http://www.ietf.org/rfc/rfc1323.txt}{RFC~1323}. Prende un valore @@ -4570,13 +4570,13 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: \itindex{TCP~window~scaling} \textit{TCP window scaling} con l'altro capo della connessione non viene effettuata. -%\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_vegas\_cong\_avoid}] +%\item[\sysctlrelfile{net/ipv4}{tcp\_vegas\_cong\_avoid}] % TODO: controllare su internet -%\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_westwood}] +%\item[\sysctlrelfile{net/ipv4}{tcp\_westwood}] % TODO: controllare su internet -\item[\procrelfile{/proc/sys/net/ipv4}{tcp\_wmem}] viene usato dallo stack TCP +\item[\sysctlrelfile{net/ipv4}{tcp\_wmem}] viene usato dallo stack TCP per controllare dinamicamente le dimensioni dei propri buffer di spedizione, adeguandole in rapporto alla memoria disponibile. Prende una tripletta di valori interi separati da spazi che indicano delle dimensioni in byte: @@ -4584,9 +4584,9 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: \begin{itemize} \item il primo valore, chiamato \textit{min}, indica la dimensione minima in byte del buffer di spedizione; il default è 4Kb. Come per l'analogo di - \procrelfile{/proc/sys/net/ipv4}{tcp\_rmem}) viene usato per assicurare + \sysctlrelfile{net/ipv4}{tcp\_rmem}) viene usato per assicurare che anche in situazioni di pressione sulla memoria (vedi - \procrelfile{/proc/sys/net/ipv4}{tcp\_mem}) le allocazioni al di sotto di + \sysctlrelfile{net/ipv4}{tcp\_mem}) le allocazioni al di sotto di questo limite abbiamo comunque successo. Di nuovo questo valore non viene ad incidere sulla dimensione del buffer di trasmissione di un singolo socket dichiarata con l'opzione \const{SO\_SNDBUF}. @@ -4594,20 +4594,20 @@ pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti: \item il secondo valore, denominato \textit{default}, indica la dimensione di default in byte del buffer di spedizione di un socket TCP. Questo valore sovrascrive il default iniziale impostato per tutti i tipi di - socket con \procfile{/proc/sys/net/core/wmem\_default}. Il default è 87380 + socket con \sysctlfile{net/core/wmem\_default}. Il default è 87380 byte, ridotto a 43689 per sistemi con poca memoria. Si può aumentare questo valore quando si desiderano dimensioni più ampie del buffer di trasmissione per i socket TCP, ma come per il precedente - \procrelfile{/proc/sys/net/ipv4}{tcp\_rmem}) se si vuole che in + \sysctlrelfile{net/ipv4}{tcp\_rmem}) se si vuole che in corrispondenza aumentino anche le dimensioni usate per la finestra TCP si deve abilitare il \itindex{TCP~window~scaling} \textit{TCP window scaling} - con \procrelfile{/proc/sys/net/ipv4}{tcp\_window\_scaling}. + con \sysctlrelfile{net/ipv4}{tcp\_window\_scaling}. \item il terzo valore, denominato \textit{max}, indica la dimensione massima in byte del buffer di spedizione di un socket TCP; il default è 128Kb, che viene ridotto automaticamente a 64Kb per sistemi con poca memoria. Il valore non può comunque eccedere il limite generale per tutti i socket - posto con \procfile{/proc/sys/net/core/wmem\_max}. Questo valore non viene + posto con \sysctlfile{net/core/wmem\_max}. Questo valore non viene ad incidere sulla dimensione del buffer di trasmissione di un singolo socket dichiarata con l'opzione \const{SO\_SNDBUF}. \end{itemize} diff --git a/system.tex b/system.tex index bac9aab..ff4033d 100644 --- a/system.tex +++ b/system.tex @@ -663,11 +663,9 @@ inclusa nei sorgenti del kernel, nella directory \file{Documentation/sysctl}. Ma oltre alle informazioni ottenibili da \func{sysctl} dentro \file{proc} sono disponibili moltissime altre informazioni, fra cui ad esempio anche quelle fornite da \func{uname} (vedi sez.~\ref{sec:sys_uname}) che sono mantenute nei -file \procrelfile{/proc/sys/kernel}{ostype}, -\procrelfile{/proc/sys/kernel}{hostname}, -\procrelfile{/proc/sys/kernel}{osrelease}, -\procrelfile{/proc/sys/kernel}{version} e -\procrelfile{/proc/sys/kernel}{domainname} di \file{/proc/sys/kernel/}. +file \sysctlrelfile{kernel}{ostype}, \sysctlrelfile{kernel}{hostname}, +\sysctlrelfile{kernel}{osrelease}, \sysctlrelfile{kernel}{version} e +\sysctlrelfile{kernel}{domainname} di \file{/proc/sys/kernel/}. @@ -1275,7 +1273,7 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard un errore di \errcode{EFBIG}.\\ \const{RLIMIT\_LOCKS}& È un limite presente solo nelle prime versioni del kernel 2.4 sul numero massimo di - \index{file!locking} \textit{file lock} (vedi + \itindex{file~locking} \textit{file lock} (vedi sez.~\ref{sec:file_locking}) che un processo poteva effettuare.\\ \const{RLIMIT\_MEMLOCK}& L'ammontare massimo di memoria che può essere @@ -1555,7 +1553,7 @@ corrispondono al contenuto della apposita struttura dati definita all'interno del kernel. Il funzionamento di \func{acct} viene inoltre modificato da uno specifico -parametro di sistema, modificabile attraverso \procfile{/proc/sys/kernel/acct} +parametro di sistema, modificabile attraverso \sysctlfile{kernel/acct} (o tramite la corrispondente \func{sysctl}). Esso contiene tre valori interi, il primo indica la percentuale di spazio disco libero sopra il quale viene ripresa una registrazione che era stata sospesa per essere scesi sotto il diff --git a/tcpsock.tex b/tcpsock.tex index d92e6d8..1fab77a 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -839,7 +839,7 @@ nella chiamata della funzione sono le seguenti: secondi per un numero di volte che può essere stabilito dall'utente. Questo può essere fatto a livello globale con una opportuna \func{sysctl},\footnote{o più semplicemente scrivendo il valore voluto in - \procfile{/proc/sys/net/ipv4/tcp\_syn\_retries}, vedi + \sysctlfile{net/ipv4/tcp\_syn\_retries}, vedi sez.~\ref{sec:sock_ipv4_sysctl}.} e a livello di singolo socket con l'opzione \const{TCP\_SYNCNT} (vedi sez.~\ref{sec:sock_tcp_udp_options}). Il valore predefinito per la ripetizione dell'invio è di 5 volte, che comporta @@ -973,9 +973,9 @@ indicare la lunghezza della coda delle connessioni complete. La lunghezza della coda delle connessioni incomplete può essere ancora controllata usando la funzione \func{sysctl} con il parametro \const{NET\_TCP\_MAX\_SYN\_BACKLOG} o scrivendola direttamente in -\procfile{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la +\sysctlfile{net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la protezione dei syncookies però (con l'opzione da compilare nel kernel e da -attivare usando \procfile{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore +attivare usando \sysctlfile{net/ipv4/tcp\_syncookies}) questo valore viene ignorato e non esiste più un valore massimo. In ogni caso in Linux il valore di \param{backlog} viene troncato ad un massimo di \const{SOMAXCONN} se è superiore a detta costante (che di default vale 128).\footnote{il valore di @@ -2618,7 +2618,7 @@ Il risultato finale qui dipende dall'implementazione dello stack TCP, e nel caso di Linux anche dall'impostazione di alcuni dei parametri di sistema che si trovano in \file{/proc/sys/net/ipv4}, che ne controllano il comportamento: in questo caso in particolare da -\procrelfile{/proc/sys/net/ipv4}{tcp\_retries2} (vedi +\sysctlrelfile{net/ipv4}{tcp\_retries2} (vedi sez.~\ref{sec:sock_ipv4_sysctl}). Questo parametro infatti specifica il numero di volte che deve essere ritentata la ritrasmissione di un pacchetto nel mezzo di una connessione prima di riportare un errore di timeout. Il valore