toccato dalla funzione.
Se non ci sono connessioni pendenti da accettare la funzione mette in attesa
il processo\footnote{a meno che non si sia settato il socket per essere
- non-bloccante, nel qual caso ritorna con l'errore \func{EAGAIN},
+ non-bloccante, nel qual caso ritorna con l'errore \macro{EAGAIN},
torneremo su questa modalità di operazione in \secref{sec:xxx_sock_noblock}}
fintanto che non ne arriva una.
\textit{hard link}). Il prototipo della funzione e le sue caratteristiche
principali, come risultano dalla man page, sono le seguenti:
\begin{prototype}{unistd.h}
-{int link(const char * oldpath, const char * newpath)}
+{int link(const char *oldpath, const char *newpath)}
Crea un nuovo collegamento diretto al file indicato da \var{oldpath}
dandogli nome \var{newpath}.
La rimozione di un file (o più precisamente della voce che lo referenzia
all'interno di una directory) si effettua con la funzione \func{unlink}; il
suo prototipo è il seguente:
-\begin{prototype}{unistd.h}{int unlink(const char * pathname)}
+\begin{prototype}{unistd.h}{int unlink(const char *pathname)}
Cancella il nome specificato dal pathname nella relativa directory e
decrementa il numero di riferimenti nel relativo inode. Nel caso di link
simbolico cancella il link simbolico; nel caso di socket, fifo o file di
specificato. La funzione che permette di creare un nuovo link simbolico è
\func{symlink}; il suo prototipo è:
\begin{prototype}{unistd.h}
- {int symlink(const char * oldpath, const char * newpath)}
- Crea un nuovo link simbolico di nome \func{newpath} il cui contenuto è
- \func{oldpath}.
+ {int symlink(const char *oldpath, const char *newpath)}
+ Crea un nuovo link simbolico di nome \param{newpath} il cui contenuto è
+ \param{oldpath}.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso la variabile \var{errno} restituisce i valori:
\begin{errlist}
- \item[\macro{EPERM}] il filesystem che contiene \var{newpath} non supporta i
+ \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta i
link simbolici.
- \item[\macro{ENOENT}] una componente di \var{newpath} non esiste o
- \func{oldpath} è una stringa vuota.
- \item[\macro{EEXIST}] esiste già un file \var{newpath}.
- \item[\macro{EROFS}] \var{newpath} è su un filesystem montato in sola
+ \item[\macro{ENOENT}] una componente di \param{newpath} non esiste o
+ \param{oldpath} è una stringa vuota.
+ \item[\macro{EEXIST}] esiste già un file \param{newpath}.
+ \item[\macro{EROFS}] \param{newpath} è su un filesystem montato in sola
lettura.
\end{errlist}
ed inoltre \macro{EFAULT}, \macro{EACCES}, \macro{ENAMETOOLONG},
\end{prototype}
Si tenga presente che la funzione non effettua nessun controllo sull'esistenza
-di un file di nome \var{oldpath}, ma si limita ad inserire quella stringa nel
-link simbolico. Pertanto un link simbolico può anche riferirsi ad un file che
-non esiste: quello che viene chiamato un \textit{dangling link}, letteralmente
-\textsl{link ciondolante}.
+di un file di nome \param{oldpath}, ma si limita ad inserire quella stringa
+nel link simbolico. Pertanto un link simbolico può anche riferirsi ad un file
+che non esiste: quello che viene chiamato un \textit{dangling link},
+letteralmente \textsl{link ciondolante}.
Come accennato i link simbolici sono risolti automaticamente dal kernel
riferimento. Quando si vuole leggere il contenuto di un link simbolico si usa
la funzione \func{readlink}, il cui prototipo è:
\begin{prototype}{unistd.h}
-{int readlink(const char * path, char * buff, size\_t size)}
+{int readlink(const char *path, char *buff, size\_t size)}
Legge il contenuto del link simbolico indicato da \var{path} nel buffer
\var{buff} di dimensione \var{size}.
Questo può causare problemi per tutti quei programmi che effettuano la
scansione di una directory senza tener conto dei link simbolici, ad esempio se
lanciassimo un comando del tipo \cmd{grep -r linux *}, il loop nella directory
-porterebbe il comando ad esaminare \file{/boot}, \file/{boot/boot},
-\file/{boot/boot/boot} e così via.
+porterebbe il comando ad esaminare \file{/boot}, \file{/boot/boot},
+\file{/boot/boot/boot} e così via.
Per questo motivo il kernel e le librerie prevedono che nella risoluzione di
un pathname possano essere seguiti un numero limitato di link simbolici, il
mostrerebbe l'esistenza di \file{temporaneo}.
-\subsection{Le funzioni \func{mkdir} e \func{rmdir}}
+\subsection{La creazione e la cancellazione delle directory}
\label{sec:file_dir_creat_rem}
-Queste due funzioni servono per creare e cancellare delle directory e sono
-omonime degli analoghi comandi di shell. Per poter accedere ai tipi usati
-da queste funzioni si deve includere il file \file{sys/types.h}, il
-prototipo della prima è:
+Per creare e cancellare delle directory si usano le due funzioni (omonime
+degli analoghi comandi di shell) \func{mkdir} e \func{rmdir}. Per poter
+accedere ai tipi usati da queste funzioni si deve includere il file
+\file{sys/types.h}, il prototipo della prima è:
\begin{prototype}{sys/stat.h}
- {int mkdir (const char * dirname, mode\_t mode)}
+ {int mkdir(const char *dirname, mode\_t mode)}
Crea una nuova directory vuota con il nome indicato da \var{dirname},
assegnandole i permessi indicati da \var{mode}. Il nome può essere indicato
con il pathname assoluto o relativo.
La seconda funzione serve ad eliminare una directory già vuota (la directory
deve cioè contenere soltanto le due voci standard \file{.} e \file{..}); il
suo prototipo è:
-\begin{prototype}{sys/stat.h}
- {int rmdir (const char * dirname)} Cancella la directory \var{dirname}, che
- deve essere vuota. Il nome può essere indicato con il pathname assoluto o
- relativo.
+\begin{prototype}{sys/stat.h}{int rmdir(const char *dirname)}
+ Cancella la directory \var{dirname}, che deve essere vuota. Il nome può
+ essere indicato con il pathname assoluto o relativo.
\bodydesc{La funzione restituisce zero in caso di successo e -1 per un
errore, nel qual caso \var{errno} assumerà i valori:
\end{prototype}
La modalità con cui avviene la cancellazione è analoga a quella di
-\func{unlink}, fintanto che il numero di link all'inode della directory non
+\func{unlink}: fintanto che il numero di link all'inode della directory non
diventa nullo e nessun processo ha la directory aperta lo spazio occupato su
disco non viene rilasciato. Se un processo ha la directory aperta la funzione
rimuove il link all'inode e nel caso sia l'ultimo, pure le voci standard
-\file{.} e \file{..}, ed il kernel non consentirà di creare più nuovi file
-nella directory.
+\file{.} e \file{..}, a questo punto il kernel non consentirà di creare più
+nuovi file nella directory.
+
+
+\subsection{La creazione di file speciali}
+\label{sec:file_mknod}
+
+Finora abbiamo parlato esclusivamente di file, directory e link simbolici; in
+\secref{sec:file_file_types} abbiamo visto però che il sistema preveda pure
+degli altri tipi di file, come i file di dispositivo e le fifo (i socket sono
+un caso a parte, che vedremo in \secref{cha:socket_intro}).
+
+La manipolazione delle caratteristiche di questi filee e la loro cancellazione
+può essere effettuata con le stesse funzioni che operano sui file normali; ma
+quando li si devono creare sono necessarie delle funzioni apposite.
+
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/stat.h}
+ \headdecl{fnctl.h}
+ \headdecl{unistd.h}
+ \funcdecl{int mknod(const char *pathname, mode\_t mode, dev\_t dev)}
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\macro{EPERM}] Il filesystem non supporta la cancellazione di
+ directory, oppure la directory che contiene \var{dirname} ha lo sticky bit
+ settato e l'\textit{effective user id} del processo non corrisponde al
+ proprietario della directory.
+ \item[\macro{EACCESS}] Non c'è il permesso di scrittura per la directory che
+ contiene la directory che si vuole cancellare, o non c'è il permesso di
+ attraversare (esecuzione) una delle directory specificate in
+ \var{dirname}.
+ \item[\macro{EBUSY}] La directory specificata è la directory di lavoro o la
+ radice di qualche processo.
+ \item[\macro{ENOTEMPTY}] La directory non è vuota.
+ \end{errlist}
+ ed inoltre anche \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP}, \macro{EROFS}.}
+\end{functions}
+
+
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/stat.h}
+ \funcdecl{int mkfifo(const char *pathname, mode\_t mode)}
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\macro{EPERM}] Il filesystem non supporta la cancellazione di
+ directory, oppure la directory che contiene \var{dirname} ha lo sticky bit
+ settato e l'\textit{effective user id} del processo non corrisponde al
+ proprietario della directory.
+ \item[\macro{EACCESS}] Non c'è il permesso di scrittura per la directory che
+ contiene la directory che si vuole cancellare, o non c'è il permesso di
+ attraversare (esecuzione) una delle directory specificate in
+ \var{dirname}.
+ \item[\macro{EBUSY}] La directory specificata è la directory di lavoro o la
+ radice di qualche processo.
+ \item[\macro{ENOTEMPTY}] La directory non è vuota.
+ \end{errlist}
+ ed inoltre anche \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{ENOTDIR}, \macro{ENOMEM}, \macro{ELOOP}, \macro{EROFS}.}
+\end{functions}
+
+
\subsection{Accesso alle directory}
Benché le directory siano oggetti del filesystem come tutti gli altri non ha
ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
poterne leggere il contenuto ad esempio per fare la lista dei file che esse
-contengono o ricerche sui medesimi. Solo il kernel scrivere direttamente in
-una directory (onde evitare inconsistenze all'interno del filesystem), i
+contengono o ricerche sui medesimi. Solo il kernel può scrivere direttamente
+in una directory (onde evitare inconsistenze all'interno del filesystem), i
processi devono creare i file usando le apposite funzioni.
Per accedere al contenuto delle directory si usano i cosiddetti
-\textit{directory streams} (chiamati così per l'analogia con i file stream);
-la funzione \func{opendir} apre uno di questi stream e la funzione
-\func{readdir} legge il contenuto della directory, i cui elementi sono le
-\textit{directory entry} (da distinguersi da quelle della cache di cui
-parlavamo in \secref{sec:file_vfs}) in una opportuna struttura \var{struct
- dirent}.
+\textit{directory streams} (chiamati così per l'analogia con i file stream di
+\capref{che:file_std_interface}); la funzione \func{opendir} apre uno di
+questi stream e la funzione \func{readdir} legge il contenuto della directory,
+i cui elementi sono le \textit{directory entry} (da distinguersi da quelle
+della cache di cui parlavamo in \secref{sec:file_vfs}) in una opportuna
+struttura \var{struct dirent}.
(NdA Il resto va scritto!!! É noioso e lo farò più avanti).
In genere il kernel tiene traccia per ciascun processo dell'inode della
directory di lavoro corrente, per ottenere il pathname occorre usare una
apposita funzione di libreria, \func{getcwd}, il cui prototipo è:
-\begin{prototype}{unistd.h}{char * getcwd (char * buffer, size\_t size)}
+\begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)}
Restituisce il filename completo della directory di lavoro corrente nella
stringa puntata da \var{buffer}, che deve essere precedentemente
allocata, per una dimensione massima di \var{size}.
altrimenti. In questo caso ci si deve ricordare di disallocare la stringa una
volta cessato il suo utilizzo.
-Di questa funzione esiste una versione \func{char * getwd(char * buffer)}
+Di questa funzione esiste una versione \code{char *getwd(char *buffer)}
fatta per compatibilità all'indietro con BSD, che non consente di specificare
la dimensione del buffer; esso deve essere allocato in precedenza ed avere una
dimensione superiore a \macro{PATH\_MAX} (di solito 256 byte, vedi
contenere il nome del file, e questa è la ragione principale per cui questa
funzione è deprecata.
-Una seconda funzione simile è \func{char * get\_current\_dir\_name(void)} che
-è sostanzialmente equivalente ad una \func{getcwd(NULL, 0)}, con la sola
+Una seconda funzione simile è \code{char *get\_current\_dir\_name(void)} che è
+sostanzialmente equivalente ad una \code{getcwd(NULL, 0)}, con la sola
differenza che essa ritorna il valore della variabile di ambiente \macro{PWD},
che essendo costruita dalla shell può contenere anche dei riferimenti
-simbolici; nel caso di \func{getcwd} infatti, essendo il pathname ricavato
+simbolici; nel caso di \func{getcwd} infatti, essendo il pathname ricavato
risalendo all'indietro l'albero della directory, si perderebbe traccia di ogni
passaggio attraverso eventuali pathname.
non solo tramite il filename, i prototipi di queste funzioni sono:
\begin{functions}
\headdecl{unistd.h}
- \funcdecl{int chdir (const char * path)}
+ \funcdecl{int chdir(const char *path)}
Cambia la directory di lavoro corrente a quella specificata dal pathname
contenuto nella stringa \var{path}.
- \funcdecl{int fchdir (int fd)} Analoga alla precedente, ma
- usa un file descriptor invece del pathname.
+ \funcdecl{int fchdir(int fd)} Analoga alla precedente, ma usa un file
+ descriptor invece del pathname.
\bodydesc{Entrambe le funzioni restituiscono zero in caso di successo
e -1 per un errore, in caso di errore \var{errno} viene settata per
\func{chdir} ai valori:
\begin{errlist}
- \item[\macro{ENOTDIR}] Uno dei componenti di \var{path} non è una directory.
+ \item[\macro{ENOTDIR}] Uno dei componenti di \param{path} non è una
+ directory.
\item[\macro{EACCESS}] Manca il permesso di ricerca su uno dei componenti di
- \func{path}.
+ \param{path}.
\end{errlist}
ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
\macro{ENOMEM}, \macro{ELOOP} e \macro{EIO}. Per \func{fchdir} invece gli
+\subsection{I file temporanei}
+\label{sec:file_temp_file}
+
+Un'altra serie di funzioni definite dalle librerie standard del C sono quelle
+che riguardano la creazione di file temporanei.
+
+
+
+
\section{La manipolazione delle caratteristiche dei files}
\label{sec:file_infos}
che corrisponda all'occupazione dello spazio su disco per via della possibile
esistenza dei cosiddetti \textsl{buchi} (detti normalmente \textit{holes}) che
si formano tutte le volte che si va a scrivere su un file dopo aver eseguito
-una \func{seek} (vedi \secref{sec:file_lseek}) oltre la sua conclusione
+una \func{lseek} (vedi \secref{sec:file_lseek}) oltre la sua conclusione
corrente.
In tal caso si avranno differenti risultati a seconda del modi in cui si
risultato di \cmd{ls}.
Se è sempre possibile allargare un file, scrivendoci sopra od usando la
-funzione \func{seek} per spostarsi oltre la sua fine, esistono anche casi in
+funzione \func{lseek} per spostarsi oltre la sua fine, esistono anche casi in
cui si può avere bisogno di effettuare un troncamento, scartando i dati
presenti al di là della dimensione scelta come nuova fine del file.
I tempi di ultimo accesso e modifica possono essere cambiati usando la
funzione \func{utime}, il cui prototipo è:
\begin{prototype}{utime.h}
-{int utime(const char * filename, struct utimbuf *times)}
+{int utime(const char *filename, struct utimbuf *times)}
Cambia i tempi di ultimo accesso e modifica dell'inode specificato da
-\var{filename} secondo i campi \var{actime} e \var{modtime} di \var{times}. Se
-questa è \macro{NULL} allora viene usato il tempo corrente.
+\param{filename} secondo i campi \var{actime} e \var{modtime} di
+\param{times}. Se questa è \macro{NULL} allora viene usato il tempo corrente.
\bodydesc{La funzione restituisce zero in caso di successo e -1 in caso
di errore, nel qual caso \var{errno} è settata opportunamente.
\begin{errlist}
\item[\macro{EACCESS}] non si ha il permesso di scrittura sul file.
-\item[\macro{ENOENT}] \var{filename} non esiste.
+\item[\macro{ENOENT}] \param{filename} non esiste.
\end{errlist}}
\end{prototype}
\end{lstlisting}
L'effetto della funzione e i privilegi necessari per eseguirla dipendono da
-cosa è l'argomento \var{times}; se è \macro{NULL} la funzione setta il tempo
+cosa è l'argomento \param{times}; se è \macro{NULL} la funzione setta il tempo
corrente ed è sufficiente avere accesso in scrittura al file; se invece si è
specificato un valore la funzione avrà successo solo se si è proprietari del
file (o si hanno i privilegi di amministratore).
I passi attraverso i quali viene stabilito se il processo possiede il diritto
di accesso sono i seguenti:
-\begin{itemize}
+\begin{enumerate}
\item Se l'\textit{effective user id} del processo è zero (corrispondente
all'amministratore) l'accesso è sempre garantito senza nessun ulteriore
controllo. Per questo motivo \textsl{root} ha piena libertà di accesso a
\item Se l'\textit{effective user id} del processo è uguale all'\acr{uid} del
proprietario del file (nel qual caso si dice che il processo è proprietario
del file) allora:
- \begin{itemize}
+ \begin{itemize*}
\item se il relativo\footnote{per relativo si intende il bit di user-read se
il processo vuole accedere in scrittura, quello di user-write per
l'accesso in scrittura, etc.} bit dei permessi d'accesso dell'utente è
settato, l'accesso è consentito
\item altrimenti l'accesso è negato
- \end{itemize}
+ \end{itemize*}
\item Se l'\textit{effective group id} del processo o uno dei
\textit{supplementary group id} dei processi corrispondono al \acr{gid} del
file allora:
- \begin{itemize}
+ \begin{itemize*}
\item se il bit dei permessi d'accesso del gruppo è settato, l'accesso è
consentito,
\item altrimenti l'accesso è negato
- \end{itemize}
+ \end{itemize*}
\item se il bit dei permessi d'accesso per tutti gli altri è settato,
l'accesso è consentito, altrimenti l'accesso è negato.
-\end{itemize}
+\end{enumerate}
Si tenga presente che questi passi vengono eseguiti esattamente in
quest'ordine. Questo vuol dire che se un processo è il proprietario di un file
la supporta, così come BSD e SVR4}, in questo caso se il bit è settato un
file potrà essere rimosso dalla directory soltanto se l'utente ha il permesso
di scrittura ed inoltre è vera una delle seguenti condizioni:
-\begin{itemize}
+\begin{itemize*}
\item l'utente è proprietario del file
\item l'utente è proprietario della directory
\item l'utente è l'amministratore
-\end{itemize}
+\end{itemize*}
un classico esempio di directory che ha questo bit settato è \file{/tmp}, i
permessi infatti di solito sono settati come:
\begin{verbatim}
Lo standard POSIX prescrive che l'\acr{uid} del nuovo file corrisponda
all'\textit{effective user id} del processo che lo crea; per il \acr{gid}
invece prevede due diverse possibilità:
-\begin{itemize}
+\begin{itemize*}
\item il \acr{gid} del file corrisponde all'\textit{effective group id} del
processo.
\item il \acr{gid} del file corrisponde al \acr{gid} della directory in cui
esso è creato.
-\end{itemize}
+\end{itemize*}
in genere BSD usa sempre la seconda possibilità, che viene per questo chiamata
semantica BSD. Linux invece segue quella che viene chiamata semantica SVr4; di
norma cioè il nuovo file viene creato, seguendo la prima opzione, con il
alcune limitazioni, provviste per motivi di sicurezza. Questo significa che
anche se si è proprietari del file non tutte le operazioni sono permesse, in
particolare:
-\begin{itemize}
+\begin{enumerate}
\item siccome solo l'amministratore può settare lo \textit{sticky bit}; se
l'\textit{effective user id} del processo non è zero esso viene
automaticamente cancellato (senza notifica di errore) qualora sia stato
notifica di errore) da \var{mode} qualora il gruppo del file non corrisponda
a quelli associati al processo (la cosa non avviene quando
l'\textit{effective user id} del processo è zero).
-\end{itemize}
+\end{enumerate}
Per alcuni filesystem\footnote{il filesystem \acr{ext2} supporta questa
caratteristica, che è mutuata da BSD.} è inoltre prevista una ulteriore
%completo vedi \ntab), i permessi (vedi \secref{sec:file_perms}), le date (vedi
%\secref{sec:file_times}).
-
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 tutto quello che occorre è chiamare la funzione
-\func{register\_filesystem} passandole un'apposita struttura
+\code{register\_filesystem} passandole un'apposita struttura
(\var{file\_system\_type}) che contiene i dettagli per il riferimento
all'implementazione del medesimo, che sarà aggiunta alla citata tabella.
pathname il VFS deve creare una nuova \textit{dentry} e caricare l'inode
corrispondente in memoria.
-Questo procedimento viene eseguito dal metodo \func{lookup()} dell'inode
+Questo procedimento viene eseguito dal metodo \code{lookup()} 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.
\textbf{Funzione} & \textbf{Operazione} \\
\hline
\hline
- \textsl{\func{open}} & apre il file \\
- \textsl{\func{read}} & legge dal file \\
- \textsl{\func{write}} & scrive sul file \\
- \textsl{\func{llseek}} & sposta la posizione corrente sul file \\
- \textsl{\func{ioctl}} & accede alle operazioni di controllo
+ \textsl{\code{open}} & apre il file \\
+ \textsl{\code{read}} & legge dal file \\
+ \textsl{\code{write}} & scrive sul file \\
+ \textsl{\code{llseek}} & sposta la posizione corrente sul file \\
+ \textsl{\code{ioctl}} & accede alle operazioni di controllo
(tramite la \func{ioctl})\\
- \textsl{\func{readdir}}& per leggere il contenuto di una directory \\
- \textsl{\func{poll}} & \\
- \textsl{\func{mmap}} & chiamata dalla system call \func{mmap}.
+ \textsl{\code{readdir}}& per leggere il contenuto di una directory \\
+ \textsl{\code{poll}} & \\
+ \textsl{\code{mmap}} & chiamata dalla system call \func{mmap}.
mappa il file in memoria\\
- \textsl{\func{release}}& chiamata quando l'ultima referenza a un file
+ \textsl{\code{release}}& chiamata quando l'ultima referenza a un file
aperto è chiusa\\
- \textsl{\func{fsync}} & chiamata dalla system call \func{fsync} \\
- \textsl{\func{fasync}} & chiamate da \func{fcntl} quando è abilitato
+ \textsl{\code{fsync}} & chiamata dalla system call \func{fsync} \\
+ \textsl{\code{fasync}} & chiamate da \func{fcntl} quando è abilitato
il modo asincrono per l'I/O su file. \\
\hline
\end{tabular}
Così sarà possibile scrivere sulla porta seriale come su un file di dati
normale; ovviamente certe operazioni (nel caso della seriale ad esempio la
-\func{seek}) non saranno disponibili, però con questo sistema l'utilizzo di
+\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.
viene settata al valore ricevuto dalla funzione sottostante di cui è
fallita l'esecuzione.
- Gli errori pertanto possono essere quelli di \func{malloc} per tutte
+ Gli errori pertanto possono essere quelli di \code{malloc} per tutte
e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
\func{fcntl} per \func{fdopen} e quelli di \func{fopen},
\func{fclose} e \func{fflush} per \func{freopen}.}
In realtà lo standard ANSI C prevede un totale di 15 possibili valori
diversi per \param{mode}, ma in \tabref{tab:file_fopen_mode} si sono
riportati solo i sei valori effettivi, ad essi può essere aggiunto pure
-il carattere \func{b} (come ultimo carattere o nel mezzo agli altri per
+il carattere \texttt{b} (come ultimo carattere o nel mezzo agli altri per
le stringhe di due caratteri) che in altri sistemi operativi serve a
distinguere i file binari dai file di testo; in un sistema POSIX questa
distinzione non esiste e il valore viene accettato solo per
\func{rewind} prima di eseguire una rilettura; viceversa nel caso in cui si
voglia fare una scrittura subito dopo aver eseguito una lettura occorre prima
usare una delle funzioni \func{fseek}, \func{fsetpos} o \func{rewind}. Anche
-una operazione nominalmente nulla come \func{fseek(file, 0, SEEK\_CUR)} è
+una 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
maggior parte dei casi questo avviene con la restituzione del valore
intero (di tipo \type{int}) \macro{EOF}\footnote{la costante deve essere
negativa, le \acr{glibc} usano -1, altre implementazioni possono avere
- valori diversi.} definito anch'esso nell'header \func{stdlib.h}.
+ 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 settano direttamente la
elemento.
In realtà quello che conta nel trasferimento dei dati sono le dimensioni
-totali, che sono sempre pari al prodotto \func{size * nelem}; la sola
+totali, che sono sempre pari al prodotto \code{size * nelem}; la sola
differenza è che le funzioni non ritornano il numero di byte scritti,
ma il numero di elementi.
\funcdecl{int fgetc(FILE *stream)} Legge un byte da \param{stream} e lo
restituisce come intero. È una sempre una funzione.
- \funcdecl{int getchar(void)} Equivalente a \func{getc(stdin)}.
+ \funcdecl{int getchar(void)} Equivalente a \code{getc(stdin)}.
\bodydesc{Tutte queste funzioni leggono un byte alla volta, che viene
restituito come intero; in caso di errore o fine del file il valore
\funcdecl{wint\_t fgetwc(FILE *stream)} Legge un carattere esteso da
\param{stream} È una sempre una funzione.
- \funcdecl{wint\_t getwchar(void)} Equivalente a \func{getwc(stdin)}.
+ \funcdecl{wint\_t getwchar(void)} Equivalente a \code{getwc(stdin)}.
\bodydesc{Tutte queste funzioni leggono un carattere alla volta, in
caso di errore o fine del file il valore di ritorno è \macro{WEOF}.}
\funcdecl{int fputc(FILE *stream)} Scrive il carattere \param{c} su
\param{stream}. È una sempre una funzione.
- \funcdecl{int putchar(void)} Equivalente a \func{putc(stdin)}.
+ \funcdecl{int putchar(void)} Equivalente a \code{putc(stdin)}.
\bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui
valore viene restituito in caso di successo; in caso di errore o
Come nel caso dell'I/O binario le \acr{glibc} provvedono per ciascuna
delle funzioni precedenti, come estensione GNU, una seconda funzione, il
-cui nome è ottenuto aggiungendo un \func{\_unlocked}, che esegue
+cui nome è ottenuto aggiungendo un \code{\_unlocked}, che esegue
esattamente le stesse operazioni evitando però il lock implicito dello
stream.
Come nel caso dell'I/O binario e a caratteri nelle \acr{glibc} sono
previste una serie di altre funzioni, estensione di tutte quelle
illustrate finora (eccetto \func{gets} e \func{puts}), il cui nome si
-ottiene aggiungendo un \func{\_unlocked}, e che eseguono esattamente le
+ottiene aggiungendo un \code{\_unlocked}, e che eseguono esattamente le
stesse operazioni delle loro equivalenti, evitando però il lock
implicito dello stream (vedi \secref{sec:file_stream_thread}).
Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e
\func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre
estensioni permettono di scrivere con caratteri estesi. Anche queste funzioni,
-il cui nome è generato dalle precedenti funzioni aggiungendo una \func{w}
-davanti a \func{print}, sono trattate in dettaglio nella documentazione delle
+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
\secref{sec:file_lseek}. La funzione restituisce 0 in caso di successo e -1
in caso di errore. La funzione \func{rewind} riporta semplicemente la
posizione corrente all'inzio dello stream, ma non esattamente equivalente ad
-una \func{fseek(stream, 0L, SEEK\_SET)} in quanto vengono cancellati anche i
+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 \func{ftell}, il
\headdecl{stdio.h}
\funcdecl{int fsetpos(FILE *stream, fpos\_t *pos)} Setta la posizione
- corrente nello stream \param{stream} al valore specificato da \func{pos}.
+ corrente nello stream \param{stream} al valore specificato da \param{pos}.
\funcdecl{int fgetpos(FILE *stream, fpos\_t *pos)} Scrive la posizione
- corrente nello stream \param{stream} in \func{pos}.
+ corrente nello stream \param{stream} in \param{pos}.
\bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di
errore.}
\begin{prototype}{stdio.h}{int setvbuf(FILE *stream, char *buf, int mode,
size\_t size)}
- Setta la bufferizzazione dello stream \func{stream} nella modalità indicata
- da \param{mode}, usando \func{buf} come buffer di lunghezza \param{size}.
+ Setta la bufferizzazione dello 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
caso di errore.}
La funzione permette di controllare tutti gli aspetti della bufferizzazione;
l'utente può specificare un buffer da usare al posto di quello allocato dal
sistema passandone alla funzione l'indirizzo in \param{buf} e la dimensione in
-\func{size}.
+\param{size}.
Ovviamente se si usa un buffer specificato dall'utente questo deve essere
stato allocato e restare disponibile per tutto il tempo in cui si opera sullo
\headdecl{stdio.h}
\funcdecl{void setbuf(FILE *stream, char *buf)} Disabilita la
- bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \func{buf}
+ bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \param{buf}
come buffer di dimensione \macro{BUFSIZ} in modalità \textit{fully buffered}.
\funcdecl{void setbuffer(FILE *stream, char *buf, size\_t size)} Disabilita
- la bufferizzazione se \param{buf} è \macro{NULL}, altrimenti usa \func{buf}
+ la bufferizzazione se \param{buf} è \macro{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à
necessario (come in tutti i programmi che non usano i thread), tutta la
procedura può comportare dei pesanti costi in termini di prestazioni. Per
questo motivo abbiamo visto in come per tutte le funzioni di I/O non
-formattato esistano delle versioni \func{\_unlocked} (alcune previste dallo
+formattato esistano delle versioni \code{\_unlocked} (alcune previste dallo
standard POSIX stesso, altre aggiunte come estenzioni dalle \acr{glibc}) che
possono essere usate in tutti questi casi\footnote{in certi casi dette
funzioni possono essere usate, visto che sono molto più efficiente, anche in
pertanto in grado di garantire prestazione enormemente più elevate.
La sostituizione di tutte le funzioni di I/O con le relative versioni
-\func{\_unlocked} in un programma che non usa i thread è però un lavoro
+\code{\_unlocked} in un programma che non usa i thread è però un lavoro
abbastanza noioso, e che appesantisce il codice; per questo motivo le
\acr{glibc} provvedono un'altra via per poter utilizzare disabilitare il
locking, anch'essa mutuata da estensioni introdotte in Solaris, cioè l'uso
di blocco dello stream.
\end{basedescript}
-
-\subsection{File temporanei}
-\label{sec:file_temp_file}
-
-Un'altra serie di funzioni definite dalle librerie standard del C sono quelle
-che riguardano la creazione di file temporanei.
\begin{prototype}{fcntl.h}
{int creat(const char *pathname, mode\_t mode)}
Crea un nuovo file vuoto, con i permessi specificati da \var{mode}. É del
- tutto equivalente a \func{open(filedes, O\_CREAT|O\_WRONLY|O\_TRUNC, mode)}.
+ tutto equivalente a \code{open(filedes, O\_CREAT|O\_WRONLY|O\_TRUNC, mode)}.
\end{prototype}
\noindent adesso questa funzione resta solo per compatibilità con i vecchi
programmi.
successo e -1 in caso di errore nel qual caso \var{errno} viene settata ad
uno dei valori:
\begin{errlist}
- \item[\macro{ESPIPE}] \var{fd} è una pipe, un socket o una fifo.
- \item[\macro{EINVAL}] \var{whence} non è un valore valido.
+ \item[\macro{ESPIPE}] \param{fd} è una pipe, un socket o una fifo.
+ \item[\macro{EINVAL}] \param{whence} non è un valore valido.
\end{errlist}
ed inoltre \macro{EBADF}.}
\end{functions}
-La nuova posizione è settata usando il valore specificato da \var{offset},
-sommato al riferimento dato da \var{whence}; quest'ultimo può assumere i
+La nuova posizione è settata usando il valore specificato da \param{offset},
+sommato al riferimento dato da \param{whence}; quest'ultimo può assumere i
seguenti valori\footnote{per compatibilità con alcune vecchie notazioni
questi valori possono essere rimpiazzati rispettivamente con 0, 1 e 2 o con
\macro{L\_SET}, \macro{L\_INCR} e \macro{L\_XTND}}:
kernel (cioè \var{f\_pos} in \var{file}, vedi \figref{fig:file_proc_file}).
Dato che la funzione ritorna la nuova posizione, usando il valore zero per
-\func{offset} si può riottenere la posizione corrente nel file chiamando la
-funzione con \func{lseek(fd, 0, SEEK\_CUR}.
+\param{offset} si può riottenere la posizione corrente nel file chiamando la
+funzione con \code{lseek(fd, 0, SEEK\_CUR}.
Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che
successiva scrittura avvenga alla fine del file, infatti se questo è stato
come vedremo in \secref{sec:sock_io_behav}), o per certi dispositivi, come le
unità a nastro, che restituiscono un singolo blocco di dati alla volta.
-In realtà anche le due condizioni segnalate dagli errori \func{EINTR} e
-\func{EAGAIN} non sono errori. La prima si verifica quando la \func{read} è
+In realtà anche le due condizioni segnalate dagli errori \macro{EINTR} e
+\macro{EAGAIN} non sono errori. La prima si verifica quando la \func{read} è
bloccata in attesa di dati in ingresso e viene interrotta da un segnale; in
tal caso l'azione da prendere è quella di rieseguire la funzione. Torneremo
sull'argomento in \secref{sec:signal_xxx}.
funzione di controllo dei file \func{fnctl} (che esamineremo in
\secref{sec:file_fcntl}) con il parametro \macro{F\_DUPFD}.
-L'operazione ha la sintassi \func{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
+L'operazione ha la sintassi \code{fnctl(oldfd, F\_DUPFD, newfd)} e se si usa 0
come valore per \param{newfd} diventa equivalente a \func{dup}. La sola
differenza, a parte i codici di errore, è che \func{dup2} chiude il nuovo file
se è già aperto mentre \func{fcntl} apre il primo disponibile con un valore
\documentclass[a4paper,11pt,twoside,italian]{book}
\usepackage[latin1]{inputenc}
\usepackage[bookmarks=true]{hyperref}
+\usepackage{makeidx}
\usepackage{booktabs}
\usepackage{pstcol}
\usepackage{pst-node}
\author{Simone Piccardi}
+\makeindex
+
\begin{document}
\pagenumbering{roman}
%\bibliographystyle{phaip}
%\bibliography{biblio}
+\printindex
+
+\end{document}
-\end{document}
\ No newline at end of file
Benchè BSD non sia uno standard formalizzato, l'implementazione di unix
dell'Università di Berkley, ha provveduto nel tempo una serie di estensioni e
-di API grande rilievo, come il link simbolici (vedi \secref{sec:file_symlink},
-la funzione \func{select}, i socket.
+di API grande rilievo, come il link simbolici, la funzione \code{select}, i
+socket.
Queste estensioni sono state via via aggiunte al sistema nelle varie versioni
del sistema (BSD 4.2, BSD 4.3 e BSD 4.4) come pure in alcuni derivati
% variables, macros, and everything can be useul,
%
\newcommand{\cmd}[1]{\texttt{#1}} % shell command
-\newcommand{\func}[1]{\texttt{#1}} % library function (or system call)
+\newcommand{\code}[1]{\texttt{#1}} % for simple code
+\newcommand{\func}[1]{%
+\index{\texttt{#1}}\texttt{#1}%
+} % library function (or system call)
\newcommand{\macro}[1]{\texttt{#1}} % macro constant
\newcommand{\var}[1]{\texttt{#1}} % variable
\newcommand{\file}[1]{\texttt{#1}} % file name
\end{prototype}
\noindent la funzione richiede come argomento l'indirizzo della opportuna
funzione di pulizia da chiamare all'uscita, che non deve prendere argomenti e
-non deve ritornare niente (deve essere essere cioè definita come \func{void
+non deve ritornare niente (deve essere essere cioè definita come \code{void
function(void)}).
Una estensione di \func{atexit} è la funzione \func{on\_exit}, che le
\cmd{-m}).
Per gestire le opzioni all'interno dei argomenti a linea di comando passati in
-\func{argv} le librerie standard del C forniscono la funzione \func{getopt}
+\var{argv} le librerie standard del C forniscono la funzione \func{getopt}
che ha il seguente prototipo:
\begin{prototype}{unistd.h}
{int getopt(int argc, char * const argv[], const char * optstring)}
Quando la funzione trova un'opzione essa ritorna il valore numerico del
carattere, in questo modo si possono eseguire azioni specifiche usando uno
-\func{switch}; \func{getopt} inoltre inizializza alcune variabili globali:
+\code{switch}; \func{getopt} inoltre inizializza alcune variabili globali:
\begin{itemize*}
-\item \var{char * optarg} contiene il puntatore alla stringa parametro
+\item \var{char *optarg} contiene il puntatore alla stringa parametro
dell'opzione.
\item \var{int optind} alla fine della scansione restituisce l'indice del
primo elemento di \var{argv} che non è un'opzione.
restituita da \func{getenv}, e sempre nella forma \var{NOME=valore}. Se la
variabile specificata non esiste la stringa sarà aggiunta all'ambiente, se
invece esiste il suo valore sarà settato a quello specificato da
-\func{string}. Si tenga presente che, seguendo lo standard SUSv2, le
+\param{string}. Si tenga presente che, seguendo lo standard SUSv2, le
\acr{glibc} successive alla versione 2.1.2 aggiungono\footnote{il
comportamento è lo stesso delle vecchie \acr{libc4} e \acr{libc5}; nelle
\acr{glibc}, dalla versione 2.0 alla 2.1.1, veniva invece fatta una copia,
Si tenga infine presente che se si passa a \func{putenv} solo il nome di una
variabile (cioè \param{string} è nella forma \texttt{NAME} e non contiene un
-\var{=}) allora questa viene cancellata dall'ambiente. Infine se la chiamata
+\texttt{=}) allora questa viene cancellata dall'ambiente. Infine se la chiamata
di \func{putenv} comporta la necessità di allocare una nuova versione del
vettore \var{environ} questo sarà allocato, ma la versione corrente sarà
deallocata solo se anch'essa è risultante da una allocazione fatta in
Il controllo del flusso di un programma in genere viene effettuato con le
varie istruzioni del linguaggio C, la più bistrattata delle quali è il
-\func{goto}, ampiamente deprecato in favore di costrutti più puliti; esiste
+\code{goto}, ampiamente deprecato in favore di costrutti più puliti; esiste
però un caso in l'uso di questa istruzione porta all'implementazione più
efficiente, quello dell'uscita in caso di errore.
\funcdecl{pid\_t wait4(pid\_t pid, int * status, int options, struct rusage
* rusage)}
È identica a \func{waitpid} sia per comportamento che per i
- valori dei parametri, ma restituisce in \var{rusage} un sommario delle
+ valori dei parametri, ma restituisce in \param{rusage} un sommario delle
risorse usate dal processo (per i dettagli vedi \secref{sec:sys_xxx})
+
\funcdecl{pid\_t wait3(int *status, int options, struct rusage *rusage)}
- Prima versione, equivalente a \func{wait4(-1, \&status, opt, rusage)} è
+ Prima versione, equivalente a \code{wait4(-1, \&status, opt, rusage)} è
ormai deprecata in favore di \func{wait4}.
\end{functions}
\noindent
liste devono essere terminate da un puntatore nullo. I vettori degli
argomenti e dell'ambiente possono essere acceduti dal nuovo programma
quando la sua funzione \func{main} è dichiarata nella forma
-\func{main(int argc, char *argv[], char *envp[])}.
+\code{main(int argc, char *argv[], char *envp[])}.
Le altre funzioni della famiglia servono per fornire all'utente una serie
possibile di diverse interfacce per la creazione di un nuovo processo. I loro
argomenti a linea di comando (cioè i valori di \var{argv} e \var{argc} visti
dalla funzione \func{main} del programma chiamato).
-Queste modalità sono due e sono riassunte dagli mnenonici \func{v} e \func{l}
+Queste modalità sono due e sono riassunte dagli mnenonici \code{v} e \code{l}
che stanno rispettivamente per \textit{vector} e \textit{list}. Nel primo caso
gli argomenti sono passati tramite il vettore di puntatori \var{argv[]} a
stringhe terminate con zero che costituiranno gli argomenti a riga di comando,
\end{table}
La seconda differenza fra le funzioni riguarda le modalità con cui si
-specifica il programma che si vuole eseguire. Con lo mnemonico \func{p} si
+specifica il programma che si vuole eseguire. Con lo mnemonico \code{p} si
indicano le due funzioni che replicano il comportamento della shell nello
specificare il comando da eseguire; quando il parametro \var{file} non
contiene una \file{/} esso viene considerato come un nome di programma, e
\end{figure}
La terza differenza è come viene passata la lista delle variabili di ambiente.
-Con lo mnemonico \func{e} vengono indicate quelle funzioni che necessitano di
+Con lo mnemonico \code{e} vengono indicate quelle funzioni che necessitano di
un vettore di parametri \var{envp[]} analogo a quello usato per gli argomenti
a riga di comando (terminato quindi da un \macro{NULL}), le altre usano il
valore della variabile \var{environ} (vedi \secref{sec:proc_environ}) del
\end{eqnarray*}
in questo modo, dato che l'\textit{effective group id} è quello giusto, il
programma può accedere a \file{/var/log/utmp} in scrittura ed aggiornarlo, a
-questo punto il programma può eseguire una \func{setgid(getgid())} per settare
+questo punto il programma può eseguire una \code{setgid(getgid())} per settare
l'\textit{effective group id} a quello dell'utente (e dato che il \textit{real
group id} corrisponde la funzione avrà successo), in questo modo non sarà
possibile lanciare dal terminale programmi che modificano detto file, in tal
e ogni processo lanciato dal terminale avrebbe comunque \acr{gid} come
\textit{effective group id}. All'uscita dal terminale, per poter di nuovo
aggiornare lo stato di \file{/var/log/utmp} il programma eseguirà una
-\func{setgid(utmp)} (dove \var{utmp} è il valore numerico associato al gruppo
+\code{setgid(utmp)} (dove \var{utmp} è il valore numerico associato al gruppo
\acr{utmp}, ottenuto ad esempio con una \func{getegid}), dato che in questo
caso il valore richiesto corrisponde al \textit{saved group id} la funzione
avrà successo e riporterà la situazione a:
disposizione due macro di compilatore, \macro{\_REENTRANT} e
\macro{\_THREAD\_SAFE}, la cui definizione attiva le versioni rientranti di
varie funzioni di libreria, che sono identificate aggiungendo il suffisso
-\func{\_r} al nome della versione normale.
+\code{\_r} al nome della versione normale.
la condizione non è più soddisfatta e il programma prosegue.
Il problema con l'implementazione inaffidabile è che niente ci garantisce che
-il segnale arrivi fra la valutazione della condizione del \func{while} e la
+il segnale arrivi fra la valutazione della condizione del \code{while} e la
chiamata a \func{pause}, nel qual caso, se il segnale non viene più generato,
il processo resterà in sleep permanentemente.
\subsection{Le funzioni \func{strsignal} e \func{psignal}}
\label{sec:sig_strsignal}
-Per la descrizione dei segnali il sistema mette a disposizione due funzioni
-che stampano un messaggio di descrizione dato il numero. In genere si usano
-quando si vuole notificare all'utente il segnale avvenuto (nel caso di
-terminazione di un processo figlio o di un manipolatore che gestisce più
-segnali); la prima funzione è una estensione GNU ed è analoga alla funzione
-\func{strerr} per gli errori:
-\begin{prototype}{string.h}{char * strsignal (int signum)}
- Ritorna il puntatore ad una stringa allocata staticamente che contiene la
- descrizione del segnale \var{signum}.
+Per la descrizione dei segnali il sistema mette a disposizione due funzioni,
+\func{strsignal} e \func{psignal}, che stampano un messaggio di descrizione
+dato il numero. In genere si usano quando si vuole notificare all'utente il
+segnale avvenuto (nel caso di terminazione di un processo figlio o di un
+manipolatore che gestisce più segnali); la prima funzione è una estensione
+GNU, accessibile avendo definito \macro{\_GNU\_SOURCE}, ed è analoga alla
+funzione \func{strerror} (si veda \secref{sec:sys_strerror}) per gli errori:
+\begin{prototype}{string.h}{char *strsignal(int signum)}
+ Ritorna il puntatore ad una stringa che contiene la descrizione del segnale
+ \var{signum}.
\end{prototype}
-
-Dato che la stringa è allocata staticamente non se ne deve modificare il
-contenuto, che resta valido solo fino alla successiva chiamata di
-\func{strsignal}; nel caso si debba mantenere traccia del messaggio sarà
+\noindent dato che la stringa è allocata staticamente non se ne deve
+modificare il contenuto, che resta valido solo fino alla successiva chiamata
+di \func{strsignal}. Nel caso si debba mantenere traccia del messaggio sarà
necessario copiarlo.
La seconda funzione deriva da BSD ed è analoga alla funzione \func{perror}
-descritta in \secref{sec:sys_strerror}.
+descritta in \secref{sec:sys_strerror}; il suo prototipo è:
+\begin{prototype}{signal.h}{void psignal(int sig, const char *s)}
+ Stampa sullo standard error un messaggio costituito dalla stringa \param{s},
+ seguita da due punti ed una descrizione del segnale indicato da \param{sig}.
+\end{prototype}
+
+Una modalità alternativa per utilizzare le descrizioni restituite da
+\func{strsignal} e \func{psignal} è quello di fare usare la variabile
+\var{sys\_siglist}, che può essere acceduta dichiarando:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ extern const char *const sys_siglist[]
+\end{lstlisting}
+\var{sys\_siglist} contiene le stringhe di descrizione indicizzate per numero
+di segnale, per cui \code{char *decr = strsignal(SIGINT)} può essere
+sostituito dall'equivalente \code{char *decr = sys\_siglist[SIGINT]}.
+
\section{La gestione dei segnali}
In questa definizione si è usato il tipo \type{sighandler\_t} che è una
estensione GNU definita in Linux che permette di riscrivere il prototipo in
-forma più leggibile dell'originario \func{void (*signal(int signum, void
+forma più leggibile dell'originario \code{void (*signal(int signum, void
(*handler)(int)))int)}, e che è sostanzialmente equivalente alla
definizione:
\begin{verbatim}
\label{sec:TCPsimp_server_main}
La prima versione del server, \file{ElemEchoTCPServer.c}, si compone di un
-corpo principale, costituito dalla funzione \func{main}. Questa si incarica
+corpo principale, costituito dalla funzione \code{main}. Questa si incarica
di creare il socket, metterlo in ascolto di connessioni in arrivo e creare un
processo figlio a cui delegare la gestione di ciascuna connessione. Questa
parte, riportata in \nfig, è analoga a quella vista nel precedente esempio
exit(0);
}
\end{lstlisting}
- \caption{Codice della funzione \texttt{main} della prima versione del server
+ \caption{Codice della funzione \code{main} della prima versione del server
per il servizio \texttt{echo}.}
\label{fig:TCPsimpl_serv_code}
\end{figure}
\secref{sec:TCPel_cunc_daytime}. Le uniche differenze rispetto all'esempio in
\figref{fig:TCPel_serv_code} sono che in questo caso per il socket in
ascolto viene usata la porta 7 e tutta la gestione della comunicazione è
-delegata alla funzione \func{ServEcho}.
+delegata alla funzione \code{ServEcho}.
% Per ogni connessione viene creato un
% processo figlio, il quale si incarica di lanciare la funzione
% \texttt{SockEcho}.
-Il codice della funzione \func{ServEcho} è invece mostrata in \nfig, la
+Il codice della funzione \code{ServEcho} è invece mostrata in \nfig, la
comunicazione viene gestita all'interno del ciclo (linee \texttt{\small
6--8}). I dati inviati dal client vengono letti dal socket con una semplice
\func{read} (che ritorna solo in presenza di dati in arrivo), la riscrittura
return;
}
\end{lstlisting}
- \caption{Codice della prima versione della funzione \func{ServEcho} per la
+ \caption{Codice della prima versione della funzione \code{ServEcho} per la
gestione del servizio \texttt{echo}.}
\label{fig:TCPsimpl_server_elem_sub}
\end{figure}
\label{fig:TCPsimpl_client_elem}
\end{figure}
-La funzione \func{main} si occupa della creazione del socket e della
+La funzione \code{main} si occupa della creazione del socket e della
connessione (linee \texttt{\small 10--27}) secondo la stessa modalità spiegata
in \secref{sec:net_cli_sample}, il client si connette sulla porta 7
all'indirizzo specificato dalla linea di comando (a cui si è aggiunta una
elementare gestione delle opzioni non riportata in figura).
Completata la connessione (quando la funzione \func{connect} ritorna) la
-funzione \func{ClientEcho}, riportata in \nfig, si preoccupa di gestire la
+funzione \code{ClientEcho}, riportata in \nfig, si preoccupa di gestire la
comunicazione, leggendo una riga alla volta dallo \file{stdin}, scrivendola
sul socket e ristampando su \file{stdout} quanto ricevuto in risposta dal
server.
La funzione utilizza due buffer per gestire i dati inviati e letti sul socket
(\texttt{\small 3}). La comunicazione viene gestita all'interno di un ciclo
(linee \texttt{\small 5--10}), i dati da inviare sulla connessione vengono
-presi dallo \texttt{stdin} usando la funzione \func{fgets} che legge una
+presi dallo \file{stdin} usando la funzione \func{fgets} che legge una
linea di testo (terminata da un \texttt{CR} e fino al massimo di
-\texttt{MAXLINE} caratteri) e la salva sul buffer di invio, la funzione
+\macro{MAXLINE} caratteri) e la salva sul buffer di invio, la funzione
\func{SockWrite} (\texttt{\small 3}) scrive detti dati sul socket (gestendo
l'invio multiplo qualora una singola \func{write} non basti, come spiegato
in \secref{sec:sock_io_behav}).
\end{verbatim}
mentre per quanto riguarda l'esecuzione dei programmi avremo che:
\begin{itemize}
-\item il client chiama la funzione \func{ClientEcho} che si blocca sulla
+\item il client chiama la funzione \code{ClientEcho} che si blocca sulla
\func{fgets} dato che non si è ancora scritto nulla sul terminale.
\item il server eseguirà una \func{fork} facendo chiamare al processo figlio
- la funzione \func{ServEcho}, quest'ultima si bloccherà sulla \func{read}
+ la funzione \code{ServEcho}, quest'ultima si bloccherà sulla \func{read}
dal socket sul quale ancora non sono presenti dati.
\item il processo padre del server chiamerà di nuovo \func{accept}
bloccandosi fino all'arrivo di un'altra connessione.
tcp 0 0 *:echo *:* LISTEN
tcp 0 0 localhost:33032 localhost:echo TIME_WAIT
\end{verbatim} %$
-con il client che entra in \macro{TIME\_WAIT}.
+con il client che entra in \texttt{TIME\_WAIT}.
Esaminiamo allora in dettaglio la sequenza di eventi che porta alla
terminazione normale della connessione, che ci servirà poi da riferimento nei
\begin{enumerate}
\item inviando un carattere di EOF da terminale la \func{fgets} ritorna
restituendo un puntatore nullo che causa l'uscita dal ciclo di
- while, così la \func{ClientEcho} ritorna.
-\item al ritorno di \func{ClientEcho} ritorna anche la funzione \func{main}, e
+ while, così la \code{ClientEcho} ritorna.
+\item al ritorno di \code{ClientEcho} ritorna anche la funzione \code{main}, e
come parte del processo terminazione tutti i file descriptor vengono chiusi
(si ricordi quanto detto in \secref{sec:proc_term_conclusion}); questo causa
la chiusura del socket di comunicazione; il client allora invierà un FIN al
server a cui questo risponderà con un ACK. A questo punto il client verrà a
- trovarsi nello stato \macro{FIN\_WAIT\_2} ed il server nello stato
- \macro{CLOSE\_WAIT} (si riveda quanto spiegato in
+ trovarsi nello stato \texttt{FIN\_WAIT\_2} ed il server nello stato
+ \texttt{CLOSE\_WAIT} (si riveda quanto spiegato in
\secref{sec:TCPel_conn_term}).
\item quando il server riceve il FIN la \func{read} del processo figlio che
gestisce la connessione ritorna restituendo 0 causando così l'uscita dal
- ciclo di while e il ritorno di \func{ServEcho}, a questo punto il processo
+ ciclo di while e il ritorno di \code{ServEcho}, a questo punto il processo
figlio termina chiamando \func{exit}.
\item all'uscita del figlio tutti i file descriptor vengono chiusi, la
chiusura del socket connesso fa sì che venga effettuata la sequenza finale
di chiusura della connessione, viene emesso un FIN dal server che riceverà
un ACK dal client, a questo punto la connessione è conclusa e il client
- resta nello stato \func{TIME\_WAIT}.
+ resta nello stato \texttt{TIME\_WAIT}.
\item
\end{enumerate}
Converte l'intero a 16 bit \var{netshort} dal formato della rete a quello
della macchina.
\end{prototype}
-I nomi sono assegnati usando la lettera \func{n} come mnemonico per indicare
+I nomi sono assegnati usando la lettera \texttt{n} come mnemonico per indicare
l'ordinamento usato sulla rete (da \textit{network order}) e la lettera
-\func{h} come mnemonico per l'ordinamento usato sulla macchina locale (da
-\textit{host order}), mentre le lettere \func{s} e \func{l} stanno ad indicare
-i tipi di dato (\type{long} o \type{short}, riportati anche dai prototipi).
+\texttt{h} come mnemonico per l'ordinamento usato sulla macchina locale (da
+\textit{host order}), mentre le lettere \texttt{s} e \texttt{l} stanno ad
+indicare i tipi di dato (\type{long} o \type{short}, riportati anche dai
+prototipi).
Usando queste funzioni si ha la conversione automatica: nel caso in cui la
macchina che si sta usando abbia una architettura \textit{big endian} queste
indirizzi IPv4 da una stringa in cui il numero di IP è espresso secondo la
cosiddetta notazione \textit{dotted-decimal}, (cioè nella forma
\texttt{192.160.0.1}) al formato binario (direttamente in \textit{network
- order}) e viceversa; in questo caso si usa la lettera \func{a} come
+ order}) e viceversa; in questo caso si usa la lettera \texttt{a} come
mnemonico per indicare la stringa. Dette funzioni sono:
\begin{prototype}{arpa/inet.h}
{int inet\_aton(const char *src, struct in\_addr *dest)}
Le tre funzioni precedenti sono limitate solo ad indirizzi IPv4, per questo
motivo è preferibile usare le due nuove funzioni \func{inet\_pton} e
\func{inet\_ntop} che possono convertire anche gli indirizzi IPv6. Anche in
-questo caso le lettere \func{n} e \func{p} sono degli mnemonici per ricordare
-il tipo di conversione effettuata e stanno per \textit{presentation} e
-\textit{numeric}.
+questo caso le lettere \texttt{n} e \texttt{p} sono degli mnemonici per
+ricordare il tipo di conversione effettuata e stanno per \textit{presentation}
+e \textit{numeric}.
% \begin{figure}[htb]
% \centering
dato che l'UTC corrisponde all'ora locale di Greenwich. È il tempo su cui
viene mantenuto l'orologio del calcolatore, e viene usato ad esempio per
indicare le date di modifica dei file o quelle di avvio dei processi. Per
- memorizzare questo tempo è stato riservato il tipo primitivo \func{time\_t}.
+ memorizzare questo tempo è stato riservato il tipo primitivo \type{time\_t}.
\item \textit{process time}: talvolta anche detto tempo di CPU. Viene misurato
in \textit{clock tick}, corrispondenti al numero di interruzioni effettuate
dal timer di sistema, e che per Linux avvengono ogni centesimo di
secondo\footnote{eccetto per la piattaforma alpha dove avvengono ogni
millesimo di secondo}. Il dato primitivo usato per questo tempo è
- \func{clock\_t}, inoltre la costante \macro{HZ} restituisce la frequenza di
+ \type{clock\_t}, inoltre la costante \macro{HZ} restituisce la frequenza di
operazione del timer, e corrisponde dunque al numero di tick al secondo. Lo
standard POSIX definisce allo stesso modo la costante \macro{CLK\_TCK});
questo valore può comunque essere ottenuto con \func{sysconf} (vedi
Esamineremo in questa sezione le sue caratteristiche principali.
-\subsection{La variabile \func{errno}}
+\subsection{La variabile \var{errno}}
\label{sec:sys_errno}
Quasi tutte le funzioni delle librerie del C sono in grado di individuare e