From: Simone Piccardi Date: Sun, 19 Jun 2005 21:43:32 +0000 (+0000) Subject: Riordinamento completo degli indici. Create della macro ad hoc per la X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=b38fb9f5c8fb8360f7ac296baa8f4a0bdd692d1c Riordinamento completo degli indici. Create della macro ad hoc per la corretta indicizzazione delle parti scritte in italic. Corretti anche alcuni errori rilevati per l'occasione. --- diff --git a/errors.tex b/errors.tex index 385e8fa..adecb8e 100644 --- a/errors.tex +++ b/errors.tex @@ -39,7 +39,7 @@ gestione dei file. permessa: solo il proprietario del file o un processo con sufficienti privilegi può eseguire l'operazione. \item \errcode{ENOENT} \textit{No such file or directory}. Il file indicato - dal \index{\textit{pathname}}\textit{pathname} non esiste: o una delle + dal \itindex{pathname}\textit{pathname} non esiste: o una delle componenti non esiste o il \textit{pathname} contiene un link simbolico spezzato. Errore tipico di un riferimento ad un file che si suppone erroneamente essere esistente. @@ -61,9 +61,9 @@ gestione dei file. consentono l'operazione. \item \errcode{ELOOP} \textit{Too many symbolic links encountered}. Ci sono troppi link simbolici nella risoluzione di un - \index{\textit{pathname}}\textit{pathname}. + \itindex{pathname}\textit{pathname}. \item \errcode{ENAMETOOLONG} \textit{File name too long}. Si è indicato un - \textit{pathname} troppo lungo. + \itindex{pathname}\textit{pathname} troppo lungo. \item \errcode{ENOTBLK} \textit{Block device required}. Si è specificato un file che non è un \textit{block device} in un contesto in cui era necessario specificare un \textit{block device} (ad esempio si è tentato di montare un @@ -257,9 +257,9 @@ specificati nelle sezioni precedenti. \item \errcode{ENOMEM} \textit{No memory available}. Il kernel non è in grado di allocare ulteriore memoria per completare l'operazione richiesta. \item \errcode{EDEADLK} \textit{Deadlock avoided}. L'allocazione di una - risorsa avrebbe causato un \textit{deadlock}\index{\textit{deadlock}}. Non - sempre il sistema è in grado di riconoscere queste situazioni, nel qual caso - si avrebbe il blocco. + risorsa avrebbe causato un \textit{deadlock}\itindex{deadlock}. Non sempre + il sistema è in grado di riconoscere queste situazioni, nel qual caso si + avrebbe il blocco. \item \errcode{EFAULT} \textit{Bad address}. Una stringa passata come argomento è fuori dello spazio di indirizzi del processo, in genere questa situazione provoca l'emissione di un segnale di \textit{segment violation} diff --git a/fileadv.tex b/fileadv.tex index c91f34e..25e62d3 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -56,7 +56,7 @@ un'altro disponibile. Questo comporta nel migliore dei casi una operazione ritardata inutilmente nell'attesa del completamento di quella bloccata, mentre nel peggiore dei casi (quando la conclusione della operazione bloccata dipende da quanto si otterrebbe dal file descriptor ``\textsl{disponibile}'') si -potrebbe addirittura arrivare ad un \textit{deadlock}\index{\textit{deadlock}}. +potrebbe addirittura arrivare ad un \textit{deadlock}\itindex{deadlock}. Abbiamo già accennato in sez.~\ref{sec:file_open} che è possibile prevenire questo tipo di comportamento delle funzioni di I/O aprendo un file in @@ -66,7 +66,7 @@ eseguite sul file che si sarebbero bloccate, ritornano immediatamente, restituendo l'errore \errcode{EAGAIN}. L'utilizzo di questa modalità di I/O permette di risolvere il problema controllando a turno i vari file descriptor, in un ciclo in cui si ripete l'accesso fintanto che esso non viene garantito. -Ovviamente questa tecnica, detta \textit{polling}\index{\textit{polling}}, è +Ovviamente questa tecnica, detta \textit{polling}\itindex{polling}, è estremamente inefficiente: si tiene costantemente impiegata la CPU solo per eseguire in continuazione delle system call che nella gran parte dei casi falliranno. @@ -123,15 +123,15 @@ degli insiemi specificati (\param{readfds}, \param{writefds} e \param{exceptfds}), non diventa attivo, per un tempo massimo specificato da \param{timeout}. -\index{\textit{file~descriptor~set}|(} +\itindbeg{file~descriptor~set} + Per specificare quali file descriptor si intende \textsl{selezionare}, la funzione usa un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo \type{fd\_set}, che serve ad identificare un insieme di file descriptor, in maniera analoga a come un -\index{\textit{signal~set}}\textit{signal set} (vedi -sez.~\ref{sec:sig_sigset}) identifica un insieme di segnali. Per la -manipolazione di questi \textit{file descriptor set} si possono usare delle -opportune macro di preprocessore: +\itindex{signal~set}\textit{signal set} (vedi sez.~\ref{sec:sig_sigset}) +identifica un insieme di segnali. Per la manipolazione di questi \textit{file + descriptor set} si possono usare delle opportune macro di preprocessore: \begin{functions} \headdecl{sys/time.h} \headdecl{sys/types.h} @@ -186,7 +186,7 @@ ritorni; se impostato a \val{NULL} la funzione attende indefinitamente. Si pu specificare anche un tempo nullo (cioè una struttura \struct{timeval} con i campi impostati a zero), qualora si voglia semplicemente controllare lo stato corrente dei file descriptor. -\index{\textit{file~descriptor~set}|)} +\itindend{file~descriptor~set} La funzione restituisce il numero di file descriptor pronti,\footnote{questo è il comportamento previsto dallo standard, ma la standardizzazione della @@ -270,7 +270,7 @@ immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della funzione. L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili -race condition\index{\textit{race~condition}} quando ci si deve porre in +\textit{race condition}\itindex{race~condition} quando ci si deve porre in attesa sia di un segnale che di dati. La tecnica classica è quella di utilizzare il gestore per impostare una variabile globale e controllare questa nel corpo principale del programma; abbiamo visto in @@ -285,29 +285,29 @@ sotto controllo anche dei file descriptor con \func{select}, in questo caso si può fare conto sul fatto che all'arrivo di un segnale essa verrebbe interrotta e si potrebbero eseguire di conseguenza le operazioni relative al segnale e alla gestione dati con un ciclo del tipo: -\includecodesnip{listati/select_race.c} qui però emerge una race -condition,\index{\textit{race~condition}} perché se il segnale arriva prima -della chiamata a \func{select}, questa non verrà interrotta, e la ricezione -del segnale non sarà rilevata. +\includecodesnip{listati/select_race.c} qui però emerge una \textit{race + condition},\itindex{race~condition} perché se il segnale arriva prima della +chiamata a \func{select}, questa non verrà interrotta, e la ricezione del +segnale non sarà rilevata. Per questo è stata introdotta \func{pselect} che attraverso l'argomento \param{sigmask} permette di riabilitare la ricezione il segnale contestualmente all'esecuzione della funzione,\footnote{in Linux però non è presente la relativa system call, e la funzione è implementata nelle \acr{glibc} attraverso \func{select} (vedi \texttt{man select\_tut}) per cui - la possibilità di race condition permane; esiste però una soluzione, - chiamata \index{\textit{self-pipe trick}}\textit{self-pipe trick}, che - consiste nell'aprire una pipe (vedi sez.~\ref{sec:ipc_pipes}) ed usare - \func{select} sul capo in lettura della stessa, e indicare l'arrivo di un - segnale scrivendo sul capo in scrittura all'interno del manipolatore; in - questo modo anche se il segnale va perso prima della chiamata di - \func{select} questa lo riconoscerà comunque dalla presenza di dati sulla - pipe.} ribloccandolo non appena essa ritorna, così che il precedente codice -potrebbe essere riscritto nel seguente modo: -\includecodesnip{listati/pselect_norace.c} in questo caso utilizzando -\var{oldmask} durante l'esecuzione di \func{pselect} la ricezione del segnale -sarà abilitata, ed in caso di interruzione si potranno eseguire le relative -operazioni. + la possibilità di \itindex{race~condition}\textit{race condition} permane; + esiste però una soluzione, chiamata \itindex{self-pipe trick} + \textit{self-pipe trick}, che consiste nell'aprire una pipe (vedi + sez.~\ref{sec:ipc_pipes}) ed usare \func{select} sul capo in lettura della + stessa, e indicare l'arrivo di un segnale scrivendo sul capo in scrittura + all'interno del manipolatore; in questo modo anche se il segnale va perso + prima della chiamata di \func{select} questa lo riconoscerà comunque dalla + presenza di dati sulla pipe.} ribloccandolo non appena essa ritorna, così +che il precedente codice potrebbe essere riscritto nel seguente modo: +\includecodesnip{listati/pselect_norace.c} +in questo caso utilizzando \var{oldmask} durante l'esecuzione di +\func{pselect} la ricezione del segnale sarà abilitata, ed in caso di +interruzione si potranno eseguire le relative operazioni. @@ -977,6 +977,7 @@ si sono specificati nel vettore \param{vector}. \subsection{File mappati in memoria} \label{sec:file_memory_map} +\itindbeg{memory~mapping} Una modalità alternativa di I/O, che usa una interfaccia completamente diversa rispetto a quella classica vista in cap.~\ref{cha:file_unix_interface}, è il cosiddetto \textit{memory-mapped I/O}, che, attraverso il meccanismo della @@ -1003,7 +1004,7 @@ si pu \label{fig:file_mmap_layout} \end{figure} -L'uso del \textit{memory-mappung} comporta una notevole semplificazione delle +L'uso del \textit{memory-mapping} comporta una notevole semplificazione delle operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer intermedi su cui appoggiare i dati da traferire, poiché questi potranno essere acceduti direttamente nella sezione di memoria mappata; inoltre questa @@ -1135,7 +1136,7 @@ tab.~\ref{tab:file_mmap_flag}. privata cui solo il processo chiamante ha accesso. Le modifiche sono mantenute attraverso il meccanismo del \textit{copy on - write}\index{\textit{copy~on~write}} e + write}\itindex{copy~on~write} e salvate su swap in caso di necessità. Non è specificato se i cambiamenti sul file originale vengano riportati sulla regione @@ -1147,8 +1148,7 @@ tab.~\ref{tab:file_mmap_flag}. \const{MAP\_EXECUTABLE}& Ignorato. \\ \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva delle pagine di swap ad uso del meccanismo del - \textit{copy on - write}\index{\textit{copy~on~write}} + \textit{copy on write}\itindex{copy~on~write} per mantenere le modifiche fatte alla regione mappata, in questo caso dopo una scrittura, se non c'è più @@ -1365,6 +1365,7 @@ Indicare un intervallo che non contiene pagine mappate non Alla conclusione del processo, ogni pagina mappata verrà automaticamente rilasciata, mentre la chiusura del file descriptor usato per effettuare la mappatura in memoria non ha alcun effetto sulla stessa. +\itindend{memory~mapping} \section{Il file locking} @@ -1377,18 +1378,18 @@ diversi. In quell'occasione si in \textit{append mode}, quando più processi scrivono contemporaneamente sullo stesso file non è possibile determinare la sequenza in cui essi opereranno. -Questo causa la possibilità di race condition\index{\textit{race~condition}}; -in generale le situazioni più comuni sono due: l'interazione fra un processo -che scrive e altri che leggono, in cui questi ultimi possono leggere -informazioni scritte solo in maniera parziale o incompleta; o quella in cui -diversi processi scrivono, mescolando in maniera imprevedibile il loro output -sul file. +Questo causa la possibilità di una \textit{race condition} +\itindex{race~condition}; in generale le situazioni più comuni sono due: +l'interazione fra un processo che scrive e altri che leggono, in cui questi +ultimi possono leggere informazioni scritte solo in maniera parziale o +incompleta; o quella in cui diversi processi scrivono, mescolando in maniera +imprevedibile il loro output sul file. In tutti questi casi il \textit{file locking} è la tecnica che permette di -evitare le race condition\index{\textit{race~condition}}, attraverso una serie -di funzioni che permettono di bloccare l'accesso al file da parte di altri -processi, così da evitare le sovrapposizioni, e garantire la atomicità delle -operazioni di scrittura. +evitare le \textit{race condition}\itindex{race~condition}, attraverso una +serie di funzioni che permettono di bloccare l'accesso al file da parte di +altri processi, così da evitare le sovrapposizioni, e garantire la atomicità +delle operazioni di scrittura. @@ -1547,14 +1548,14 @@ anche se richiesto attraverso un file descriptor, agisce sempre su un file; perciò le informazioni relative agli eventuali \textit{file lock} sono mantenute a livello di inode\index{inode},\footnote{in particolare, come accennato in fig.~\ref{fig:file_flock_struct}, i \textit{file lock} sono - mantenuti un una \textit{linked~list}\index{\textit{linked list}} di - strutture \struct{file\_lock}. La lista è referenziata dall'indirizzo di - partenza mantenuto dal campo \var{i\_flock} della struttura \struct{inode} - (per le definizioni esatte si faccia riferimento al file \file{fs.h} nei - sorgenti del kernel). Un bit del campo \var{fl\_flags} di specifica se si - tratta di un lock in semantica BSD (\const{FL\_FLOCK}) o POSIX - (\const{FL\_POSIX}).} dato che questo è l'unico riferimento in comune che -possono avere due processi diversi che aprono lo stesso file. + mantenuti un una \textit{linked~list} di strutture \struct{file\_lock}. La + lista è referenziata dall'indirizzo di partenza mantenuto dal campo + \var{i\_flock} della struttura \struct{inode} (per le definizioni esatte si + faccia riferimento al file \file{fs.h} nei sorgenti del kernel). Un bit del + campo \var{fl\_flags} di specifica se si tratta di un lock in semantica BSD + (\const{FL\_FLOCK}) o POSIX (\const{FL\_POSIX}).} \itindex{linked~list} dato +che questo è l'unico riferimento in comune che possono avere due processi +diversi che aprono lo stesso file. \begin{figure}[htb] \centering @@ -1636,8 +1637,8 @@ essa viene usata solo secondo il prototipo: \item[\errcode{EDEADLK}] Si è richiesto un lock su una regione bloccata da un altro processo che è a sua volta in attesa dello sblocco di un lock mantenuto dal processo corrente; si avrebbe pertanto un - \textit{deadlock}\index{\textit{deadlock}}. Non è garantito che il - sistema riconosca sempre questa situazione. + \textit{deadlock}\itindex{deadlock}. Non è garantito che il sistema + riconosca sempre questa situazione. \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale prima di poter acquisire un lock. \end{errlist} @@ -1756,8 +1757,7 @@ stato effettivamente acquisito. \begin{figure}[htb] \centering \includegraphics[width=9cm]{img/file_lock_dead} - \caption{Schema di una situazione di - \textit{deadlock}\index{\textit{deadlock}}.} + \caption{Schema di una situazione di \textit{deadlock}\itindex{deadlock}.} \label{fig:file_flock_dead} \end{figure} @@ -1769,12 +1769,11 @@ un lock sulla regione 2 che non pu del processo 2; il processo 1 si bloccherà fintanto che il processo 2 non rilasci il blocco. Ma cosa accade se il processo 2 nel frattempo tenta a sua volta di ottenere un lock sulla regione A? Questa è una tipica situazione che -porta ad un \textit{deadlock}\index{\textit{deadlock}}, dato che a quel punto -anche il processo 2 si bloccherebbe, e niente potrebbe sbloccare l'altro -processo. Per questo motivo il kernel si incarica di rilevare situazioni di -questo tipo, ed impedirle restituendo un errore di \errcode{EDEADLK} alla -funzione che cerca di acquisire un lock che porterebbe ad un -\textit{deadlock}. +porta ad un \textit{deadlock}\itindex{deadlock}, dato che a quel punto anche +il processo 2 si bloccherebbe, e niente potrebbe sbloccare l'altro processo. +Per questo motivo il kernel si incarica di rilevare situazioni di questo tipo, +ed impedirle restituendo un errore di \errcode{EDEADLK} alla funzione che +cerca di acquisire un lock che porterebbe ad un \textit{deadlock}. \begin{figure}[!bht] \centering \includegraphics[width=13cm]{img/file_posix_lock} @@ -1802,7 +1801,7 @@ voce nella file table, ma con il valore del \acr{pid} del processo. Quando si richiede un lock il kernel effettua una scansione di tutti i lock presenti sul file\footnote{scandisce cioè la - \index{\textit{linked~list}}\textit{linked list} delle strutture + \itindex{linked~list}\textit{linked list} delle strutture \struct{file\_lock}, scartando automaticamente quelle per cui \var{fl\_flags} non è \const{FL\_POSIX}, così che le due interfacce restano ben separate.} per verificare se la regione richiesta non si sovrappone ad diff --git a/filedir.tex b/filedir.tex index 8618693..ea85603 100644 --- a/filedir.tex +++ b/filedir.tex @@ -93,20 +93,20 @@ chiamare questo tipo di associazione un collegamento diretto (o \textit{hard \errval{ENOSPC}, \errval{EIO}.} \end{prototype} -La funzione crea sul \index{\textit{pathname}}\textit{pathname} -\param{newpath} un collegamento diretto al file indicato da \param{oldpath}. -Per quanto detto la creazione di un nuovo collegamento diretto non copia il -contenuto del file, ma si limita a creare una voce nella directory specificata -da \param{newpath} e ad aumentare di uno il numero di riferimenti al file -(riportato nel campo \var{st\_nlink} della struttura \struct{stat}, vedi -sez.~\ref{sec:file_stat}) aggiungendo il nuovo nome ai precedenti. Si noti che -uno stesso file può essere così chiamato con vari nomi in diverse directory. +La funzione crea sul \itindex{pathname}\textit{pathname} \param{newpath} un +collegamento diretto al file indicato da \param{oldpath}. Per quanto detto la +creazione di un nuovo collegamento diretto non copia il contenuto del file, ma +si limita a creare una voce nella directory specificata da \param{newpath} e +ad aumentare di uno il numero di riferimenti al file (riportato nel campo +\var{st\_nlink} della struttura \struct{stat}, vedi sez.~\ref{sec:file_stat}) +aggiungendo il nuovo nome ai precedenti. Si noti che uno stesso file può +essere così chiamato con vari nomi in diverse directory. Per quanto dicevamo in sez.~\ref{sec:file_filesystem} la creazione di un collegamento diretto è possibile solo se entrambi i -\index{\textit{pathname}}\textit{pathname} sono nello stesso filesystem; -inoltre il filesystem deve supportare i collegamenti diretti (il meccanismo -non è disponibile ad esempio con il filesystem \acr{vfat} di Windows). +\itindex{pathname}\textit{pathname} sono nello stesso filesystem; inoltre il +filesystem deve supportare i collegamenti diretti (il meccanismo non è +disponibile ad esempio con il filesystem \acr{vfat} di Windows). 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 @@ -257,9 +257,8 @@ nello stesso filesystem) si usa invece la funzione \funcd{rename},\footnote{la \param{oldpath} o più in generale si è cercato di creare una directory come sotto-directory di se stessa. \item[\errcode{ENOTDIR}] Uno dei componenti dei - \index{\textit{pathname}}\textit{pathname} non è una directory o - \param{oldpath} è una directory e \param{newpath} esiste e non è una - directory. + \itindex{pathname}\textit{pathname} non è una directory o \param{oldpath} + è una directory e \param{newpath} esiste e non è una directory. \end{errlist} ed inoltre \errval{EACCES}, \errval{EPERM}, \errval{EMLINK}, \errval{ENOENT}, \errval{ENOMEM}, \errval{EROFS}, \errval{ELOOP} e @@ -458,7 +457,7 @@ directory 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 \index{\textit{pathname}}\textit{pathname} possano essere seguiti un numero +un \itindex{pathname}\textit{pathname} possano essere seguiti un numero limitato di link simbolici, il cui valore limite è specificato dalla costante \const{MAXSYMLINKS}. Qualora questo limite venga superato viene generato un errore ed \var{errno} viene impostata al valore \errcode{ELOOP}. @@ -523,7 +522,7 @@ per creare una directory La funzione crea una nuova directory vuota, che contiene cioè solo le due voci standard (\file{.} e \file{..}), con il nome indicato dall'argomento \param{dirname}. Il nome può essere indicato sia come -\index{\textit{pathname}}\textit{pathname} assoluto che relativo. +\itindex{pathname}\textit{pathname} assoluto che relativo. I permessi di accesso alla directory (vedi sez.~\ref{sec:file_access_control}) sono specificati da \param{mode}, i cui possibili valori sono riportati in @@ -559,7 +558,7 @@ prototipo La funzione cancella la directory \param{dirname}, che deve essere vuota (la directory deve cioè contenere soltanto le due voci standard \file{.} e \file{..}). Il nome può essere indicato con il -\index{\textit{pathname}}\textit{pathname} assoluto o relativo. +\itindex{pathname}\textit{pathname} assoluto o relativo. La modalità con cui avviene la cancellazione è analoga a quella di \func{unlink}: fintanto che il numero di link all'inode\index{inode} della @@ -768,11 +767,10 @@ con i thread; il suo prototipo \end{functions} La funzione restituisce in \param{result} (come -\index{\textit{value~result~argument}}\textit{value result argument}) -l'indirizzo dove sono stati salvati i dati, che di norma corrisponde a quello -della struttura precedentemente allocata e specificata dall'argomento -\param{entry} (anche se non è assicurato che la funzione usi lo spazio fornito -dall'utente). +\itindex{value~result~argument}\textit{value result argument}) l'indirizzo +dove sono stati salvati i dati, che di norma corrisponde a quello della +struttura precedentemente allocata e specificata dall'argomento \param{entry} +(anche se non è assicurato che la funzione usi lo spazio fornito dall'utente). I vari campi di \struct{dirent} contengono le informazioni relative alle voci presenti nella directory; sia BSD che SVr4\footnote{POSIX prevede invece solo @@ -1042,10 +1040,12 @@ concluse con successo. \subsection{La directory di lavoro} \label{sec:file_work_dir} +\itindbeg{pathname} + A ciascun processo è associata una directory nel filesystem che è chiamata \textsl{directory corrente} o \textsl{directory di lavoro} (in inglese \textit{current working directory}) che è quella a cui si fa riferimento -quando un \index{\textit{pathname}}\textit{pathname} è espresso in forma +quando un \itindsub{pathname}{relativo}\textit{pathname} è espresso in forma relativa, dove il ``\textsl{relativa}'' fa riferimento appunto a questa directory. @@ -1058,9 +1058,9 @@ sez.~\ref{sec:proc_fork}), la directory corrente della shell diventa anche la directory corrente di qualunque comando da essa lanciato. In genere il kernel tiene traccia per ciascun processo dell'inode\index{inode} -della directory di lavoro, per ottenere il -\index{\textit{pathname}}\textit{pathname} occorre usare una apposita funzione -di libreria, \funcd{getcwd}, il cui prototipo è: +della directory di lavoro, per ottenere il \textit{pathname} +occorre usare una apposita funzione di libreria, \funcd{getcwd}, il cui +prototipo è: \begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)} Legge il \textit{pathname} della directory di lavoro corrente. @@ -1078,10 +1078,10 @@ di libreria, \funcd{getcwd}, il cui prototipo \end{errlist}} \end{prototype} -La funzione restituisce il \index{\textit{pathname}}\textit{pathname} completo -della directory di lavoro nella stringa puntata da \param{buffer}, che deve -essere precedentemente allocata, per una dimensione massima di \param{size}. -Il buffer deve essere sufficientemente lungo da poter contenere il +La funzione restituisce il \textit{pathname} completo della directory di +lavoro nella stringa puntata da \param{buffer}, che deve essere +precedentemente allocata, per una dimensione massima di \param{size}. Il +buffer deve essere sufficientemente lungo da poter contenere il \textit{pathname} completo più lo zero di terminazione della stringa. Qualora esso ecceda le dimensioni specificate con \param{size} la funzione restituisce un errore. @@ -1090,27 +1090,25 @@ Si pu \param{buffer},\footnote{questa è un'estensione allo standard POSIX.1, supportata da Linux.} nel qual caso la stringa sarà allocata automaticamente per una dimensione pari a \param{size} qualora questa sia diversa da zero, o -della lunghezza esatta del \index{\textit{pathname}}\textit{pathname} -altrimenti. In questo caso ci si deve ricordare di disallocare la stringa una -volta cessato il suo utilizzo. +della lunghezza esatta del \textit{pathname} altrimenti. In questo caso ci si +deve ricordare di disallocare la stringa una volta cessato il suo utilizzo. 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 \const{PATH\_MAX} (di solito 256 byte, vedi sez.~\ref{sec:sys_limits}); il problema è che in Linux non esiste una -dimensione superiore per un \index{\textit{pathname}}\textit{pathname}, per -cui non è detto che il buffer sia sufficiente a contenere il nome del file, e -questa è la ragione principale per cui questa funzione è deprecata. +dimensione superiore per un \textit{pathname}, per cui non è detto che il +buffer sia sufficiente a contenere il nome del file, e questa è la ragione +principale per cui questa funzione è deprecata. 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 \val{PWD}, che essendo costruita dalla shell può contenere un \textit{pathname} comprendente anche dei link simbolici. Usando \func{getcwd} infatti, essendo -il \index{\textit{pathname}}\textit{pathname} ricavato risalendo all'indietro -l'albero della directory, si perderebbe traccia di ogni passaggio attraverso -eventuali link simbolici. +il \textit{pathname} ricavato risalendo all'indietro l'albero della directory, +si perderebbe traccia di ogni passaggio attraverso eventuali link simbolici. Per cambiare la directory di lavoro si può usare la funzione \funcd{chdir} (equivalente del comando di shell \cmd{cd}) il cui nome sta appunto per @@ -1132,9 +1130,8 @@ Per cambiare la directory di lavoro si pu quale si hanno i permessi di accesso. Dato che anche le directory sono file, è possibile riferirsi ad esse anche -tramite il file descriptor, e non solo tramite il -\index{\textit{pathname}}\textit{pathname}, per fare questo si usa -\funcd{fchdir}, il cui prototipo è: +tramite il file descriptor, e non solo tramite il \textit{pathname}, per fare +questo si usa \funcd{fchdir}, il cui prototipo è: \begin{prototype}{unistd.h}{int fchdir(int fd)} Identica a \func{chdir}, ma usa il file descriptor \param{fd} invece del \textit{pathname}. @@ -1149,6 +1146,8 @@ possibile (tutti gli altri sarebbero occorsi all'apertura di \param{fd}), quello in cui il processo non ha il permesso di accesso alla directory specificata da \param{fd}. +\itindend{pathname} + \subsection{I file temporanei} @@ -1159,7 +1158,7 @@ sembri semplice, in realt prima vista. Infatti anche se sembrerebbe banale generare un nome a caso e creare il file dopo aver controllato che questo non esista, nel momento fra il controllo e la creazione si ha giusto lo spazio per una possibile \textit{race - condition}\index{\textit{race~condition}} (si ricordi quanto visto in + condition}\itindex{race~condition} (si ricordi quanto visto in sez.~\ref{sec:proc_race_cond}). Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei, @@ -1239,7 +1238,7 @@ automaticamente cancellato alla sua chiusura o all'uscita dal programma. Lo standard non specifica in quale directory verrà aperto il file, ma le \acr{glibc} prima tentano con \const{P\_tmpdir} e poi con \file{/tmp}. Questa funzione è rientrante e non soffre di problemi di \textit{race - condition}\index{\textit{race~condition}}. + condition}\itindex{race~condition}. Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo caso si possono usare le vecchie funzioni \funcd{mktemp} e \func{mkstemp} che @@ -1260,7 +1259,7 @@ il suo prototipo \end{prototype} \noindent dato che \param{template} deve poter essere modificata dalla funzione non si può usare una stringa costante. Tutte le avvertenze riguardo -alle possibili \textit{race condition}\index{\textit{race~condition}} date per +alle possibili \textit{race condition}\itindex{race~condition} date per \func{tmpnam} continuano a valere; inoltre in alcune vecchie implementazioni il valore usato per sostituire le \code{XXXXXX} viene formato con il \acr{pid} del processo più una lettera, il che mette a disposizione solo 26 possibilità @@ -1311,7 +1310,7 @@ In OpenBSD \noindent la directory è creata con permessi \code{0700} (al solito si veda cap.~\ref{cha:file_unix_interface} per i dettagli); dato che la creazione della directory è sempre esclusiva i precedenti problemi di \textit{race - condition}\index{\textit{race~condition}} non si pongono. + condition}\itindex{race~condition} non si pongono. \section{La manipolazione delle caratteristiche dei files} @@ -1488,8 +1487,7 @@ poi si effettua il confronto con la combinazione di tipi scelta. Il campo \var{st\_size} contiene la dimensione del file in byte (se si tratta di un file regolare, nel caso di un link simbolico la dimensione è quella del -\index{\textit{pathname}}\textit{pathname} che contiene, per le fifo è sempre -nullo). +\itindex{pathname}\textit{pathname} che contiene, per le fifo è sempre nullo). Il campo \var{st\_blocks} definisce la lunghezza del file in blocchi di 512 byte. Il campo \var{st\_blksize} infine definisce la dimensione preferita per @@ -1541,7 +1539,7 @@ dimensione si possono usare le due funzioni \funcd{truncate} e \begin{errlist} \item[\errcode{EACCES}] il file non ha permesso di scrittura o non si ha il permesso di esecuzione una delle directory del - \index{\textit{pathname}}\textit{pathname}. + \itindex{pathname}\textit{pathname}. \item[\errcode{ETXTBSY}] Il file è un programma in esecuzione. \end{errlist} ed anche \errval{ENOTDIR}, \errval{ENAMETOOLONG}, \errval{ENOENT}, @@ -1874,15 +1872,15 @@ limiteremo ad un riassunto delle regole generali, entrando nei dettagli pi avanti. La prima regola è che per poter accedere ad un file attraverso il suo -\textit{pathname} occorre il permesso di esecuzione in ciascuna delle -directory che compongono il \textit{pathname}; lo stesso vale per aprire un -file nella directory corrente (per la quale appunto serve il diritto di -esecuzione). +\itindex{pathname}\textit{pathname} occorre il permesso di esecuzione in +ciascuna delle directory che compongono il \textit{pathname}; lo stesso vale +per aprire un file nella directory corrente (per la quale appunto serve il +diritto di esecuzione). Per una directory infatti il permesso di esecuzione significa che essa può -essere attraversata nella risoluzione del -\index{\textit{pathname}}\textit{pathname}, ed è distinto dal permesso di -lettura che invece implica che si può leggere il contenuto della directory. +essere attraversata nella risoluzione del \itindex{pathname}\textit{pathname}, +ed è distinto dal permesso di lettura che invece implica che si può leggere il +contenuto della directory. Questo significa che se si ha il permesso di esecuzione senza permesso di lettura si potrà lo stesso aprire un file in una directory (se si hanno i @@ -2520,20 +2518,20 @@ directory di lavoro, ha anche una directory \textsl{radice}\footnote{entrambe di norma corrispondente alla radice dell'albero di file e directory come visto dal kernel (ed illustrato in sez.~\ref{sec:file_organization}), ha per il processo il significato specifico di directory rispetto alla quale vengono -risolti i \index{\textit{pathname}!assoluto}\textit{pathname} +risolti i \itindsub{pathname}{assoluto}\textit{pathname} assoluti.\footnote{cioè quando un processo chiede la risoluzione di un \textit{pathname}, il kernel usa sempre questa directory come punto di partenza.} Il fatto che questo valore sia specificato per ogni processo apre allora la possibilità di modificare le modalità di risoluzione dei \textit{pathname} assoluti da parte di un processo cambiando questa directory, -così come si fa coi \index{\textit{pathname}!relativo}\textit{pathname} -relativi cambiando la directory di lavoro. +così come si fa coi \itindsub{pathname}{relativo}\textit{pathname} relativi +cambiando la directory di lavoro. Normalmente la directory radice di un processo coincide anche con la radice del filesystem usata dal kernel, e dato che il suo valore viene ereditato dal padre da ogni processo figlio, in generale i processi risolvono i -\index{\textit{pathname}!assoluto}\textit{pathname} assoluti a partire sempre -dalla stessa directory, che corrisponde alla \file{/} del sistema. +\itindsub{pathname}{assoluto}\textit{pathname} assoluti a partire sempre dalla +stessa directory, che corrisponde alla \file{/} del sistema. In certe situazioni però, per motivi di sicurezza, è utile poter impedire che un processo possa accedere a tutto il filesystem; per far questo si può @@ -2554,11 +2552,11 @@ prototipo \end{prototype} \noindent in questo modo la directory radice del processo diventerà \param{path} (che ovviamente deve esistere) ed ogni -\index{\textit{pathname}!assoluto}\textit{pathname} assoluto usato dalle -funzioni chiamate nel processo sarà risolto a partire da essa, rendendo -impossibile accedere alla parte di albero sovrastante. Si ha così quella che -viene chiamata una \textit{chroot jail}, in quanto il processo non può più -accedere a file al di fuori della sezione di albero in cui è stato +\itindsub{pathname}{assoluto}\textit{pathname} assoluto usato dalle funzioni +chiamate nel processo sarà risolto a partire da essa, rendendo impossibile +accedere alla parte di albero sovrastante. Si ha così quella che viene +chiamata una \textit{chroot jail}, in quanto il processo non può più accedere +a file al di fuori della sezione di albero in cui è stato \textsl{imprigionato}. Solo un processo con i privilegi di amministratore può usare questa funzione, @@ -2571,10 +2569,9 @@ Questo si cedono i privilegi di root. Infatti se per un qualche motivo il processo resta con la directory di lavoro fuori dalla \textit{chroot jail}, potrà comunque accedere a tutto il resto del filesystem usando -\index{\textit{pathname}!relativo}\textit{pathname} relativi, i quali, -partendo dalla directory di lavoro che è fuori della \textit{chroot jail}, -potranno (con l'uso di \texttt{..}) risalire fino alla radice effettiva del -filesystem. +\itindsub{pathname}{relativo}\textit{pathname} relativi, i quali, partendo +dalla directory di lavoro che è fuori della \textit{chroot jail}, potranno +(con l'uso di \texttt{..}) risalire fino alla radice effettiva del filesystem. Ma se ad un processo restano i privilegi di amministratore esso potrà comunque portare la sua directory di lavoro fuori dalla \textit{chroot jail} in cui si diff --git a/fileintro.tex b/fileintro.tex index 78c2a71..3ac9475 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -53,7 +53,7 @@ file ed introducendo le interfacce disponibili e le loro caratteristiche. \subsection{L'organizzazione di file e directory} \label{sec:file_organization} -\index{\textit{pathname}|(} +\itindbeg{pathname} In Unix, a differenza di quanto avviene in altri sistemi operativi, tutti i file vengono tenuti all'interno di un unico albero la cui radice (quella che viene chiamata \textit{root directory}) viene montata all'avvio. Un file @@ -115,10 +115,10 @@ Se il \textit{pathname} comincia per \texttt{/} la ricerca parte dalla directory radice del processo; questa, a meno di un \func{chroot} (su cui torneremo in sez.~\ref{sec:file_chroot}) è la stessa per tutti i processi ed equivale alla directory radice dell'albero dei file: in questo caso si parla -di un \textsl{pathname assoluto}\index{\textit{pathname}!assoluto}. Altrimenti -la ricerca parte dalla directory corrente (su cui torneremo in +di un \textsl{pathname assoluto} \itindsub{pathname}{assoluto}. Altrimenti la +ricerca parte dalla directory corrente (su cui torneremo in sez.~\ref{sec:file_work_dir}) ed il pathname è detto \textsl{pathname -relativo}\index{\textit{pathname}!relativo}. + relativo} \itindsub{pathname}{relativo}. I nomi \file{.} e \file{..} hanno un significato speciale e vengono inseriti in ogni directory: il primo fa riferimento alla directory corrente e il @@ -126,6 +126,7 @@ secondo alla directory \textsl{genitrice} (o \textit{parent directory}) cio la directory che contiene il riferimento alla directory corrente; nel caso la directory corrente coincida con la directory radice, allora il riferimento è a se stessa. +\itindend{pathname} \subsection{I tipi di file} @@ -135,7 +136,7 @@ Come detto in precedenza, in Unix esistono vari tipi di file; in Linux questi sono implementati come oggetti del \textit{Virtual File System} (vedi sez.~\ref{sec:file_vfs_work}) e sono presenti in tutti i filesystem unix-like utilizzabili con Linux. L'elenco dei vari tipi di file definiti dal -\textit{Virtual File System}\index{\textit{Virtual~File~System}} è riportato in +\textit{Virtual File System}\itindex{Virtual~File~System} è riportato in tab.~\ref{tab:file_file_types}. Si tenga ben presente che questa classificazione non ha nulla a che fare con @@ -329,15 +330,16 @@ Linux, l'\acr{ext2}. % introdotti qui alcuni termini che potranno comparire in seguito, come % \textit{inode}, \textit{dentry}, \textit{dcache}. +\itindbeg{Virtual~File~System} In Linux il concetto di \textit{everything is a file} è stato implementato -attraverso il \textit{Virtual File System}\index{\textit{Virtual~File~System}} -(da qui in avanti 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. Esso fornisce un livello di indirezione che permette -di collegare le operazioni di manipolazione sui file alle operazioni di I/O, e -gestisce l'organizzazione di queste ultime nei vari modi in cui i diversi -filesystem le effettuano, permettendo la coesistenza di filesystem differenti -all'interno dello stesso albero delle directory. +attraverso il \textit{Virtual File System} (da qui in avanti 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. Esso fornisce +un livello di indirezione che permette di collegare le operazioni di +manipolazione sui file alle operazioni di I/O, e gestisce l'organizzazione di +queste ultime nei vari modi in cui i diversi filesystem le effettuano, +permettendo la coesistenza di filesystem differenti all'interno dello stesso +albero delle directory. Quando un processo esegue una system call che opera su un file, il kernel chiama sempre una funzione implementata nel VFS; la funzione eseguirà le @@ -396,9 +398,8 @@ sui file gi \subsection{Il funzionamento del \textit{Virtual File System}} \label{sec:file_vfs_work} -La funzione più importante implementata dal -VFS\index{\textit{Virtual~File~System}} è la system call \func{open} che -permette di aprire un file. Dato un \index{\textit{pathname}}\textit{pathname} +La funzione più importante implementata dal VFS è la 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 @@ -426,7 +427,7 @@ La \textit{dcache} costituisce perci 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 -\index{\textit{pathname}}\textit{pathname} il VFS deve creare una nuova +\itindex{pathname}\textit{pathname} il VFS deve creare una nuova \textit{dentry} e caricare l'inode\index{inode} corrispondente in memoria. Questo procedimento viene eseguito dal metodo \code{lookup()} @@ -493,6 +494,7 @@ 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. +\itindend{Virtual~File~System} \subsection{Il funzionamento di un filesystem Unix} @@ -670,12 +672,12 @@ L'utilizzo di raggruppamenti di blocchi ha inoltre degli effetti positivi nelle prestazioni dato che viene ridotta la distanza fra i dati e la tabella degli inode\index{inode}. -Le directory sono implementate come una linked list con voci di dimensione -variabile. Ciascuna voce della lista contiene il numero di inode\index{inode}, -la sua lunghezza, il nome del file e la sua lunghezza, secondo lo schema in -fig.~\ref{fig:file_ext2_dirs}; in questo modo è possibile implementare nomi -per i file anche molto lunghi (fino a 1024 caratteri) senza sprecare spazio -disco. +Le directory sono implementate come una \itindex{linked~list}\textit{linked + list} con voci di dimensione variabile. Ciascuna voce della lista contiene +il numero di inode\index{inode}, la sua lunghezza, il nome del file e la sua +lunghezza, secondo lo schema in fig.~\ref{fig:file_ext2_dirs}; in questo modo +è possibile implementare nomi per i file anche molto lunghi (fino a 1024 +caratteri) senza sprecare spazio disco. diff --git a/filestd.tex b/filestd.tex index 4526eb0..b507ea0 100644 --- a/filestd.tex +++ b/filestd.tex @@ -746,10 +746,9 @@ viene restituito un \val{NULL}, ed il buffer \param{buf} non viene toccato. L'uso di \func{gets} è deprecato e deve essere assolutamente evitato; la funzione infatti non controlla il numero di byte letti, per cui nel caso la stringa letta superi le dimensioni del buffer, si avrà un \textit{buffer - overflow}\index{\textit{buffer~overflow}}, con sovrascrittura della memoria -del processo adiacente al buffer.\footnote{questa tecnica è spiegata in - dettaglio e con molta efficacia nell'ormai famoso articolo di Aleph1 - \cite{StS}.} + overflow}\itindex{buffer~overflow}, con sovrascrittura della memoria del +processo adiacente al buffer.\footnote{questa tecnica è spiegata in dettaglio + e con molta efficacia nell'ormai famoso articolo di Aleph1 \cite{StS}.} Questa è una delle vulnerabilità più sfruttate per guadagnare accessi non autorizzati al sistema (i cosiddetti \textit{exploit}), basta @@ -866,8 +865,8 @@ Se il buffer di destinazione subito, altrimenti il buffer viene allargato usando \func{realloc} e la nuova dimensione ed il nuovo puntatore vengono passata indietro (si noti infatti come per entrambi gli argomenti si siano usati dei -\index{\textit{value~result~argument}}\textit{value result argument}, passando -dei puntatori anziché i valori delle variabili, secondo la tecnica spiegata in +\itindex{value~result~argument}\textit{value result argument}, passando dei +puntatori anziché i valori delle variabili, secondo la tecnica spiegata in sez.~\ref{sec:proc_var_passing}). Se si passa alla funzione l'indirizzo di un puntatore impostato a \val{NULL} e @@ -876,7 +875,7 @@ necessaria a contenere la linea. In tutti i casi si ottiene dalla funzione un puntatore all'inizio del testo della linea letta. Un esempio di codice può essere il seguente: \includecodesnip{listati/getline.c} -e per evitare memory leak\index{\textit{memory~leak}} occorre ricordarsi di +e per evitare \textit{memory leak}\itindex{memory~leak} occorre ricordarsi di liberare \var{ptr} con una \func{free}. Il valore di ritorno della funzione indica il numero di caratteri letti @@ -931,9 +930,8 @@ quello specificato) la terza permette di stampare su una stringa, in genere l'uso di \func{sprintf} è sconsigliato in quanto è possibile, se non si ha la sicurezza assoluta sulle dimensioni del risultato della stampa, eccedere le dimensioni di \param{str}, con conseguente sovrascrittura di altre variabili e -possibili \textit{buffer overflow}\index{\textit{buffer~overflow}}; per questo -motivo si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo -è: +possibili \textit{buffer overflow}\itindex{buffer~overflow}; per questo motivo +si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo è: \begin{prototype}{stdio.h} {snprintf(char *str, size\_t size, const char *format, ...)} Identica a \func{sprintf}, ma non scrive su \param{str} più di @@ -1118,7 +1116,7 @@ scritti sulla stringa di destinazione: \param{size} caratteri. \end{prototype} \noindent in modo da evitare possibili buffer -overflow\index{\textit{buffer~overflow}}. +overflow\itindex{buffer~overflow}. Per eliminare alla radice questi problemi, le \acr{glibc} supportano una @@ -1140,14 +1138,15 @@ sono: \bodydesc{Le funzioni ritornano il numero di caratteri stampati.} \end{functions} + Entrambe le funzioni prendono come argomento \param{strptr} che deve essere l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà restituito (si ricordi quanto detto in sez.~\ref{sec:proc_var_passing} a -proposito dei \index{\textit{value~result~argument}}\textit{value result - argument}) l'indirizzo della stringa allocata automaticamente dalle -funzioni. Occorre inoltre ricordarsi di invocare \func{free} per liberare -detto puntatore quando la stringa non serve più, onde evitare memory -leak\index{\textit{memory~leak}}. +proposito dei \itindex{value~result~argument}\textit{value result argument}) +l'indirizzo della stringa allocata automaticamente dalle funzioni. Occorre +inoltre ricordarsi di invocare \func{free} per liberare detto puntatore quando +la stringa non serve più, onde evitare \textit{memory + leak}\itindex{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 diff --git a/fileunix.tex b/fileunix.tex index 4d91e52..e59fd06 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -34,7 +34,9 @@ tutte le implementazione di un sistema unix-like. \subsection{L'architettura dei \textit{file descriptor}} \label{sec:file_fd} -\index{file!descriptor|(} Per poter accedere al contenuto di un file occorre +\index{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 quanto visto in sez.~\ref{sec:file_vfs_work}). Questo si fa aprendo il file con la funzione \func{open} che provvederà a localizzare @@ -185,9 +187,8 @@ usando direttamente le system call del kernel. \label{sec:file_open} La funzione \funcd{open} è la funzione fondamentale per accedere ai file, ed è -quella che crea l'associazione fra un -\index{\textit{pathname}}\textit{pathname} ed un file descriptor, il suo -prototipo è: +quella che crea l'associazione fra un \itindex{pathname}\textit{pathname} ed +un file descriptor, il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/stat.h} @@ -344,10 +345,10 @@ valore pi \footnotetext[2]{la pagina di manuale di \func{open} segnala che questa opzione è difettosa su NFS, e che i programmi che la usano per stabilire un - \textsl{file di lock}\index{file!di lock} possono incorrere in una race - condition\index{\textit{race~condition}}. Si consiglia come alternativa di - usare un file con un nome univoco e la funzione \func{link} per verificarne - l'esistenza (vedi sez.~\ref{sec:ipc_file_lock}).} + \textsl{file di lock}\index{file!di lock} possono incorrere in una + \textit{race condition}\itindex{race~condition}. Si consiglia come + alternativa di usare un file con un nome univoco e la funzione \func{link} + per verificarne l'esistenza (vedi sez.~\ref{sec:ipc_file_lock}).} \footnotetext[3]{\textit{Denial of Service}\index{DoS}, si chiamano così attacchi miranti ad impedire un servizio causando una qualche forma di @@ -542,8 +543,8 @@ Si tenga presente inoltre che usare \const{SEEK\_END} non assicura affatto che la successiva scrittura avvenga alla fine del file, infatti se questo è stato aperto anche da un altro processo che vi ha scritto, la fine del file può essersi spostata, ma noi scriveremo alla posizione impostata in precedenza -(questa è una potenziale sorgente di \textit{race condition} -\index{\textit{race~condition}}, vedi sez.~\ref{sec:file_atomic}). +(questa è una potenziale sorgente di \itindex{race~condition}\textit{race + condition}, vedi sez.~\ref{sec:file_atomic}). Non tutti i file supportano la capacità di eseguire una \func{lseek}, in questo caso la funzione ritorna l'errore \errcode{EPIPE}. Questo, oltre che per @@ -843,8 +844,8 @@ sez.~\ref{sec:file_locking}). Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui vari processi devono scrivere alla fine di un file (ad esempio un file di log). Come accennato in sez.~\ref{sec:file_lseek} impostare la posizione alla -fine del file e poi scrivere può condurre ad una \textit{race - condition}\index{\textit{race~condition}}: infatti può succedere che un +fine del file e poi scrivere può condurre ad una +\itindex{race~condition}\textit{race condition}: infatti può succedere che un secondo processo scriva alla fine del file fra la \func{lseek} e la \func{write}; in questo caso, come abbiamo appena visto, il file sarà esteso, ma il nostro primo processo avrà ancora la posizione corrente impostata con la @@ -863,9 +864,9 @@ Un altro caso tipico in cui creare un \textsl{file di lock}\index{file!di lock}, bloccandosi se il file esiste. In questo caso la sequenza logica porterebbe a verificare prima l'esistenza del file con una \func{stat} per poi crearlo con una \func{creat}; -di nuovo avremmo la possibilità di una race -condition\index{\textit{race~condition}} da parte di un altro processo che -crea lo stesso file fra il controllo e la creazione. +di nuovo avremmo la possibilità di una \textit{race + condition}\itindex{race~condition} da parte di un altro processo che crea lo +stesso file fra il controllo e la creazione. Per questo motivo sono stati introdotti per \func{open} i due flag \const{O\_CREAT} e \const{O\_EXCL}. In questo modo l'operazione di controllo @@ -991,9 +992,9 @@ sull'altro (dato che quello che viene modificato della \textit{file table} a cui entrambi fanno riferimento). L'unica differenza fra due file descriptor duplicati è che ciascuno avrà il suo \textit{file descriptor flag}; a questo proposito va specificato che nel caso -di \func{dup} il flag di \textit{close-on-exec}\index{\textit{close-on-exec}} -(vedi sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}) viene sempre -cancellato nella copia. +di \func{dup} il flag di \textit{close-on-exec}\itindex{close-on-exec} (vedi +sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}) viene sempre cancellato +nella copia. L'uso principale di questa funzione è per la redirezione dell'input e dell'output fra l'esecuzione di una \func{fork} e la successiva \func{exec}; @@ -1091,10 +1092,10 @@ per \var{cmd} massimo numero di descrittori consentito. \item[\const{F\_SETFD}] imposta il valore del \textit{file descriptor flag} al valore specificato con \param{arg}. Al momento l'unico bit usato è quello di - \textit{close-on-exec}\index{\textit{close-on-exec}}, identificato dalla - costante \const{FD\_CLOEXEC}, che serve a richiedere che il file venga - chiuso nella esecuzione di una \func{exec} (vedi sez.~\ref{sec:proc_exec}). - Ritorna un valore nullo in caso di successo e -1 in caso di errore. + \textit{close-on-exec}\itindex{close-on-exec}, identificato dalla costante + \const{FD\_CLOEXEC}, che serve a richiedere che il file venga chiuso nella + esecuzione di una \func{exec} (vedi sez.~\ref{sec:proc_exec}). Ritorna un + valore nullo in caso di successo e -1 in caso di errore. \item[\const{F\_GETFD}] ritorna il valore del \textit{file descriptor flag} di \param{fd} o -1 in caso di errore; se \const{FD\_CLOEXEC} è impostato i file descriptor aperti vengono chiusi attraverso una \func{exec} altrimenti (il @@ -1284,8 +1285,10 @@ effettuata attraverso \func{ioctl} in quasi tutte le implementazioni di Unix), qui riportiamo solo i valori di alcuni comandi che sono definiti per ogni file: \begin{basedescript}{\desclabelwidth{2.0cm}} -\item[\const{FIOCLEX}] Imposta il bit di \textit{close on exec}. -\item[\const{FIONCLEX}] Cancella il bit di \textit{close on exec}. +\item[\const{FIOCLEX}] Imposta il flag di + \textit{close-on-exec}\itindex{close-on-exec}. +\item[\const{FIONCLEX}] Cancella il flag di + \textit{close-on-exec}\itindex{close-on-exec}. \item[\const{FIOASYNC}] Abilita l'I/O asincrono. \item[\const{FIONBIO}] Abilita l'I/O in modalità non bloccante. \end{basedescript} diff --git a/intro.tex b/intro.tex index fd82888..7cca8ce 100644 --- a/intro.tex +++ b/intro.tex @@ -62,11 +62,11 @@ all'hardware, mentre i programmi normali vengono eseguiti in modalit (e non possono accedere direttamente alle zone di memoria riservate o alle porte di input/output). -Una parte del kernel, lo \textit{scheduler}\index{\textit{scheduler}}, si -occupa di stabilire, ad intervalli fissi e sulla base di un opportuno calcolo -delle priorità, quale ``\textsl{processo}'' deve essere posto in esecuzione -(il cosiddetto \textit{preemptive - scheduling}\index{\textit{preemptive~scheduling}}). Questo verrà comunque +Una parte del kernel, lo \textit{scheduler}\itindex{scheduler}, si occupa di +stabilire, ad intervalli fissi e sulla base di un opportuno calcolo delle +priorità, quale ``\textsl{processo}'' deve essere posto in esecuzione (il +cosiddetto \textit{prehemptive + multitasking}\itindex{prehemptive~multitasking}). Questo verrà comunque eseguito in modalità protetta; quando necessario il processo potrà accedere alle risorse hardware soltanto attraverso delle opportune chiamate al sistema che restituiranno il controllo al kernel. @@ -258,11 +258,11 @@ un nome espresso in caratteri in sez.~\ref{sec:sys_user_group} queste informazioni possono essere mantenute, con l'uso del \textit{Name Service Switch}, su varie tipologie di supporti, compresi server centralizzati come LDAP.} -\index{\textit{Name~Service~Switch}} Questi numeri sono l'\textit{user - identifier}, detto in breve \textsl{user-ID}, ed indicato dall'acronimo -\acr{uid}, e il \textit{group identifier}, detto in breve \textsl{group-ID}, -ed identificato dall'acronimo \acr{gid}, e sono quelli che vengono usati dal -kernel per identificare l'utente. +\itindex{Name~Service~Switch} Questi numeri sono l'\textit{user identifier}, +detto in breve \textsl{user-ID}, ed indicato dall'acronimo \acr{uid}, e il +\textit{group identifier}, detto in breve \textsl{group-ID}, ed identificato +dall'acronimo \acr{gid}, e sono quelli che vengono usati dal kernel per +identificare l'utente. In questo modo il sistema è in grado di tenere traccia dell'utente a cui appartiene ciascun processo ed impedire ad altri utenti di interferire con diff --git a/ipc.tex b/ipc.tex index e6b45de..4894732 100644 --- a/ipc.tex +++ b/ipc.tex @@ -169,8 +169,8 @@ direzione del flusso dei dati Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato intermedio su un file temporaneo. Questo però non tiene conto del fatto che un \textit{CGI} deve poter gestire più richieste in concorrenza, e si avrebbe una -evidente \textit{race condition}\index{\textit{race~condition}} in caso di -accesso simultaneo a detto file.\footnote{il problema potrebbe essere superato +evidente \textit{race condition}\itindex{race~condition} in caso di accesso +simultaneo a detto file.\footnote{il problema potrebbe essere superato determinando in anticipo un nome appropriato per il file temporaneo, che verrebbe utilizzato dai vari sotto-processi, e cancellato alla fine della loro esecuzione; ma a questo le cose non sarebbero più tanto semplici.} @@ -453,8 +453,8 @@ comunque una fifo in scrittura anche se non ci sono ancora processi il lettura; è possibile anche usare la fifo all'interno di un solo processo, nel qual caso però occorre stare molto attenti alla possibili situazioni di stallo.\footnote{se si cerca di leggere da una fifo che non contiene dati si - avrà un deadlock\index{\textit{deadlock}} immediato, dato che il processo si - blocca e non potrà quindi mai eseguire le funzioni di scrittura.} + avrà un deadlock\itindex{deadlock} immediato, dato che il processo si blocca + e non potrà quindi mai eseguire le funzioni di scrittura.} Per la loro caratteristica di essere accessibili attraverso il filesystem, è piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle @@ -647,13 +647,12 @@ state raccolte nella libreria \file{libgapil.so}, per poter usare quest'ultima occorrerà definire la speciale variabile di ambiente \code{LD\_LIBRARY\_PATH} in modo che il linker dinamico possa accedervi. -In generale questa variabile indica il -\index{\textit{pathname}}\textit{pathname} della directory contenente la -libreria. Nell'ipotesi (che daremo sempre per verificata) che si facciano le -prove direttamente nella directory dei sorgenti (dove di norma vengono creati -sia i programmi che la libreria), il comando da dare sarà \code{export - LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare il server, facendogli -leggere una decina di frasi, con: +In generale questa variabile indica il \itindex{pathname}\textit{pathname} +della directory contenente la libreria. Nell'ipotesi (che daremo sempre per +verificata) che si facciano le prove direttamente nella directory dei sorgenti +(dove di norma vengono creati sia i programmi che la libreria), il comando da +dare sarà \code{export LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare +il server, facendogli leggere una decina di frasi, con: \begin{verbatim} [piccardi@gont sources]$ ./fortuned -n10 \end{verbatim} @@ -880,7 +879,7 @@ nome di un file ed un numero di versione; il suo prototipo \end{functions} La funzione determina un valore della chiave sulla base di \param{pathname}, -che deve specificare il \index{\textit{pathname}}\textit{pathname} di un file +che deve specificare il \itindex{pathname}\textit{pathname} di un file effettivamente esistente e di un numero di progetto \param{proj\_id)}, che di norma viene specificato come carattere, dato che ne vengono utilizzati solo gli 8 bit meno significativi.\footnote{nelle libc4 e libc5, come avviene in @@ -1186,23 +1185,23 @@ file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}. \end{figure} -Una coda di messaggi è costituita da una -\index{\textit{linked~list}}\textit{linked list};\footnote{una \textit{linked - list} è una tipica struttura di dati, organizzati in una lista in cui - ciascun elemento contiene un puntatore al successivo. In questo modo la - struttura è veloce nell'estrazione ed immissione dei dati dalle estremità - dalla lista (basta aggiungere un elemento in testa o in coda ed aggiornare - un puntatore), e relativamente veloce da attraversare in ordine sequenziale - (seguendo i puntatori), è invece relativamente lenta nell'accesso casuale e - nella ricerca.} i nuovi messaggi vengono inseriti in coda alla lista e -vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si è riportato lo -schema con cui queste strutture vengono mantenute dal kernel.\footnote{lo - schema illustrato in fig.~\ref{fig:ipc_mq_schema} è in realtà una - semplificazione di quello usato effettivamente fino ai kernel della serie - 2.2.x, nei kernel della serie 2.4.x la gestione delle code di messaggi è - stata modificata ed è effettuata in maniera diversa; abbiamo mantenuto lo - schema precedente in quanto illustra comunque in maniera più che adeguata i - principi di funzionamento delle code di messaggi.} +Una coda di messaggi è costituita da una \itindex{linked~list}\textit{linked + list};\footnote{una \textit{linked list} è una tipica struttura di dati, + organizzati in una lista in cui ciascun elemento contiene un puntatore al + successivo. In questo modo la struttura è veloce nell'estrazione ed + immissione dei dati dalle estremità dalla lista (basta aggiungere un + elemento in testa o in coda ed aggiornare un puntatore), e relativamente + veloce da attraversare in ordine sequenziale (seguendo i puntatori), è + invece relativamente lenta nell'accesso casuale e nella ricerca.} i nuovi +messaggi vengono inseriti in coda alla lista e vengono letti dalla cima, in +fig.~\ref{fig:ipc_mq_schema} si è riportato lo schema con cui queste strutture +vengono mantenute dal kernel.\footnote{lo schema illustrato in + fig.~\ref{fig:ipc_mq_schema} è in realtà una semplificazione di quello usato + effettivamente fino ai kernel della serie 2.2.x, nei kernel della serie + 2.4.x la gestione delle code di messaggi è stata modificata ed è effettuata + in maniera diversa; abbiamo mantenuto lo schema precedente in quanto + illustra comunque in maniera più che adeguata i principi di funzionamento + delle code di messaggi.} \begin{figure}[!htb] \footnotesize \centering @@ -1518,7 +1517,7 @@ possono essere utilizzate, e non si ha a disposizione niente di analogo alle funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di una di queste strutture alla volta; ad esempio non si può scrivere un server che aspetti un messaggio su più di una coda senza fare ricorso ad una tecnica -di \textit{polling}\index{\textit{polling}} che esegua un ciclo di attesa su +di \textit{polling}\itindex{polling} che esegua un ciclo di attesa su ciascuna di esse. Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro @@ -2198,8 +2197,8 @@ coda di attesa associata a ciascun insieme di semafori\footnote{che viene Nella struttura viene memorizzato il riferimento alle operazioni richieste (nel campo \var{sops}, che è un puntatore ad una struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper}) poi quest'ultimo viene messo -stato di attesa e viene invocato lo scheduler\index{\textit{scheduler}} per -passare all'esecuzione di un altro processo. +stato di attesa e viene invocato lo scheduler\itindex{scheduler} per passare +all'esecuzione di un altro processo. Se invece tutte le operazioni possono avere successo queste vengono eseguite immediatamente, dopo di che il kernel esegue una scansione della coda di @@ -2507,14 +2506,14 @@ corrispondente comportamento della funzione, sono i seguenti: il creatore del segmento, oppure l'amministratore. Compiuta l'operazione aggiorna anche il valore del campo \var{shm\_ctime}. \item[\const{SHM\_LOCK}] Abilita il \textit{memory - locking}\index{\textit{memory~locking}}\footnote{impedisce cioè che la - memoria usata per il segmento venga salvata su disco dal meccanismo della - memoria virtuale\index{memoria~virtuale}; si ricordi quanto trattato in + locking}\itindex{memory~locking}\footnote{impedisce cioè che la memoria + usata per il segmento venga salvata su disco dal meccanismo della memoria + virtuale\index{memoria~virtuale}; si ricordi quanto trattato in sez.~\ref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo l'amministratore può utilizzare questo comando. \item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory - locking}\index{\textit{memory~locking}} sul segmento di memoria condivisa. - Solo l'amministratore può utilizzare questo comando. + locking}\itindex{memory~locking} sul segmento di memoria condivisa. Solo + l'amministratore può utilizzare questo comando. \end{basedescript} i primi tre comandi sono gli stessi già visti anche per le code di messaggi e gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche @@ -3037,8 +3036,8 @@ caratteristica della funzione \func{open} (illustrata in sez.~\ref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non toglie che in alcune implementazioni questa tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si - è comunque soggetti alla possibilità di una race - condition\index{\textit{race~condition}}.} che essa ritorni un errore quando + è comunque soggetti alla possibilità di una \textit{race + condition}\itindex{race~condition}.} che essa ritorni un errore quando usata con i flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può essere eseguita atomicamente, il processo che crea il file con successo si può considerare come titolare del @@ -3083,8 +3082,8 @@ problemi, che non lo rendono una alternativa praticabile per la sincronizzazione: anzitutto in caso di terminazione imprevista del processo, si lascia allocata la risorsa (il \textsl{file di lock}) e questa deve essere sempre cancellata esplicitamente. Inoltre il controllo della disponibilità -può essere eseguito solo con una tecnica di -\textit{polling}\index{\textit{polling}}, ed è quindi molto inefficiente. +può essere eseguito solo con una tecnica di \textit{polling}\itindex{polling}, +ed è quindi molto inefficiente. La tecnica dei file di lock ha comunque una sua utilità, e può essere usata con successo quando l'esigenza è solo quella di segnalare l'occupazione di una @@ -3106,10 +3105,9 @@ 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 -attesa, senza necessità di ricorrere al -\textit{polling}\index{\textit{polling}} per determinare la disponibilità -della risorsa, e al rilascio della stessa da parte del processo che la -occupava si otterrà il nuovo lock atomicamente. +attesa, senza necessità di ricorrere al \textit{polling}\itindex{polling} per +determinare la disponibilità della risorsa, e al rilascio della stessa da +parte del processo che la occupava si otterrà il nuovo lock atomicamente. Questo approccio presenta il notevole vantaggio che alla terminazione di un processo tutti i lock acquisiti vengono rilasciati automaticamente (alla @@ -3203,6 +3201,7 @@ nessun inconveniente. \subsection{Il \textit{memory mapping} anonimo} \label{sec:ipc_mmap_anonymous} +\itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono \textsl{correlati}\footnote{se cioè hanno almeno un progenitore comune.} l'uso delle pipe può costituire una valida alternativa alle code di messaggi; nella stessa situazione si può @@ -3231,7 +3230,7 @@ il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica più avanti, quando realizzeremo una nuova versione del monitor visto in sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete. - +\itindend{memory~mapping} \section{Il sistema di comunicazione fra processi di POSIX} @@ -3256,16 +3255,16 @@ tuttavia dei patch e una libreria aggiuntiva. La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso degli identificatori e delle chiavi visti nel SysV IPC, per passare ai -\textit{Posix IPC names}\index{\textit{Posix~IPC~names}}, che sono -sostanzialmente equivalenti ai nomi dei file. Tutte le funzioni che creano un -oggetto di IPC Posix prendono come primo argomento una stringa che indica uno -di questi nomi; lo standard è molto generico riguardo l'implementazione, ed i -nomi stessi possono avere o meno una corrispondenza sul filesystem; tutto -quello che è richiesto è che: +\textit{Posix IPC names}\itindex{Posix~IPC~names}, che sono sostanzialmente +equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC +Posix prendono come primo argomento una stringa che indica uno di questi nomi; +lo standard è molto generico riguardo l'implementazione, ed i nomi stessi +possono avere o meno una corrispondenza sul filesystem; tutto quello che è +richiesto è che: \begin{itemize} \item i nomi devono essere conformi alle regole che caratterizzano i - \index{\textit{pathname}}\textit{pathname}, in particolare non essere più - lunghi di \const{PATH\_MAX} byte e terminati da un carattere nullo. + \itindex{pathname}\textit{pathname}, in particolare non essere più lunghi di + \const{PATH\_MAX} byte e terminati da un carattere nullo. \item se il nome inizia per una \texttt{/} chiamate differenti allo stesso nome fanno riferimento allo stesso oggetto, altrimenti l'interpretazione del nome dipende dall'implementazione. @@ -3283,7 +3282,7 @@ messaggi, tutto viene creato usando come radici delle opportune directory (rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si faccia riferimento a sez.~\ref{sec:ipc_posix_shm} e sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni -sono considerati come un \index{\textit{pathname}!assoluto}\textit{pathname} +sono considerati come un \itindsub{pathname}{assoluto}\textit{pathname} assoluto (comprendente eventuali sottodirectory) rispetto a queste radici. Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti diff --git a/macro.tex b/macro.tex index c8f3296..631220a 100644 --- a/macro.tex +++ b/macro.tex @@ -99,42 +99,73 @@ % \newcommand{\cmd}[1]{\texttt{#1}} % shell command \newcommand{\code}[1]{\texttt{#1}} % for simple code + \newcommand{\func}[1]{% -\index{#1@{{\tt {#1}} (funzione)}}\texttt{#1}% +\index{funzione!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (funzione)}}\texttt{#1}% } + \newcommand{\funcd}[1]{% -\index{#1@{{\tt {#1}} (funzione)}!definizione di}\texttt{#1}% +\index{funzione!{#1}@{{\tt {#1}}}!definizione di}\texttt{#1}% +%\index{#1@{{\tt {#1}} (funzione)}!definizione di}\texttt{#1}% } + \newcommand{\macro}[1]{% -\index{#1@{{\tt {#1}} (macro)}}\texttt{#1}% +\index{macro!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (macro)}}\texttt{#1}% } + \newcommand{\errcode}[1]{% -\index{#1@{{\tt {#1}} (errore)}}\texttt{#1}% +\index{errore!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (errore)}}\texttt{#1}% } + \newcommand{\errval}[1]{\texttt{#1}} % value \newcommand{\var}[1]{\texttt{#1}} % variable \newcommand{\val}[1]{\texttt{#1}} % value + \newcommand{\const}[1]{% -\index{#1@{{\tt {#1}} (costante)}}\texttt{#1}% +\index{costante!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (costante)}}\texttt{#1}% } % constant name + \newcommand{\direct}[1]{% -\index{#1@{{\tt {#1}} (direttiva)}}\texttt{#1}% +\index{direttiva!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (direttiva)}}\texttt{#1}% } % constant name + \newcommand{\file}[1]{\texttt{#1}} % file name \newcommand{\link}[1]{\texttt{#1}} % html link \newcommand{\ctyp}[1]{\texttt{#1}} % C standard type + \newcommand{\type}[1]{% -\index{#1@{{\tt {#1}} (tipo)}}\texttt{#1}% +\index{tipo!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (tipo)}}\texttt{#1}% } % system type \newcommand{\struct}[1]{% -\index{#1@{{\tt {#1}} (struttura dati)}}\texttt{#1}% +\index{struttura dati!{#1}@{{\tt {#1}}}}\texttt{#1}% +%\index{#1@{{\tt {#1}} (struttura dati)}}\texttt{#1}% } % struttura dati \newcommand{\structd}[1]{% -\index{#1@{{\tt {#1}} (struttura dati)}!definizione di}\texttt{#1}% +\index{struttura dati!{#1}@{{\tt {#1}}}!definizione di}\texttt{#1}% +%\index{#1@{{\tt {#1}} (struttura dati)}!definizione di}\texttt{#1}% } % struttura dati \newcommand{\param}[1]{\texttt{#1}} % function parameter \newcommand{\acr}[1]{\textsl{#1}} % acrostic (for pid, suid, ecc.) +\newcommand{\itindex}[1]{% +\index{#1@{\textit{#1}}}% +} + +\newcommand{\itindbeg}[1]{% +\index{#1@{\textit{#1}}|(}% +} +\newcommand{\itindend}[1]{% +\index{#1@{\textit{#1}}|)}% +} +\newcommand{\itindsub}[2]{% +\index{#1@{\textit{#1}}!#2}% +} % Aggiunte di Mirko per la gestione delle tabelle complicate come immagini % nella traslazione in HTML diff --git a/othersock.tex b/othersock.tex index 7231bf2..6915f99 100644 --- a/othersock.tex +++ b/othersock.tex @@ -54,10 +54,11 @@ utilizzando per il tipo di socket il valore \const{SOCK\_DGRAM}. Questa differenza comporta ovviamente che anche le modalità con cui si usano i socket UDP sono completamente diverse rispetto ai socket TCP, ed in particolare non esistendo il concetto di connessione non esiste il meccanismo -del \textit{three way handshake} né quello degli stati del protocollo. In -realtà tutto quello che avviene nella comunicazione attraverso dei socket UDP -è la trasmissione di un pacchetto da un client ad un server o viceversa, -secondo lo schema illustrato in fig.~\ref{fig:UDP_packet-exchange}. +del \itindex{three~way~handshake}\textit{three way handshake} né quello degli +stati del protocollo. In realtà tutto quello che avviene nella comunicazione +attraverso dei socket UDP è la trasmissione di un pacchetto da un client ad un +server o viceversa, secondo lo schema illustrato in +fig.~\ref{fig:UDP_packet-exchange}. \begin{figure}[htb] \centering @@ -265,8 +266,8 @@ l'indirizzo del mittente del pacchetto che opportunamente inizializzati con i puntatori alle variabili dove la struttura contenente quest'ultimo e la relativa lunghezza saranno scritti (si noti che \param{fromlen} è un valore intero ottenuto come -\index{\textit{value~result~argument}}\textit{value result argument}). Se non -si è interessati a questa informazione, entrambi gli argomenti devono essere +\itindex{value~result~argument}\textit{value result argument}). Se non si è +interessati a questa informazione, entrambi gli argomenti devono essere inizializzati al valore \const{NULL}. Una differenza fondamentale del comportamento di queste funzioni rispetto alle diff --git a/process.tex b/process.tex index 43dac1d..7c64e60 100644 --- a/process.tex +++ b/process.tex @@ -304,11 +304,11 @@ compiti principali del kernel. Quando un processo cerca di accedere ad una pagina che non è nella memoria reale, avviene quello che viene chiamato un \textit{page - fault}\index{\textit{page~fault}}; l'hardware di gestione della memoria -genera un'interruzione e passa il controllo al kernel il quale sospende il -processo e si incarica di mettere in RAM la pagina richiesta (effettuando -tutte le operazioni necessarie per reperire lo spazio necessario), per poi -restituire il controllo al processo. + fault}\itindex{page~fault}; l'hardware di gestione della memoria genera +un'interruzione e passa il controllo al kernel il quale sospende il processo e +si incarica di mettere in RAM la pagina richiesta (effettuando tutte le +operazioni necessarie per reperire lo spazio necessario), per poi restituire +il controllo al processo. Dal punto di vista di un processo questo meccanismo è completamente trasparente, e tutto avviene come se tutte le pagine fossero sempre @@ -333,11 +333,11 @@ commette quando si chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o scrivere da un indirizzo per il quale non esiste un'associazione della pagina virtuale, il kernel risponde al relativo \textit{page - fault}\index{\textit{page~fault}} mandando un segnale \const{SIGSEGV} al -processo, che normalmente ne causa la terminazione immediata. + fault}\itindex{page~fault} mandando un segnale \const{SIGSEGV} al processo, +che normalmente ne causa la terminazione immediata. È pertanto importante capire come viene strutturata \textsl{la memoria - virtuale}\index{\textit{page~fault}} di un processo. Essa viene divisa in + virtuale}\index{memoria~virtuale} di un processo. Essa viene divisa in \textsl{segmenti}, cioè un insieme contiguo di indirizzi virtuali ai quali il processo può accedere. Solitamente un programma C viene suddiviso nei seguenti segmenti: @@ -555,7 +555,7 @@ tollerante nei confronti di piccoli errori come quello di chiamate doppie a Il problema più comune e più difficile da risolvere che si incontra con le routine di allocazione è quando non viene opportunamente liberata la memoria non più utilizzata, quello che in inglese viene chiamato \textit{memory - leak}\index{\textit{memory~leak}}, cioè una \textsl{perdita di memoria}. + leak}\itindex{memory~leak}, cioè una \textsl{perdita di memoria}. Un caso tipico che illustra il problema è quello in cui in una subroutine si alloca della memoria per uso locale senza liberarla prima di uscire. La @@ -568,33 +568,33 @@ Il problema momento, in corrispondenza ad una qualunque chiamata di \func{malloc}, che può essere in una sezione del codice che non ha alcuna relazione con la subroutine che contiene l'errore. Per questo motivo è sempre molto difficile trovare un -\textit{memory leak}\index{\textit{memory~leak}}. +\textit{memory leak}\itindex{memory~leak}. In C e C++ il problema è particolarmente sentito. In C++, per mezzo della -programmazione ad oggetti, il problema dei \textit{memory leak} è notevolmente -ridimensionato attraverso l'uso accurato di appositi oggetti come gli -\textit{smartpointers}. Questo però va a scapito delle prestazioni -dell'applicazione in esecuzione. - -In altri linguaggi come il java e recentemente il C\# il problema non si pone -nemmeno perché la gestione della memoria viene fatta totalmente in maniera -automatica, ovvero il programmatore non deve minimamente preoccuparsi di -liberare la memoria allocata precedentemente quando non serve più, poiché -l'infrastruttura del linguaggio gestisce automaticamente la cosiddetta -\index{\textit{garbage~collection}}\textit{garbage collection}. In tal caso, -attraverso meccanismi simili a quelli del \textit{reference counting}, quando -una zona di memoria precedentemente allocata non è più riferita da nessuna -parte del codice in esecuzione, può essere deallocata automaticamente in -qualunque momento dall'infrastruttura. - -Anche questo va a scapito delle prestazioni dell'applicazione in esecuzione -(inoltre le applicazioni sviluppate con tali linguaggi di solito non sono -eseguibili compilati, come avviene invece per il C ed il C++, ed è necessaria -la presenza di una infrastruttura per la loro interpretazione e pertanto hanno -di per sé delle prestazioni più scadenti rispetto alle stesse applicazioni -compilate direttamente). Questo comporta però il problema della non -predicibilità del momento in cui viene deallocata la memoria precedentemente -allocata da un oggetto. +programmazione ad oggetti, il problema dei \textit{memory + leak}\itindex{memory~leak} è notevolmente ridimensionato attraverso l'uso +accurato di appositi oggetti come gli \textit{smartpointers}. Questo però in +genere va a scapito delle prestazioni dell'applicazione in esecuzione. + +% In altri linguaggi come il java e recentemente il C\# il problema non si pone +% nemmeno perché la gestione della memoria viene fatta totalmente in maniera +% automatica, ovvero il programmatore non deve minimamente preoccuparsi di +% liberare la memoria allocata precedentemente quando non serve più, poiché +% l'infrastruttura del linguaggio gestisce automaticamente la cosiddetta +% \index{\textit{garbage~collection}}\textit{garbage collection}. In tal caso, +% attraverso meccanismi simili a quelli del \textit{reference counting}, quando +% una zona di memoria precedentemente allocata non è più riferita da nessuna +% parte del codice in esecuzione, può essere deallocata automaticamente in +% qualunque momento dall'infrastruttura. + +% Anche questo va a scapito delle prestazioni dell'applicazione in esecuzione +% (inoltre le applicazioni sviluppate con tali linguaggi di solito non sono +% eseguibili compilati, come avviene invece per il C ed il C++, ed è necessaria +% la presenza di una infrastruttura per la loro interpretazione e pertanto hanno +% di per sé delle prestazioni più scadenti rispetto alle stesse applicazioni +% compilate direttamente). Questo comporta però il problema della non +% predicibilità del momento in cui viene deallocata la memoria precedentemente +% allocata da un oggetto. Per limitare l'impatto di questi problemi, e semplificare la ricerca di eventuali errori, l'implementazione delle routine di allocazione delle @@ -614,10 +614,10 @@ molto complesse riguardo l'allocazione della memoria. \label{sec:proc_mem_sbrk_alloca} Una possibile alternativa all'uso di \func{malloc}, che non soffre dei -problemi di \textit{memory leak}\index{\textit{memory~leak}} descritti in -precedenza, è la funzione \funcd{alloca}, che invece di allocare la memoria -nello heap usa il segmento di stack della funzione corrente. La sintassi è -identica a quella di \func{malloc}, il suo prototipo è: +problemi di \textit{memory leak}\itindex{memory~leak} descritti in precedenza, +è la funzione \funcd{alloca}, che invece di allocare la memoria nello heap usa +il segmento di stack della funzione corrente. La sintassi è identica a quella +di \func{malloc}, il suo prototipo è: \begin{prototype}{stdlib.h}{void *alloca(size\_t size)} Alloca \param{size} byte nello stack. @@ -633,7 +633,7 @@ quindi non esiste un analogo della \func{free}) in quanto essa viene rilasciata automaticamente al ritorno della funzione. Come è evidente questa funzione ha molti vantaggi, anzitutto permette di -evitare alla radice i problemi di memory leak\index{\textit{memory~leak}}, +evitare alla radice i problemi di \textit{memory leak}\itindex{memory~leak}, dato che non serve più la deallocazione esplicita; inoltre la deallocazione automatica funziona anche quando si usa \func{longjmp} per uscire da una subroutine con un salto non locale da una funzione (vedi @@ -751,7 +751,7 @@ motivi per cui si possono avere di queste necessit crittografia richiedono il blocco di alcune pagine di memoria. \end{itemize} -\index{\textit{memory~locking}|(} +\itindbeg{memory~locking} Il meccanismo che previene la paginazione\index{paginazione} di parte della memoria virtuale di un processo è chiamato \textit{memory locking} (o \textsl{blocco della memoria}). Il blocco è sempre associato alle pagine della @@ -768,11 +768,11 @@ Il \textit{memory lock} persiste fintanto che il processo che detiene la memoria bloccata non la sblocca. Chiaramente la terminazione del processo comporta anche la fine dell'uso della sua memoria virtuale, e quindi anche di tutti i suoi \textit{memory lock}. Infine i \textit{memory lock} non sono -ereditati dai processi figli.\footnote{ma siccome Linux usa il \textit{copy on - write} (vedi sez.~\ref{sec:proc_fork}) gli indirizzi virtuali del figlio - sono mantenuti sullo stesso segmento di RAM del padre, quindi fintanto che - un figlio non scrive su un segmento, può usufruire del \textit{memory lock} - del padre.} +ereditati dai processi figli.\footnote{ma siccome Linux usa il + \itindex{copy~on~write}\textit{copy on write} (vedi + sez.~\ref{sec:proc_fork}) gli indirizzi virtuali del figlio sono mantenuti + sullo stesso segmento di RAM del padre, quindi fintanto che un figlio non + scrive su un segmento, può usufruire del \textit{memory lock} del padre.} Siccome la richiesta di un \textit{memory lock} da parte di un processo riduce la memoria fisica disponibile nel sistema, questo ha un evidente impatto su @@ -856,18 +856,19 @@ esempio limitandosi a tutte le pagine allocate a partire da un certo momento. In ogni caso un processo real-time che deve entrare in una sezione critica deve provvedere a riservare memoria sufficiente prima dell'ingresso, per scongiurare l'occorrenza di un eventuale \textit{page - fault}\index{\textit{page~fault}} causato dal meccanismo di \textit{copy on - write}\index{\textit{copy~on~write}}. Infatti se nella sezione critica si -va ad utilizzare memoria che non è ancora stata riportata in RAM si potrebbe -avere un page fault durante l'esecuzione della stessa, con conseguente -rallentamento (probabilmente inaccettabile) dei tempi di esecuzione. + fault}\itindex{page~fault} causato dal meccanismo di \textit{copy on + write}\itindex{copy~on~write}. Infatti se nella sezione critica si va ad +utilizzare memoria che non è ancora stata riportata in RAM si potrebbe avere +un \itindex{page~fault}\textit{page fault} durante l'esecuzione della stessa, +con conseguente rallentamento (probabilmente inaccettabile) dei tempi di +esecuzione. In genere si ovvia a questa problematica chiamando una funzione che ha allocato una quantità sufficientemente ampia di variabili automatiche, in modo che esse vengano mappate in RAM dallo stack, dopo di che, per essere sicuri che esse siano state effettivamente portate in memoria, ci si scrive sopra. \index{memoria~virtuale|)} -\index{\textit{memory~locking}|)} +\itindend{memory~locking} @@ -1291,13 +1292,12 @@ nella programmazione normale. Talvolta però è necessario che la funzione possa restituire indietro alla funzione chiamante un valore relativo ad uno dei suoi argomenti. Per far -questo si usa il cosiddetto -\index{\textit{value~result~argument}}\textit{value result argument}, si passa -cioè, invece di una normale variabile, un puntatore alla stessa; vedremo -alcuni esempi di questa modalità nelle funzioni che gestiscono i socket (in -sez.~\ref{sec:TCP_functions}), in cui, per permettere al kernel di restituire -informazioni sulle dimensioni delle strutture degli indirizzi utilizzate, -viene usato questo meccanismo. +questo si usa il cosiddetto \itindex{value~result~argument}\textit{value + result argument}, si passa cioè, invece di una normale variabile, un +puntatore alla stessa; vedremo alcuni esempi di questa modalità nelle funzioni +che gestiscono i socket (in sez.~\ref{sec:TCP_functions}), in cui, per +permettere al kernel di restituire informazioni sulle dimensioni delle +strutture degli indirizzi utilizzate, viene usato questo meccanismo. \subsection{Il passaggio di un numero variabile di argomenti} diff --git a/prochand.tex b/prochand.tex index 651e145..9272a20 100644 --- a/prochand.tex +++ b/prochand.tex @@ -144,8 +144,8 @@ fig.~\ref{fig:proc_task_struct}. \end{figure} Come accennato in sez.~\ref{sec:intro_unix_struct} è lo -\textit{scheduler}\index{\textit{scheduler}} che decide quale processo mettere -in esecuzione; esso viene eseguito ad ogni system call ed ad ogni +\textit{scheduler}\itindex{scheduler} che decide quale processo mettere in +esecuzione; esso viene eseguito ad ogni system call ed ad ogni interrupt,\footnote{più in una serie di altre occasioni. NDT completare questa parte.} (ma può essere anche attivato esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato periodicamente, generando un @@ -157,7 +157,7 @@ Hertz.\footnote{Il valore usuale di questa costante sez.~\ref{sec:sys_unix_time}).} %Si ha cioè un interrupt dal timer ogni centesimo di secondo. -Ogni volta che viene eseguito, lo \textit{scheduler}\index{\textit{scheduler}} +Ogni volta che viene eseguito, lo \textit{scheduler}\itindex{scheduler} effettua il calcolo delle priorità dei vari processi attivi (torneremo su questo in sez.~\ref{sec:proc_priority}) e stabilisce quale di essi debba essere posto in esecuzione fino alla successiva invocazione. @@ -268,9 +268,8 @@ Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende un candidato per generare ulteriori indicatori associati al processo di cui diventa possibile garantire l'unicità: ad esempio in alcune implementazioni la funzione \func{tempnam} (si veda sez.~\ref{sec:file_temp_file}) usa il -\acr{pid} per generare un \index{\textit{pathname}}\textit{pathname} univoco, -che non potrà essere replicato da un altro processo che usi la stessa -funzione. +\acr{pid} per generare un \itindex{pathname}\textit{pathname} univoco, che non +potrà essere replicato da un altro processo che usi la stessa funzione. Tutti i processi figli dello stesso processo padre sono detti \textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di @@ -326,7 +325,7 @@ pertanto padre e figlio vedono variabili diverse. Per quanto riguarda la gestione della memoria, in generale il segmento di testo, che è identico per i due processi, è condiviso e tenuto in read-only per il padre e per i figli. Per gli altri segmenti Linux utilizza la tecnica -del \textit{copy on write}\index{\textit{copy~on~write}}; questa tecnica +del \textit{copy on write}\itindex{copy~on~write}; questa tecnica comporta che una pagina di memoria viene effettivamente copiata per il nuovo processo solo quando ci viene effettuata sopra una scrittura (e si ha quindi una reale differenza fra padre e figlio). In questo modo si rende molto più @@ -442,8 +441,8 @@ Go to next child Esaminiamo questo risultato: una prima conclusione che si può trarre è che non si può dire quale processo fra il padre ed il figlio venga eseguito per primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo - scheduler\index{\textit{scheduler}} di Ingo Molnar che esegue sempre per - primo il figlio; per mantenere la portabilità è opportuno non fare comunque + scheduler\itindex{scheduler} di Ingo Molnar che esegue sempre per primo il + figlio; per mantenere la portabilità è opportuno non fare comunque affidamento su questo comportamento.} dopo la chiamata a \func{fork}; dall'esempio si può notare infatti come nei primi due cicli sia stato eseguito per primo il padre (con la stampa del \acr{pid} del nuovo processo) per poi @@ -464,9 +463,8 @@ Pertanto non si pu istruzioni del codice fra padre e figli, né sull'ordine in cui questi potranno essere messi in esecuzione. Se è necessaria una qualche forma di precedenza occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il -rischio di incorrere nelle cosiddette -\textit{race condition}\index{\textit{race~condition}} -(vedi sez.~\ref{sec:proc_race_cond}). +rischio di incorrere nelle cosiddette \textit{race + condition}\itindex{race~condition} (vedi sez.~\ref{sec:proc_race_cond}). Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli processi completamente separati, le modifiche delle variabili nei processi @@ -586,7 +584,7 @@ propriet comune dopo l'esecuzione di una \func{fork} è la seguente: \begin{itemize*} \item i file aperti e gli eventuali flag di - \textit{close-on-exec}\index{\textit{close-on-exec}} impostati (vedi + \textit{close-on-exec}\itindex{close-on-exec} impostati (vedi sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}); \item gli identificatori per il controllo di accesso: l'\textsl{user-ID reale}, il \textsl{group-ID reale}, l'\textsl{user-ID effettivo}, il @@ -639,11 +637,10 @@ padre, che costituiva un inutile appesantimento in tutti quei casi in cui la \func{fork} veniva fatta solo per poi eseguire una \func{exec}. La funzione venne introdotta in BSD per migliorare le prestazioni. -Dato che Linux supporta il \textit{copy on - write}\index{\textit{copy~on~write}} la perdita di prestazioni è -assolutamente trascurabile, e l'uso di questa funzione (che resta un caso -speciale della system call \func{\_\_clone}) è deprecato; per questo eviteremo -di trattarla ulteriormente. +Dato che Linux supporta il \textit{copy on write}\itindex{copy~on~write} la +perdita di prestazioni è assolutamente trascurabile, e l'uso di questa +funzione (che resta un caso speciale della system call \func{\_\_clone}) è +deprecato; per questo eviteremo di trattarla ulteriormente. \subsection{La conclusione di un processo} @@ -1189,7 +1186,7 @@ non viene trovato nessun altro file viene finalmente restituito Le altre quattro funzioni si limitano invece a cercare di eseguire il file indicato dall'argomento \param{path}, che viene interpretato come il -\index{\textit{pathname}}\textit{pathname} del programma. +\itindex{pathname}\textit{pathname} del programma. \begin{figure}[htb] \centering @@ -1238,7 +1235,7 @@ speciale sez.~\ref{sec:sig_gen_beha}). La gestione dei file aperti dipende dal valore che ha il flag di -\textit{close-on-exec}\index{\textit{close-on-exec}} (vedi anche +\textit{close-on-exec}\itindex{close-on-exec} (vedi anche sez.~\ref{sec:file_fcntl}) per ciascun file descriptor. I file per cui è impostato vengono chiusi, tutti gli altri file restano aperti. Questo significa che il comportamento predefinito è che i file restano aperti @@ -1248,9 +1245,8 @@ che imposti il suddetto flag. Per le directory, lo standard POSIX.1 richiede che esse vengano chiuse attraverso una \func{exec}, in genere questo è fatto dalla funzione \func{opendir} (vedi sez.~\ref{sec:file_dir_read}) che effettua da sola -l'impostazione del flag di -\textit{close-on-exec}\index{\textit{close-on-exec}} sulle directory che apre, -in maniera trasparente all'utente. +l'impostazione del flag di \textit{close-on-exec}\itindex{close-on-exec} sulle +directory che apre, in maniera trasparente all'utente. Abbiamo detto che l'\textsl{user-ID reale} ed il \textsl{group-ID reale} restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per @@ -1700,8 +1696,8 @@ corrente. Anche queste funzioni sono un'estensione specifica di Linux, e non richiedono nessun privilegio. I valori sono restituiti negli argomenti, che vanno specificati come puntatori (è un altro esempio di -\index{\textit{value~result~argument}}\textit{value result argument}). Si noti -che queste funzioni sono le uniche in grado di leggere gli identificatori del +\itindex{value~result~argument}\textit{value result argument}). Si noti che +queste funzioni sono le uniche in grado di leggere gli identificatori del gruppo \textit{saved}. @@ -1870,7 +1866,7 @@ scrivere codice portabile. \label{sec:proc_priority} In questa sezione tratteremo più approfonditamente i meccanismi con il quale -lo \textit{scheduler}\index{\textit{scheduler}} assegna la CPU ai vari +lo \textit{scheduler}\itindex{scheduler} assegna la CPU ai vari processi attivi. In particolare prenderemo in esame i vari meccanismi con cui viene gestita l'assegnazione del tempo di CPU, ed illustreremo le varie funzioni di gestione. @@ -1879,6 +1875,7 @@ funzioni di gestione. \subsection{I meccanismi di \textit{scheduling}} \label{sec:proc_sched} +\itindbeg{scheduler} La scelta di un meccanismo che sia in grado di distribuire in maniera efficace il tempo di CPU per l'esecuzione dei processi è sempre una questione delicata, ed oggetto di numerose ricerche; in generale essa dipende in maniera @@ -1886,13 +1883,14 @@ essenziale anche dal tipo di utilizzo che deve essere fatto del sistema, per cui non esiste un meccanismo che sia valido per tutti gli usi. La caratteristica specifica di un sistema multitasking come Linux è quella del -cosiddetto \textit{prehemptive multitasking}: questo significa che al -contrario di altri sistemi (che usano invece il cosiddetto \textit{cooperative +cosiddetto \itindex{prehemptive~multitasking}\textit{prehemptive + multitasking}: questo significa che al contrario di altri sistemi (che usano +invece il cosiddetto \itindex{cooperative~multitasking}\textit{cooperative multitasking}) non sono i singoli processi, ma il kernel stesso a decidere quando la CPU deve essere passata ad un altro processo. Come accennato in sez.~\ref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione -apposita del kernel, lo \textit{scheduler}\index{\textit{scheduler}}, il cui -scopo è quello di distribuire al meglio il tempo di CPU fra i vari processi. +apposita del kernel, lo \textit{scheduler}, il cui scopo è quello di +distribuire al meglio il tempo di CPU fra i vari processi. La cosa è resa ancora più complicata dal fatto che con le architetture multi-processore si deve anche scegliere quale sia la CPU più opportuna da @@ -2013,32 +2011,30 @@ essere eseguito, e quando un processo potr nell'esecuzione. Il meccanismo usato da Linux è piuttosto semplice,\footnote{in realtà nella - serie 2.6.x lo \textit{scheduler} è stato riscritto da zero e può usare - diversi algoritmi, selezionabili sia in fase di compilazione, che, nelle - versioni più recenti, all'avvio (addirittura è stato ideato un sistema - modulare che permette di cambiare lo scheduler al volo, che comunque non è - incluso nel kernel ufficiale).} ad ogni processo è assegnata una -\textit{time-slice}, cioè un intervallo di tempo (letteralmente una fetta) per -il quale esso deve essere eseguito. Il valore della \textit{time-slice} è -controllato dalla cosiddetta \textit{nice} (o \textit{niceness}) del processo. -Essa è contenuta nel campo \var{nice} di \struct{task\_struct}; tutti i -processi vengono creati con lo stesso valore, ed essa specifica il valore -della durata iniziale della \textit{time-slice} che viene assegnato ad un -altro campo della struttura (\var{counter}) quando il processo viene eseguito -per la prima volta e diminuito progressivamente ad ogni interruzione del -timer. - -Durante la sua esecuzione lo scheduler\index{\textit{scheduler}} scandisce la -coda dei processi in stato \textit{runnable} associando, in base al valore di -\var{counter}, un peso ad ogni processo in attesa di esecuzione,\footnote{il - calcolo del peso in realtà è un po' più complicato, ad esempio nei sistemi - multiprocessore viene favorito un processo eseguito sulla stessa CPU, e a - parità del valore di \var{counter} viene favorito chi ha una priorità più - elevata.} chi ha il peso più alto verrà posto in esecuzione, ed il -precedente processo sarà spostato in fondo alla coda. Dato che ad ogni -interruzione del timer il valore di \var{counter} del processo corrente viene -diminuito, questo assicura che anche i processi con priorità più bassa -verranno messi in esecuzione. + serie 2.6.x lo scheduler è stato riscritto da zero e può usare diversi + algoritmi, selezionabili sia in fase di compilazione, che, nelle versioni + più recenti, all'avvio (addirittura è stato ideato un sistema modulare che + permette di cambiare lo scheduler al volo, che comunque non è incluso nel + kernel ufficiale).} ad ogni processo è assegnata una \textit{time-slice}, +cioè un intervallo di tempo (letteralmente una fetta) per il quale esso deve +essere eseguito. Il valore della \textit{time-slice} è controllato dalla +cosiddetta \textit{nice} (o \textit{niceness}) del processo. Essa è contenuta +nel campo \var{nice} di \struct{task\_struct}; tutti i processi vengono creati +con lo stesso valore, ed essa specifica il valore della durata iniziale della +\textit{time-slice} che viene assegnato ad un altro campo della struttura +(\var{counter}) quando il processo viene eseguito per la prima volta e +diminuito progressivamente ad ogni interruzione del timer. + +Durante la sua esecuzione lo scheduler scandisce la coda dei processi in stato +\textit{runnable} associando, in base al valore di \var{counter}, un peso ad +ogni processo in attesa di esecuzione,\footnote{il calcolo del peso in realtà + è un po' più complicato, ad esempio nei sistemi multiprocessore viene + favorito un processo eseguito sulla stessa CPU, e a parità del valore di + \var{counter} viene favorito chi ha una priorità più elevata.} chi ha il +peso più alto verrà posto in esecuzione, ed il precedente processo sarà +spostato in fondo alla coda. Dato che ad ogni interruzione del timer il +valore di \var{counter} del processo corrente viene diminuito, questo assicura +che anche i processi con priorità più bassa verranno messi in esecuzione. La priorità di un processo è così controllata attraverso il valore di \var{nice}, che stabilisce la durata della \textit{time-slice}; per il @@ -2167,7 +2163,7 @@ processo qualsiasi sia la sua priorit Adeos gestiti dalle code del nano-kernel), in modo da poterli controllare direttamente qualora ci sia la necessità di avere un processo con priorità più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un -page fault\index{\textit{page~fault}} si possono avere ritardi non previsti. +\textit{page fault}\itindex{page~fault} si possono avere ritardi non previsti. Se l'ultimo problema può essere aggirato attraverso l'uso delle funzioni di controllo della memoria virtuale (vedi sez.~\ref{sec:proc_mem_lock}), il primo non è superabile e può comportare ritardi non prevedibili riguardo ai tempi di @@ -2182,14 +2178,13 @@ si lavora con processi che usano priorit cui si sia assegnata la massima priorità assoluta, in modo da poter essere comunque in grado di rientrare nel sistema. -Quando c'è un processo con priorità assoluta lo -scheduler\index{\textit{scheduler}} lo metterà in esecuzione prima di ogni -processo normale. In caso di più processi sarà eseguito per primo quello con -priorità assoluta più alta. Quando ci sono più processi con la stessa priorità -assoluta questi vengono tenuti in una coda e tocca al kernel decidere quale -deve essere eseguito. Il meccanismo con cui vengono gestiti questi processi -dipende dalla politica di scheduling che si è scelto; lo standard ne prevede -due: +Quando c'è un processo con priorità assoluta lo scheduler lo metterà in +esecuzione prima di ogni processo normale. In caso di più processi sarà +eseguito per primo quello con priorità assoluta più alta. Quando ci sono più +processi con la stessa priorità assoluta questi vengono tenuti in una coda e +tocca al kernel decidere quale deve essere eseguito. Il meccanismo con cui +vengono gestiti questi processi dipende dalla politica di scheduling che si è +scelto; lo standard ne prevede due: \begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}} \item[\textit{FIFO}] \textit{First In First Out}. Il processo viene eseguito fintanto che non cede volontariamente la CPU (con \func{sched\_yield}), si @@ -2417,13 +2412,13 @@ Infine con il supporto dei sistemi multiprocessore sono state introdotte delle funzioni che permettono di controllare in maniera più dettagliata la scelta di quale processore utilizzare per eseguire un certo programma. Uno dei problemi che si pongono nei sistemi multiprocessore è infatti quello -dell'\textsl{effetto ping-pong}.\index{\textsl{effetto ping-pong}} Può -accadere cioè che lo scheduler, quando riavvia un processo precedentemente -interrotto, scegliendo il primo processore disponibile lo faccia eseguire da -un processore diverso rispetto a quello su cui era stato eseguito in -precedenza. Se il processo passa da un processore all'altro in questo modo -(cosa che avveniva abbastanza di frequente con i kernel della seria 2.4.x) si -ha l'\textsl{effetto ping-pong}. +dell'\textsl{effetto ping-pong}.\index{effetto~ping-pong} Può accadere cioè +che lo scheduler, quando riavvia un processo precedentemente interrotto, +scegliendo il primo processore disponibile lo faccia eseguire da un processore +diverso rispetto a quello su cui era stato eseguito in precedenza. Se il +processo passa da un processore all'altro in questo modo (cosa che avveniva +abbastanza di frequente con i kernel della seria 2.4.x) si ha +l'\textsl{effetto ping-pong}. Questo tipo di comportamento può generare dei seri problemi di prestazioni; infatti tutti i processori moderni utilizzano una memoria interna (la @@ -2441,16 +2436,17 @@ questa operazione diventa serio quando si verifica l'\textsl{effetto ping-pong}, in tal caso infatti un processo \textsl{rimbalza} continuamente da un processore all'altro e si ha una continua invalidazione della cache, che non diventa mai -disponibile. +disponibile. +\itindbeg{CPU~affinity} Per ovviare a questo tipo di problemi è nato il concetto di \textsl{affinità - di processore} (o \index{\textit{CPU~affinity}}\textit{CPU affinity}); la + di processore} (o \textit{CPU affinity}); la possibilità cioè di far sì che un processo possa essere assegnato per l'esecuzione sempre allo stesso processore. Lo scheduler dei kernel della -serie 2.4.x aveva una scarsa \textit{CPU affinity}, e l'effetto ping-pong era -comune; con il nuovo scheduler dei kernel della 2.6.x questo problema è stato -risolto ed esso cerca di mantenere il più possibile ciascun processo sullo -stesso processore. +serie 2.4.x aveva una scarsa \textit{CPU affinity}, e +\index{effetto~ping-pong} l'effetto ping-pong era comune; con il nuovo +scheduler dei kernel della 2.6.x questo problema è stato risolto ed esso cerca +di mantenere il più possibile ciascun processo sullo stesso processore. In certi casi però resta l'esigenza di poter essere sicuri che un processo sia sempre eseguito dallo stesso processore,\footnote{quella che viene detta @@ -2584,6 +2580,9 @@ paricolari. soltanto su un sistema multiprocessore, esse possono comunque essere utilizzate anche in un sistema con un processore singolo, nel qual caso però non avranno alcun risultato effettivo. +\itindend{scheduler} +\itindend{CPU~affinity} + \section{Problematiche di programmazione multitasking} @@ -2613,10 +2612,10 @@ di interruzione in una fase intermedia. In un ambiente multitasking il concetto è essenziale, dato che un processo può essere interrotto in qualunque momento dal kernel che mette in esecuzione un altro processo o dalla ricezione di un segnale; occorre pertanto essere -accorti nei confronti delle possibili -\textit{race condition}\index{\textit{race~condition}} (vedi -sez.~\ref{sec:proc_race_cond}) derivanti da operazioni interrotte in una fase -in cui non erano ancora state completate. +accorti nei confronti delle possibili \textit{race + condition}\itindex{race~condition} (vedi sez.~\ref{sec:proc_race_cond}) +derivanti da operazioni interrotte in una fase in cui non erano ancora state +completate. Nel caso dell'interazione fra processi la situazione è molto più semplice, ed occorre preoccuparsi della atomicità delle operazioni solo quando si ha a che @@ -2651,7 +2650,7 @@ condiviso, onde evitare problemi con le ottimizzazioni del codice. \subsection{Le \textit{race condition} ed i \textit{deadlock}} \label{sec:proc_race_cond} -\index{\textit{race~condition}|(} +\itindbeg{race~condition} Si definiscono \textit{race condition} tutte quelle situazioni in cui processi diversi operano su una risorsa comune, ed in cui il risultato viene a dipendere dall'ordine in cui essi effettuano le loro operazioni. Il caso @@ -2680,7 +2679,7 @@ cui si compiono le operazioni sulle risorse condivise (le cosiddette opportunamente protette da meccanismi di sincronizzazione (torneremo su queste problematiche di questo tipo in cap.~\ref{cha:IPC}). -\index{\textit{deadlock}|(} +\itindbeg{deadlock} Un caso particolare di \textit{race condition} sono poi i cosiddetti \textit{deadlock}, particolarmente gravi in quanto comportano spesso il blocco completo di un servizio, e non il fallimento di una singola operazione. Per @@ -2702,8 +2701,8 @@ In tutti questi casi visto in sez.~\ref{sec:proc_atom_oper}; questi problemi infatti possono essere risolti soltanto assicurandosi, quando essa sia richiesta, che sia possibile eseguire in maniera atomica le operazioni necessarie. -\index{\textit{race~condition}|)} -\index{\textit{deadlock}|)} +\itindend{race~condition} +\itindend{deadlock} \subsection{Le funzioni rientranti} diff --git a/session.tex b/session.tex index b3ce7d0..7f6a999 100644 --- a/session.tex +++ b/session.tex @@ -234,8 +234,8 @@ processo padre, per impostare il valore nel figlio, che da quest'ultimo, per sé stesso, in modo che il cambiamento di \textit{process group} sia immediato per entrambi; una delle due chiamate sarà ridondante, ma non potendo determinare quale dei due processi viene eseguito per primo, occorre eseguirle -comunque entrambe per evitare di esporsi ad una race -condition\index{\textit{race~condition}}. +comunque entrambe per evitare di esporsi ad una \textit{race + condition}\itindex{race~condition}. Si noti come nessuna delle funzioni esaminate finora permetta di spostare un processo da una sessione ad un altra; infatti l'unico modo di far cambiare @@ -394,13 +394,15 @@ corrispondenti segnali (rispettivamente \const{SIGTSTP}, \const{SIGINT}, \const{SIGQUIT} e \const{SIGTERM}, trattati in sez.~\ref{sec:sig_job_control}) a tutti i processi del raggruppamento di \textit{foreground}; in questo modo la shell può gestire il blocco e l'interruzione dei vari comandi. - + +% \| + Per completare la trattazione delle caratteristiche del job control legate al terminale di controllo, occorre prendere in considerazione i vari casi legati alla terminazione anomala dei processi, che sono di norma gestite attraverso il segnale \const{SIGHUP}. Il nome del segnale deriva da \textit{hungup}, termine che viene usato per indicare la condizione in cui il terminale diventa -inutilizzabile, (letteralmente sarebbe \textsl{impiccagione}). +inutilizzabile, (letteralmente sarebbe \textsl{impiccagione}). Quando si verifica questa condizione, ad esempio se si interrompe la linea, o va giù la rete o più semplicemente si chiude forzatamente la finestra di @@ -1038,10 +1040,10 @@ prototipo \textit{pathname} del terminale.} \end{prototype} -La funzione scrive il \index{\textit{pathname}}\textit{pathname} del terminale -di controllo del processo chiamante nella stringa posta all'indirizzo -specificato dall'argomento \param{s}. La memoria per contenere la stringa -deve essere stata allocata in precedenza ed essere lunga almeno +La funzione scrive il \itindex{pathname}\textit{pathname} del terminale di +controllo del processo chiamante nella stringa posta all'indirizzo specificato +dall'argomento \param{s}. La memoria per contenere la stringa deve essere +stata allocata in precedenza ed essere lunga almeno \const{L\_ctermid}\footnote{\const{L\_ctermid} è una delle varie costanti del sistema, non trattata esplicitamente in sez.~\ref{sec:sys_characteristics} che indica la dimensione che deve avere una stringa per poter contenere il @@ -1072,7 +1074,7 @@ si avr Se si passa come argomento \val{NULL} la funzione restituisce il puntatore ad una stringa statica che può essere sovrascritta da chiamate successive. Si -tenga presente che il \index{\textit{pathname}}\textit{pathname} restituito +tenga presente che il \itindex{pathname}\textit{pathname} restituito potrebbe non identificare univocamente il terminale (ad esempio potrebbe essere \file{/dev/tty}), inoltre non è detto che il processo possa effettivamente aprire il terminale. @@ -1417,12 +1419,12 @@ fig.~\ref{fig:term_termios}). \const{TOSTOP} & Se abilitato, con il supporto per il job control presente, genera il segnale \const{SIGTTOU} per un processo in background che cerca di scrivere sul terminale.\\ - \const{XCASE} & Se settato il terminale funziona solo con le + \const{XCASE} & Se impostato il terminale funziona solo con le maiuscole. L'input è convertito in minuscole tranne per i caratteri preceduti da una \verb|\|. In output le maiuscole sono precedute da una \verb|\| e le minuscole convertite in maiuscole.\\ - \const{DEFECHO}& Se impostate effettua l'eco solo se c'è un processo in + \const{DEFECHO}& Se impostato effettua l'eco solo se c'è un processo in lettura.\\ \const{FLUSHO} & Effettua la cancellazione della coda di uscita. Viene attivato dal carattere DISCARD. Non è supportato in diff --git a/signal.tex b/signal.tex index 3adaee3..0c11317 100644 --- a/signal.tex +++ b/signal.tex @@ -116,7 +116,7 @@ verr Questa è la ragione per cui l'implementazione dei segnali secondo questa semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del segnale e la reinstallazione del suo gestore non sono operazioni atomiche, e -sono sempre possibili delle race condition\index{\textit{race~condition}} +sono sempre possibili delle \textit{race condition}\itindex{race~condition} (sull'argomento vedi quanto detto in sez.~\ref{sec:proc_multi_prog}). Un altro problema è che in questa semantica non esiste un modo per bloccare i @@ -136,7 +136,7 @@ Si dice che il segnale viene \textsl{consegnato} al processo (dall'inglese \textit{delivered}) quando viene eseguita l'azione per esso prevista, mentre per tutto il tempo che passa fra la generazione del segnale e la sua consegna esso è detto \textsl{pendente} (o \textit{pending}). In genere questa -procedura viene effettuata dallo scheduler\index{\textit{scheduler}} quando, +procedura viene effettuata dallo scheduler\itindex{scheduler} quando, riprendendo l'esecuzione del processo in questione, verifica la presenza del segnale nella \struct{task\_struct} e mette in esecuzione il gestore. @@ -209,9 +209,9 @@ ignorarlo). Normalmente l'invio al processo che deve ricevere il segnale è immediato ed avviene non appena questo viene rimesso in esecuzione dallo -scheduler\index{\textit{scheduler}} che esegue l'azione specificata. Questo a -meno che il segnale in questione non sia stato bloccato prima della notifica, -nel qual caso l'invio non avviene ed il segnale resta \textsl{pendente} +scheduler\itindex{scheduler} che esegue l'azione specificata. Questo a meno +che il segnale in questione non sia stato bloccato prima della notifica, nel +qual caso l'invio non avviene ed il segnale resta \textsl{pendente} indefinitamente. Quando lo si sblocca il segnale \textsl{pendente} sarà subito notificato. Si tenga presente però che i segnali \textsl{pendenti} non si accodano, alla generazione infatti il kernel marca un flag nella @@ -241,11 +241,11 @@ una delle tre possibilit Un programma può specificare queste scelte usando le due funzioni \func{signal} e \func{sigaction} (vedi sez.~\ref{sec:sig_signal} e -sez.~\ref{sec:sig_sigaction}). Se si è installato un gestore sarà -quest'ultimo ad essere eseguito alla notifica del segnale. Inoltre il sistema -farà si che mentre viene eseguito il gestore di un segnale, quest'ultimo -venga automaticamente bloccato (così si possono evitare race -condition\index{\textit{race~condition}}). +sez.~\ref{sec:sig_sigaction}). Se si è installato un gestore sarà quest'ultimo +ad essere eseguito alla notifica del segnale. Inoltre il sistema farà si che +mentre viene eseguito il gestore di un segnale, quest'ultimo venga +automaticamente bloccato (così si possono evitare \textit{race + condition}\itindex{race~condition}). Nel caso non sia stata specificata un'azione, viene utilizzata l'azione standard che (come vedremo in sez.~\ref{sec:sig_standard}) è propria di ciascun @@ -415,11 +415,11 @@ tipologia, verr \label{sec:sig_prog_error} Questi segnali sono generati quando il sistema, o in certi casi direttamente -l'hardware (come per i \textit{page fault} non validi) rileva un qualche -errore insanabile nel programma in esecuzione. In generale la generazione di -questi segnali significa che il programma ha dei gravi problemi (ad esempio ha -dereferenziato un puntatore non valido o ha eseguito una operazione aritmetica -proibita) e l'esecuzione non può essere proseguita. +l'hardware (come per i \itindex{page~fault}\textit{page fault} non validi) +rileva un qualche errore insanabile nel programma in esecuzione. In generale +la generazione di questi segnali significa che il programma ha dei gravi +problemi (ad esempio ha dereferenziato un puntatore non valido o ha eseguito +una operazione aritmetica proibita) e l'esecuzione non può essere proseguita. In genere si intercettano questi segnali per permettere al programma di terminare in maniera pulita, ad esempio per ripristinare le impostazioni della @@ -1354,12 +1354,11 @@ Chiaramente, anche se il tempo pu nanosecondo, la precisione di \func{nanosleep} è determinata dalla risoluzione temporale del timer di sistema. Perciò la funzione attenderà comunque il tempo specificato, ma prima che il processo possa tornare ad essere eseguito -occorrerà almeno attendere il successivo giro di -scheduler\index{\textit{scheduler}} e cioè un tempo che a seconda dei casi può -arrivare fino a 1/\const{HZ}, (sempre che il sistema sia scarico ed il -processa venga immediatamente rimesso in esecuzione); per questo motivo il -valore restituito in \param{rem} è sempre arrotondato al multiplo successivo -di 1/\const{HZ}. +occorrerà almeno attendere il successivo giro di scheduler\itindex{scheduler} +e cioè un tempo che a seconda dei casi può arrivare fino a 1/\const{HZ}, +(sempre che il sistema sia scarico ed il processa venga immediatamente rimesso +in esecuzione); per questo motivo il valore restituito in \param{rem} è sempre +arrotondato al multiplo successivo di 1/\const{HZ}. In realtà è possibile ottenere anche pause più precise del centesimo di secondo usando politiche di scheduling real-time come \const{SCHED\_FIFO} o @@ -1451,8 +1450,8 @@ tutti gli stati di terminazione sono stati ricevuti. Le funzioni esaminate finora fanno riferimento alle modalità più elementari della gestione dei segnali; non si sono pertanto ancora prese in -considerazione le tematiche più complesse, collegate alle varie race -condition\index{\textit{race~condition}} che i segnali possono generare e alla +considerazione le tematiche più complesse, collegate alle varie \textit{race + condition}\itindex{race~condition} che i segnali possono generare e alla natura asincrona degli stessi. Affronteremo queste problematiche in questa sezione, partendo da un esempio @@ -1494,14 +1493,13 @@ l'interruzione di \func{pause} venisse causata da un altro segnale. Questo codice però, a parte il non gestire il caso in cui si è avuta una precedente chiamata a \func{alarm} (che si è tralasciato per brevità), -presenta una pericolosa race condition\index{\textit{race~condition}}. +presenta una pericolosa \textit{race condition}\itindex{race~condition}. Infatti, se il processo viene interrotto fra la chiamata di \func{alarm} e \func{pause}, può capitare (ad esempio se il sistema è molto carico) che il tempo di attesa scada prima dell'esecuzione di quest'ultima, cosicché essa sarebbe eseguita dopo l'arrivo di \const{SIGALRM}. In questo caso ci si -troverebbe di fronte ad un deadlock\index{\textit{deadlock}}, in quanto -\func{pause} non verrebbe mai più interrotta (se non in caso di un altro -segnale). +troverebbe di fronte ad un deadlock\itindex{deadlock}, in quanto \func{pause} +non verrebbe mai più interrotta (se non in caso di un altro segnale). Questo problema può essere risolto (ed è la modalità con cui veniva fatto in SVr2) usando la funzione \func{longjmp} (vedi sez.~\ref{sec:proc_longjmp}) per @@ -1558,7 +1556,7 @@ segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}). Questo è il tipico esempio di caso, già citato in sez.~\ref{sec:proc_race_cond}, in cui si genera una -\index{\textit{race~condition}}race condition; infatti, in una situazione in +\itindex{race~condition}\textit{race condition}; infatti, in una situazione in cui un segnale è già arrivato (e \var{flag} è già ad 1) se un altro segnale segnale arriva immediatamente dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima della cancellazione del flag (\texttt{\small 7}), la sua @@ -1575,7 +1573,8 @@ reagire alla ricezione di un segnale. \subsection{Gli \textsl{insiemi di segnali} o \textit{signal set}} \label{sec:sig_sigset} -\index{\textit{signal~set}|(} +\itindbeg{signal~set} + Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali originarie, nate con la semantica inaffidabile, hanno dei limiti non superabili; in particolare non è prevista nessuna funzione che permetta di @@ -1637,8 +1636,8 @@ ottenuto con \func{sigemptyset} o togliendo quelli che non servono da un insieme completo ottenuto con \func{sigfillset}. Infine \func{sigismember} permette di verificare la presenza di uno specifico segnale in un insieme. -\index{\textit{signal~set}|)} +\itindend{signal~set} \subsection{La funzione \func{sigaction}} @@ -1871,7 +1870,7 @@ estremamente semplice, \textit{signal mask}} \label{sec:sig_sigmask} -\index{\textit{signal mask}|(} +\itindbeg{signal~mask} Come spiegato in sez.~\ref{sec:sig_semantics} tutti i moderni sistemi unix-like permettono di bloccare temporaneamente (o di eliminare completamente, impostando \const{SIG\_IGN} come azione) la consegna dei segnali ad un @@ -1949,7 +1948,7 @@ occorre ricordare che qualunque modifica alla maschera dei segnali viene perduta alla conclusione del terminatore. Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte -dei casi di race condition\index{\textit{race~condition}} restano aperte +dei casi di \textit{race condition}\itindex{race~condition} restano aperte alcune possibilità legate all'uso di \func{pause}; il caso è simile a quello del problema illustrato nell'esempio di fig.~\ref{fig:sig_sleep_incomplete}, e cioè la possibilità che il processo riceva il segnale che si intende usare per @@ -2008,8 +2007,8 @@ fine (\texttt{\small 22}), e al contempo si prepara la maschera dei segnali \var{sleep\_mask} per riattivare \const{SIGALRM} all'esecuzione di \func{sigsuspend}. -In questo modo non sono più possibili race -condition\index{\textit{race~condition}} dato che \const{SIGALRM} viene +In questo modo non sono più possibili \textit{race + condition}\itindex{race~condition} dato che \const{SIGALRM} viene disabilitato con \func{sigprocmask} fino alla chiamata di \func{sigsuspend}. Questo metodo è assolutamente generale e può essere applicato a qualunque altra situazione in cui si deve attendere per un segnale, i passi sono sempre @@ -2023,9 +2022,10 @@ i seguenti: \end{enumerate*} Per quanto possa sembrare strano bloccare la ricezione di un segnale per poi riabilitarla immediatamente dopo, in questo modo si evita il -deadlock\index{\textit{deadlock}} dovuto all'arrivo del segnale prima -dell'esecuzione di \func{sigsuspend}. -\index{\textit{signal mask}|)} +deadlock\itindex{deadlock} dovuto all'arrivo del segnale prima dell'esecuzione +di \func{sigsuspend}. + +\itindend{signal~mask} \subsection{Ulteriori funzioni di gestione} diff --git a/sockadv.tex b/sockadv.tex index b033b6f..b6ee0ca 100644 --- a/sockadv.tex +++ b/sockadv.tex @@ -45,7 +45,7 @@ fig.~\ref{fig:sock_extended_err_struct}. \begin{minipage}[c]{15cm} \includestruct{listati/sock_extended_err.h} \end{minipage} - \caption{La struttura \structd{sock_extended_err} usata dall'opzione + \caption{La struttura \structd{sock\_extended\_err} usata dall'opzione \const{IP\_RECVERR} per ottenere le informazioni relative agli errori su un socket.} \label{fig:sock_extended_err_struct} diff --git a/sockctrl.tex b/sockctrl.tex index 815ceb1..13384f3 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -34,7 +34,7 @@ porte o altre propriet \subsection{La struttura del \textit{resolver}} \label{sec:sock_resolver} -\index{\textit{resolver}|(} +\itindbeg{resolver} La risoluzione dei nomi è associata tradizionalmente al servizio del \textit{Domain Name Service} che permette di identificare le macchine su internet invece che per numero IP attraverso il relativo \textsl{nome a @@ -117,7 +117,7 @@ dell'ordine in cui questi vengono interrogati.\footnote{con le implementazioni funzioni di libreria, prevedendo un ordine di interrogazione predefinito e non modificabile (a meno di una ricompilazione delle librerie stesse).} -\index{\textit{Name~Service~Switch}|(} +\itindbeg{Name~Service~Switch} Per risolvere questa serie di problemi la risoluzione dei nomi a dominio eseguirà dal \textit{resolver} è stata inclusa all'interno di un meccanismo generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi @@ -168,7 +168,7 @@ tab.~\ref{tab:sys_NSS_classes}. \label{tab:sys_NSS_classes} \end{table} -Il sistema del \textit{Name Service Switch} è controllato dal contenuto del +Il sistema del \textit{Name Service Switch} è controllato dal contenuto del file \file{/etc/nsswitch.conf}; questo contiene una riga\footnote{seguendo una convezione comune per i file di configurazione le righe vuote vengono ignorate e tutto quello che segue un carattere ``\texttt{\#}'' viene @@ -193,7 +193,7 @@ quello che conta sono le funzioni classiche che il \textit{resolver} mette a disposizione,\footnote{è cura della implementazione fattane nelle \acr{glibc} tenere conto della presenza del \textit{Name Service Switch}.} e sono queste quelle che tratteremo nelle sezioni successive. -\index{\textit{Name~Service~Switch}|)} +\itindend{Name~Service~Switch} \subsection{Le funzioni di interrogazione del \textit{resolver}} @@ -610,16 +610,15 @@ Restituisce una stringa corrispondente ad un errore di risoluzione. \noindent che, come l'analoga \func{strerror}, restituisce una stringa con un messaggio di errore già formattato, corrispondente al codice passato come argomento (che si presume sia dato da \var{h\_errno}). -\index{\textit{resolver}|)} - +\itindend{resolver} \subsection{La risoluzione dei nomi a dominio} \label{sec:sock_name_services} -La principale funzionalità del \index{\textit{resolver}}\textit{resolver} -resta quella di risolvere i nomi a dominio in indirizzi IP, per cui non ci +La principale funzionalità del \itindex{resolver}\textit{resolver} resta +quella di risolvere i nomi a dominio in indirizzi IP, per cui non ci dedicheremo oltre alle funzioni di richiesta generica ed esamineremo invece le funzioni a questo dedicate. La prima funzione è \funcd{gethostbyname} il cui scopo è ottenere l'indirizzo di una stazione noto il suo nome a dominio, il @@ -683,7 +682,7 @@ Con l'uso di \func{gethostbyname} normalmente si ottengono solo gli indirizzi IPv4, se si vogliono ottenere degli indirizzi IPv6 occorrerà prima impostare l'opzione \const{RES\_USE\_INET6} nel campo \texttt{\_res.options} e poi chiamare \func{res\_init} (vedi sez.~\ref{sec:sock_resolver_functions}) per -modificare le opzioni del \index{\textit{resolver}}\textit{resolver}; dato che +modificare le opzioni del \itindex{resolver}\textit{resolver}; dato che questo non è molto comodo è stata definita\footnote{questa è una estensione fornita dalle \acr{glibc}, disponibile anche in altri sistemi unix-like.} un'altra funzione, \funcd{gethostbyname2}, il cui prototipo è: @@ -720,10 +719,10 @@ suoi risultati. Vediamo allora un primo esempio dell'uso delle funzioni di risoluzione, in fig.~\ref{fig:mygethost_example} è riportato un estratto del codice di un programma che esegue una semplice interrogazione al -\index{\textit{resolver}}\textit{resolver} usando \func{gethostbyname} e poi -ne stampa a video i risultati. Al solito il sorgente completo, che comprende -il trattamento delle opzioni ed una funzione per stampare un messaggio di -aiuto, è nel file \texttt{mygethost.c} dei sorgenti allegati alla guida. +\itindex{resolver}\textit{resolver} usando \func{gethostbyname} e poi ne +stampa a video i risultati. Al solito il sorgente completo, che comprende il +trattamento delle opzioni ed una funzione per stampare un messaggio di aiuto, +è nel file \texttt{mygethost.c} dei sorgenti allegati alla guida. Il programma richiede un solo argomento che specifichi il nome da cercare, senza il quale (\texttt{\small 12--15}) esce con un errore. Dopo di che @@ -778,10 +777,10 @@ copiare il contenuto della sola struttura non i dati, in quanto questa contiene puntatori ad altri dati, che pure possono essere sovrascritti; per questo motivo, se si vuole salvare il risultato di una chiamata, occorrerà eseguire quella che si chiama una -\index{\textit{deep~copy}}\textit{deep copy}.\footnote{si chiama così quella - tecnica per cui, quando si deve copiare il contenuto di una struttura - complessa (con puntatori che puntano ad altri dati, che a loro volta possono - essere puntatori ad altri dati) si deve copiare non solo il contenuto della +\itindex{deep~copy}\textit{deep copy}.\footnote{si chiama così quella tecnica + per cui, quando si deve copiare il contenuto di una struttura complessa (con + puntatori che puntano ad altri dati, che a loro volta possono essere + puntatori ad altri dati) si deve copiare non solo il contenuto della struttura, ma eseguire una scansione per risolvere anche tutti i puntatori contenuti in essa (e così via se vi sono altre sottostrutture con altri puntatori) e copiare anche i dati da questi referenziati.} @@ -819,9 +818,9 @@ lunghezza di questo buffer devono essere indicati con gli argomenti \param{buf} e \param{buflen}. Gli ultimi due argomenti vengono utilizzati per avere indietro i risultati -come \index{\textit{value~result~argument}}\textit{value result argument}, si -deve specificare l'indirizzo della variabile su cui la funzione dovrà salvare -il codice di errore con \param{h\_errnop} e quello su cui dovrà salvare il +come \itindex{value~result~argument}\textit{value result argument}, si deve +specificare l'indirizzo della variabile su cui la funzione dovrà salvare il +codice di errore con \param{h\_errnop} e quello su cui dovrà salvare il puntatore che si userà per accedere i dati con \param{result}. In caso di successo entrambe le funzioni restituiscono un valore nullo, @@ -969,7 +968,7 @@ tab.~\ref{tab:sock_getipnodebyname_flags}. sistema è associata ad un indirizzo di tale tipo.\\ \const{AI\_DEFAULT} & il valore di default, è equivalente alla combinazione di \const{AI\_ADDRCONFIG} e di - \const{AI\_V4MAPPED)}.\\ + \const{AI\_V4MAPPED}.\\ \hline \end{tabular} \caption{Valori possibili per i bit dell'argomento \param{flags} della @@ -1248,6 +1247,16 @@ ricerche generiche sugli indirizzi, usando sia IPv4 che IPv6, e richiedere risoluzioni sui nomi dei servizi indipendentemente dal protocollo (ad esempio TCP o UDP) che questi possono utilizzare. +Come ultimo argomento in \param{res} deve essere passato un puntatore ad una +variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che verrà +utilizzata dalla funzione per riportare (come \itindex{value~result~argument} +\textit{value result argument}) i propri risultati. La funzione infatti è +rientrante, ed alloca autonomamente tutta la memoria necessaria in cui +verranno riportati i risultati della risoluzione. La funzione scriverà +all'indirizzo puntato da \param{res} il puntatore iniziale ad una +\itindex{linked~list}\textit{linked list} di strutture di tipo +\struct{addrinfo} contenenti tutte le informazioni ottenute. + \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} @@ -1258,12 +1267,12 @@ TCP o UDP) che questi possono utilizzare. \label{fig:sock_addrinfo_struct} \end{figure} -La struttura \struct{addrinfo}, la cui definizione\footnote{la definizione è - ripresa direttamente dal file \texttt{netdb.h} in questa struttura viene - dichiarata, la pagina di manuale riporta \type{size\_t} come tipo di dato - per il campo \var{ai\_addrlen}, qui viene usata quanto previsto dallo - standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi di - dati sono comunque equivalenti.} è riportata in +Come illustrato la struttura \struct{addrinfo}, la cui definizione\footnote{la + definizione è ripresa direttamente dal file \texttt{netdb.h} in questa + struttura viene dichiarata, la pagina di manuale riporta \type{size\_t} come + tipo di dato per il campo \var{ai\_addrlen}, qui viene usata quanto previsto + dallo standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi + di dati sono comunque equivalenti.} è riportata in fig.~\ref{fig:sock_addrinfo_struct}, viene usata sia in ingresso, per passare dei valori di controllo alla funzione, che in uscita, per ricevere i risultati. Il primo campo, \var{ai\_flags}, è una maschera binaria di bit che @@ -1273,7 +1282,7 @@ che viene usato soltanto in ingresso. I tre campi successivi \var{ai\_family}, famiglia di indirizzi, il tipo di socket e il protocollo, in ingresso vengono usati per impostare una selezione (impostandone il valore nella struttura puntata da \param{hints}), mentre in uscita indicano il tipo di risultato -contenuto nella struttura. +contenuto nella struttura. Tutti i campi seguenti vengono usati soltanto in uscita; il campo \var{ai\_addrlen} indica la dimensione della struttura degli indirizzi @@ -1364,15 +1373,6 @@ bit della maschera. \label{tab:ai_flags_values} \end{table} -Come ultimo argomento di \func{getaddrinfo} deve essere passato un puntatore -ad una variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che -verrà utilizzata dalla funzione per riportare (come \textit{value result - argument}) i propri risultati. La funzione infatti è rientrante, ed alloca -autonomamente tutta la memoria necessaria in cui verranno riportati i -risultati della risoluzione. La funzione scriverà in \param{res} il puntatore -iniziale ad una \index{\textit{linked~list}}\textit{linked list} di strutture -di tipo \struct{addrinfo} contenenti tutte le informazioni ottenute. - La funzione restituisce un valore nullo in caso di successo, o un codice in caso di errore. I valori usati come codice di errore sono riportati in tab.~\ref{tab:addrinfo_error_code}; dato che la funzione utilizza altre @@ -1461,14 +1461,14 @@ lista illustrata in fig.~\ref{fig:sock_addrinfo_list}. \begin{figure}[!htb] \centering \includegraphics[width=10cm]{img/addrinfo_list} - \caption{La \index{\textit{linked~list}}\textit{linked list} delle strutture + \caption{La \itindex{linked~list}\textit{linked list} delle strutture \struct{addrinfo} restituite da \func{getaddrinfo}.} \label{fig:sock_addrinfo_list} \end{figure} Come primo esempio di uso di \func{getaddrinfo} vediamo un programma -elementare di interrogazione del \index{\textit{resolver}}\textit{resolver} -basato questa funzione, il cui corpo principale è riportato in +elementare di interrogazione del \itindex{resolver}\textit{resolver} basato +questa funzione, il cui corpo principale è riportato in fig.~\ref{fig:mygetaddr_example}. Il codice completo del programma, compresa la gestione delle opzioni in cui è gestita l'eventuale inizializzazione dell'argomento \var{hints} per restringere le ricerche su protocolli, tipi di @@ -1558,11 +1558,10 @@ IPv4 address: \end{Verbatim} %$ -Una volta estratti i risultati dalla -\index{\textit{linked~list}}\textit{linked list} puntata da \param{res} se -questa non viene più utilizzata si dovrà avere cura di disallocare -opportunamente tutta la memoria, per questo viene fornita l'apposita funzione -\funcd{freeaddrinfo}, il cui prototipo è: +Una volta estratti i risultati dalla \itindex{linked~list}\textit{linked list} +puntata da \param{res} se questa non viene più utilizzata si dovrà avere cura +di disallocare opportunamente tutta la memoria, per questo viene fornita +l'apposita funzione \funcd{freeaddrinfo}, il cui prototipo è: \begin{functions} \headdecl{netdb.h} @@ -1581,7 +1580,7 @@ per \param{res}. Si tenga presente infine che se si copiano i risultati da una delle strutture \struct{addrinfo} restituite nella lista indicizzata da \param{res}, occorre -avere cura di eseguire una \index{\textit{deep~copy}}\textit{deep copy} in cui +avere cura di eseguire una \itindex{deep~copy}\textit{deep copy} in cui si copiano anche tutti i dati presenti agli indirizzi contenuti nella struttura \struct{addrinfo}, perché una volta disallocati i dati con \func{freeaddrinfo} questi non sarebbero più disponibili. @@ -1979,11 +1978,12 @@ di \func{setsockopt}, anche se non per entrambe le funzioni. In questo caso \param{optval} viene usato per ricevere le informazioni ed indica l'indirizzo a cui andranno scritti i dati letti dal socket, infine \param{optlen} diventa un puntatore ad una variabile -che viene usata come \textit{value result argument} per indicare, prima della -chiamata della funzione, la lunghezza del buffer allocato per \param{optval} e -per ricevere indietro, dopo la chiamata della funzione, la dimensione -effettiva dei dati scritti su di esso. Se la dimenzione del buffer allocato -per \param{optval} non è sufficiente si avrà un errore. +che viene usata come \itindex{value~result~argument}\textit{value result + argument} per indicare, prima della chiamata della funzione, la lunghezza +del buffer allocato per \param{optval} e per ricevere indietro, dopo la +chiamata della funzione, la dimensione effettiva dei dati scritti su di esso. +Se la dimenzione del buffer allocato per \param{optval} non è sufficiente si +avrà un errore. @@ -2283,7 +2283,7 @@ programmazione dei socket. Per questo motivo faremo in questa sezione un approfondimento sul significato delle opzioni generiche più importanti. -\index{\texttt{SO\_KEEPALIVE} (costante)|(} +\index{costante!{\tt SO\_KEEPALIVE}|(} \subsubsection{L'opzione \const{SO\_KEEPALIVE}} La prima opzione da approfondire è \const{SO\_KEEPALIVE} che permette di @@ -2385,10 +2385,10 @@ tutte le volte che un processo figlio viene eseguito in risposta ad una connessione verrà pertanto eseguita o meno la sezione (\texttt{\small 14--17}) che esegue l'impostazione di \const{SO\_KEEPALIVE} sul socket connesso, attivando il relativo comportamento. -\index{\texttt{SO\_KEEPALIVE} (costante)|)} +\index{costante!{\tt SO\_KEEPALIVE}|)} -\index{\texttt{SO\_REUSEADDR} (costante)|(} +\index{costante!{\tt SO\_REUSEADDR}|(} \subsubsection{L'opzione \const{SO\_REUSEADDR}} La seconda opzione da approfondire è \const{SO\_REUSEADDR}, che consente di @@ -2560,10 +2560,9 @@ questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto primo programma a consentirlo, avendo usato fin dall'inizio \const{SO\_REUSEADDR}.} -\index{\texttt{SO\_REUSEADDR} (costante)|)} +\index{costante!{\tt SO\_REUSEADDR}|)} - -\index{\texttt{SO\_LINGER} (costante)|(} +\index{costante!{\tt SO\_LINGER}|(} \subsubsection{L'opzione \const{SO\_LINGER}} La terza opzione da approfondire è \const{SO\_LINGER}; essa, come il nome @@ -2649,9 +2648,7 @@ secondi\footnote{questa completamento della trasmissione dei dati sul buffer.} pari al valore specificato in \var{l\_linger}. - - -\index{\texttt{SO\_LINGER} (costante)|)} +\index{costante!{\tt SO\_LINGER}|)} diff --git a/socket.tex b/socket.tex index 833d037..3cb33d3 100644 --- a/socket.tex +++ b/socket.tex @@ -541,7 +541,7 @@ il campo \var{sun\_path} deve specificare un indirizzo. Questo ha due forme; può essere un file (di tipo socket) nel filesystem o una stringa univoca (mantenuta in uno spazio di nomi astratto). Nel primo caso l'indirizzo viene specificato come una stringa (terminata da uno zero) corrispondente al -\index{\textit{pathname}}\textit{pathname} del file; nel secondo invece +\itindex{pathname}\textit{pathname} del file; nel secondo invece \var{sun\_path} inizia con uno zero e vengono usati come nome i restanti byte come stringa, senza terminazione. @@ -562,7 +562,7 @@ I socket AppleTalk permettono di usare il protocollo DDP, che a pacchetto, di tipo \const{SOCK\_DGRAM}; l'argomento \param{protocol} di \func{socket} deve essere nullo. È altresì possibile usare i socket raw specificando un tipo \const{SOCK\_RAW}, nel qual caso l'unico valore valido -per \param{protocol} è \func{ATPROTO\_DDP}. +per \param{protocol} è \const{ATPROTO\_DDP}. Gli indirizzi AppleTalk devono essere specificati tramite una struttura \struct{sockaddr\_atalk}, la cui definizione è riportata in @@ -743,7 +743,7 @@ seguito. \subsection{La \textit{endianess}} \label{sec:sock_endianess} -\index{\textit{endianess}|(} +\itindbeg{endianess} La rappresentazione di un numero binario in un computer può essere fatta in due modi, chiamati rispettivamente \textit{big endian} e \textit{little endian} a seconda di come i singoli bit vengono aggregati per formare le @@ -834,23 +834,21 @@ accedere al contenuto della prima variabile, ed infine calcola (\texttt{\small significativo (cioè, per quanto visto in fig.~\ref{fig:sock_endianess}, che sia \textit{little endian}). Infine la funzione restituisce (\texttt{\small 12}) il valore del confonto delle due variabili. - -\index{\textit{endianess}|)} +\itindend{endianess} \subsection{Le funzioni per il riordinamento} \label{sec:sock_func_ord} -Il problema connesso all'endianess\index{\textit{endianess}} è che quando si -passano dei dati da un tipo di architettura all'altra i dati vengono -interpretati in maniera diversa, e ad esempio nel caso dell'intero a 16 bit ci -si ritroverà con i due byte in cui è suddiviso scambiati di posto. Per questo -motivo si usano delle funzioni di conversione che servono a tener conto -automaticamente della possibile differenza fra l'ordinamento usato sul -computer e quello che viene usato nelle trasmissione sulla rete; queste -funzioni sono \funcd{htonl}, \funcd{htons}, \funcd{ntohl} e \funcd{ntohs} ed i -rispettivi prototipi sono: +Il problema connesso all'endianess\itindex{endianess} è che quando si passano +dei dati da un tipo di architettura all'altra i dati vengono interpretati in +maniera diversa, e ad esempio nel caso dell'intero a 16 bit ci si ritroverà +con i due byte in cui è suddiviso scambiati di posto. Per questo motivo si +usano delle funzioni di conversione che servono a tener conto automaticamente +della possibile differenza fra l'ordinamento usato sul computer e quello che +viene usato nelle trasmissione sulla rete; queste funzioni sono \funcd{htonl}, +\funcd{htons}, \funcd{ntohl} e \funcd{ntohs} ed i rispettivi prototipi sono: \begin{functions} \headdecl{netinet/in.h} \funcdecl{unsigned long int htonl(unsigned long int hostlong)} diff --git a/system.tex b/system.tex index 200aa94..d9b86d2 100644 --- a/system.tex +++ b/system.tex @@ -391,7 +391,7 @@ riportate in tab.~\ref{tab:sys_file_macro}. \const{LINK\_MAX} &8 & numero massimo di link a un file\\ \const{NAME\_MAX}& 14 & lunghezza in byte di un nome di file. \\ \const{PATH\_MAX}& 256 & lunghezza in byte di un - \index{\textit{pathname}}\textit{pathname}.\\ + \itindex{pathname}\textit{pathname}.\\ \const{PIPE\_BUF}&4096 & byte scrivibili atomicamente in una pipe (vedi sez.~\ref{sec:ipc_pipes}).\\ \const{MAX\_CANON}&255 & dimensione di una riga di terminale in modo @@ -422,7 +422,7 @@ le analoghe di tab.~\ref{tab:sys_posix1_general}. \const{\_POSIX\_LINK\_MAX} &8 & numero massimo di link a un file.\\ \const{\_POSIX\_NAME\_MAX}& 14 & lunghezza in byte di un nome di file. \\ \const{\_POSIX\_PATH\_MAX}& 256 & lunghezza in byte di un - \index{\textit{pathname}}\textit{pathname}.\\ + \itindex{pathname}\textit{pathname}.\\ \const{\_POSIX\_PIPE\_BUF}& 512 & byte scrivibili atomicamente in una pipe.\\ \const{\_POSIX\_MAX\_CANON}&255 & dimensione di una riga di @@ -465,13 +465,13 @@ E si noti come la funzione in questo caso richieda un argomento che specifichi a quale file si fa riferimento, dato che il valore del limite cercato può variare a seconda del filesystem. Una seconda versione della funzione, \funcd{fpathconf}, opera su un file descriptor invece che su un -\index{\textit{pathname}}\textit{pathname}. Il suo prototipo è: +\itindex{pathname}\textit{pathname}. Il suo prototipo è: \begin{prototype}{unistd.h}{long fpathconf(int fd, int name)} Restituisce il valore del parametro \param{name} per il file \param{fd}. \bodydesc{È identica a \func{pathconf} solo che utilizza un file descriptor - invece di un \index{\textit{pathname}}\textit{pathname}; pertanto gli - errori restituiti cambiano di conseguenza.} + invece di un \itindex{pathname}\textit{pathname}; pertanto gli errori + restituiti cambiano di conseguenza.} \end{prototype} \noindent ed il suo comportamento è identico a quello di \func{pathconf}. @@ -589,8 +589,8 @@ maniera gerarchica all'interno di un albero;\footnote{si tenga presente che occorrerà includere anche i file \file{linux/unistd.h} e \file{linux/sysctl.h}.} per accedere ad uno di essi occorre specificare un cammino attraverso i vari nodi dell'albero, in maniera analoga a come avviene -per la risoluzione di un \index{\textit{pathname}}\textit{pathname} (da cui -l'uso alternativo del filesystem \file{/proc}, che vedremo dopo). +per la risoluzione di un \itindex{pathname}\textit{pathname} (da cui l'uso +alternativo del filesystem \file{/proc}, che vedremo dopo). Ciascun nodo dell'albero è identificato da un valore intero, ed il cammino che arriva ad identificare un parametro specifico è passato alla funzione @@ -633,11 +633,11 @@ forma di file alcune delle strutture interne del kernel stesso. In particolare l'albero dei valori di \func{sysctl} viene presentato in forma di file nella directory \file{/proc/sys}, cosicché è possibile accedervi -specificando un \index{\textit{pathname}}\textit{pathname} e leggendo e -scrivendo sul file corrispondente al parametro scelto. Il kernel si occupa di -generare al volo il contenuto ed i nomi dei file corrispondenti, e questo ha -il grande vantaggio di rendere accessibili i vari parametri a qualunque -comando di shell e di permettere la navigazione dell'albero dei valori. +specificando un \itindex{pathname}\textit{pathname} e leggendo e scrivendo sul +file corrispondente al parametro scelto. Il kernel si occupa di generare al +volo il contenuto ed i nomi dei file corrispondenti, e questo ha il grande +vantaggio di rendere accessibili i vari parametri a qualunque comando di shell +e di permettere la navigazione dell'albero dei valori. Alcune delle corrispondenze dei file presenti in \file{/proc/sys} con i valori di \func{sysctl} sono riportate nei commenti del codice che può essere trovato @@ -689,7 +689,7 @@ sulla directory \param{target}. \textit{mount point} o di spostarlo quando \param{target} non è un \textit{mount point} o è \file{/}. \item[\errcode{EACCES}] non si ha il permesso di accesso su uno dei - componenti del \index{\textit{pathname}}\textit{pathname}, o si è cercato + componenti del \itindex{pathname}\textit{pathname}, o si è cercato di montare un filesystem disponibile in sola lettura senza averlo specificato o il device \param{source} è su un filesystem montato con l'opzione \const{MS\_NODEV}. @@ -933,10 +933,9 @@ dall'altra con il diffondersi delle reti la necessit informazioni degli utenti e dei gruppi per insiemi di macchine, in modo da mantenere coerenti i dati, ha portato anche alla necessità di poter recuperare e memorizzare dette informazioni su supporti diversi, introducendo il sistema -del \index{\textit{Name~Service~Switch}}\textit{Name Service Switch} che -tratteremo brevemente più avanti (in sez.~\ref{sec:sock_resolver}) dato che la -maggior parte delle sua applicazioni sono relative alla risoluzioni di nomi di -rete. +del \itindex{Name~Service~Switch}\textit{Name Service Switch} che tratteremo +brevemente più avanti (in sez.~\ref{sec:sock_resolver}) dato che la maggior +parte delle sua applicazioni sono relative alla risoluzioni di nomi di rete. In questo paragrafo ci limiteremo comunque a trattere le funzioni classiche per la lettura delle informazioni relative a utenti e gruppi tralasciando @@ -1068,7 +1067,7 @@ fig.~\ref{fig:sys_group_struct}. Le funzioni viste finora sono in grado di leggere le informazioni sia direttamente dal file delle password in \file{/etc/passwd} che tramite il -sistema del \index{\textit{Name~Service~Switch}}\textit{Name Service Switch} e +sistema del \itindex{Name~Service~Switch}\textit{Name Service Switch} e sono completamente generiche. Si noti però che non c'è una funzione che permetta di impostare direttamente una password.\footnote{in realtà questo può essere fatto ricorrendo a PAM, ma questo è un altro discorso.} Dato che @@ -1365,12 +1364,11 @@ kernel nelle system call eseguite per conto del processo. Gli altri tre campi servono a quantificare l'uso della memoria virtuale\index{memoria~virtuale} e corrispondono rispettivamente al numero di -\textit{page fault}\index{\textit{page~fault}} (vedi -sez.~\ref{sec:proc_mem_gen}) avvenuti senza richiedere I/O su disco (i -cosiddetti \textit{minor page fault}), a quelli che invece han richiesto I/O -su disco (detti invece \textit{major page fault}) ed al numero di volte che il -processo è stato completamente tolto dalla memoria per essere inserito nello -swap. +\textit{page fault}\itindex{page~fault} (vedi sez.~\ref{sec:proc_mem_gen}) +avvenuti senza richiedere I/O su disco (i cosiddetti \textit{minor page + fault}), a quelli che invece han richiesto I/O su disco (detti invece +\textit{major page fault}) ed al numero di volte che il processo è stato +completamente tolto dalla memoria per essere inserito nello swap. In genere includere esplicitamente \file{} non è più strettamente necessario, ma aumenta la portabilità, e serve comunque quando, come nella @@ -1623,12 +1621,11 @@ Il suo prototipo \end{prototype} La funzione restituisce in ciascun elemento di \param{loadavg} il numero medio -di processi attivi sulla coda dello scheduler\index{\textit{scheduler}}, -calcolato su un diverso intervalli di tempo. Il numero di intervalli che si -vogliono leggere è specificato da \param{nelem}, dato che nel caso di Linux il -carico viene valutato solo su tre intervalli (corrispondenti a 1, 5 e 15 -minuti), questo è anche il massimo valore che può essere assegnato a questo -argomento. +di processi attivi sulla coda dello scheduler\itindex{scheduler}, calcolato su +un diverso intervalli di tempo. Il numero di intervalli che si vogliono +leggere è specificato da \param{nelem}, dato che nel caso di Linux il carico +viene valutato solo su tre intervalli (corrispondenti a 1, 5 e 15 minuti), +questo è anche il massimo valore che può essere assegnato a questo argomento. diff --git a/tcpsock.tex b/tcpsock.tex index 78a6ce4..583ec3d 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -38,7 +38,7 @@ significato di alcuni dei vari \textsl{stati} ad essa associati. \subsection{La creazione della connessione: il \textit{three way handshake}} \label{sec:TCP_conn_cre} -\index{\textit{three~way~handshake}|(} +\itindbeg{three~way~handshake} Il processo che porta a creare una connessione TCP è chiamato \textit{three way handshake}; la successione tipica degli eventi (e dei \textsl{segmenti}\footnote{Si ricordi che il segmento è l'unità elementare di @@ -118,7 +118,8 @@ aspetta di ricevere con il pacchetto successivo; dato che il primo pacchetto SYN consuma un byte, nel \textit{three way handshake} il numero di acknowledge è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso varrà anche (vedi fig.~\ref{fig:TCP_close}) per l'acknowledgement di un FIN. -\index{\textit{three~way~handshake}|)} + +\itindend{three~way~handshake} \subsection{Le opzioni TCP.} @@ -716,7 +717,7 @@ Si noti che si \const{INADDR\_ANY}, anche se, essendo questo nullo, il riordinamento è inutile. Si tenga presente comunque che tutte le costanti \val{INADDR\_} (riportate in tab.~\ref{tab:TCP_ipv4_addr}) sono definite secondo -l'\textit{endianess}\index{\textit{endianess}} della macchina, ed anche se +l'\textit{endianess}\itindex{endianess} della macchina, ed anche se esse possono essere invarianti rispetto all'ordinamento dei bit, è comunque buona norma usare sempre la funzione \func{htonl}. @@ -765,8 +766,8 @@ connessione con un server TCP,\footnote{di nuovo la funzione limiterà ad impostare l'indirizzo dal quale e verso il quale saranno inviati e ricevuti i pacchetti, mentre per socket di tipo \const{SOCK\_STREAM} o \const{SOCK\_SEQPACKET}, essa attiverà la procedura di avvio (nel caso del - TCP il \index{\textit{three~way~handshake}}\textit{three way handshake}) - della connessione.} il prototipo della funzione è il seguente: + TCP il \itindex{three~way~handshake}\textit{three way handshake}) della + connessione.} il prototipo della funzione è il seguente: \begin{prototype}{sys/socket.h} {int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t addrlen)} @@ -809,7 +810,7 @@ nell'esempio sez.~\ref{sec:TCP_daytime_client}, usando le funzioni illustrate in sez.~\ref{sec:sock_addr_func}. Nel caso di socket TCP la funzione \func{connect} avvia il -\index{\textit{three~way~handshake}}\textit{three way handshake}, e ritorna +\itindex{three~way~handshake}\textit{three way handshake}, e ritorna solo quando la connessione è stabilita o si è verificato un errore. Le possibili cause di errore sono molteplici (ed i relativi codici riportati sopra), quelle che però dipendono dalla situazione della rete e non da errori @@ -908,7 +909,7 @@ infatti vengono mantenute due code: \begin{enumerate} \item La coda delle connessioni incomplete (\textit{incomplete connection queue} che contiene un riferimento per ciascun socket per il quale è - arrivato un SYN ma il \index{\textit{three~way~handshake}}\textit{three way + arrivato un SYN ma il \itindex{three~way~handshake}\textit{three way handshake} non si è ancora concluso. Questi socket sono tutti nello stato \texttt{SYN\_RECV}. \item La coda delle connessioni complete (\textit{complete connection queue} @@ -922,7 +923,7 @@ quando arriva un SYN da un client il server crea una nuova voce nella coda delle connessioni incomplete, e poi risponde con il SYN$+$ACK. La voce resterà nella coda delle connessioni incomplete fino al ricevimento dell'ACK dal client o fino ad un timeout. Nel caso di completamento del -\index{\textit{three~way~handshake}}\textit{three way handshake} la voce viene +\itindex{three~way~handshake}\textit{three way handshake} la voce viene spostata nella coda delle connessioni complete. Quando il processo chiama la funzione \func{accept} (vedi sez.~\ref{sec:TCP_func_accept}) la prima voce nella coda delle connessioni complete è passata al programma, o, se la coda è @@ -979,7 +980,7 @@ che il compito principale della coda sia quello di gestire il caso in cui il server è occupato fra chiamate successive alla \func{accept} (per cui la coda più occupata sarebbe quella delle connessioni completate), ma piuttosto quello di gestire la presenza di un gran numero di SYN in attesa di concludere il -\textit{three way handshake}\index{\textit{three~way~handshake}}. +\textit{three way handshake}\itindex{three~way~handshake}. Infine va messo in evidenza che, nel caso di socket TCP, quando un SYN arriva con tutte le code piene, il pacchetto deve essere ignorato. Questo perché la @@ -997,10 +998,10 @@ trasparente dal protocollo TCP. \label{sec:TCP_func_accept} La funzione \funcd{accept} è chiamata da un server per gestire la connessione -una volta che sia stato completato il \textit{three way - handshake},\footnote{la funzione è comunque generica ed è utilizzabile su - socket di tipo \const{SOCK\_STREAM}, \const{SOCK\_SEQPACKET} e - \const{SOCK\_RDM}.} la funzione restituisce un nuovo socket descriptor su +una volta che sia stato completato il \itindex{three~way~handshake} +\textit{three way handshake},\footnote{la funzione è comunque generica ed è + utilizzabile su socket di tipo \const{SOCK\_STREAM}, \const{SOCK\_SEQPACKET} + e \const{SOCK\_RDM}.} la funzione restituisce un nuovo socket descriptor su cui si potrà operare per effettuare la comunicazione. Se non ci sono connessioni completate il processo viene messo in attesa. Il prototipo della funzione è il seguente: @@ -1911,14 +1912,14 @@ connessioni da qualunque indirizzo e da qualunque porta e su qualunque interfaccia locale. A questo punto si può lanciare il client, esso chiamerà \func{socket} e -\func{connect}; una volta completato il \textit{three way handshake} la -connessione è stabilita; la \func{connect} ritornerà nel client\footnote{si - noti che è sempre la \func{connect} del client a ritornare per prima, in - quanto questo avviene alla ricezione del secondo segmento (l'ACK del server) - del \textit{three way handshake}, la \func{accept} del server ritorna solo - dopo un altro mezzo RTT quando il terzo segmento (l'ACK del client) viene - ricevuto.} e la \func{accept} nel server, ed usando di nuovo \cmd{netstat} -otterremmo che: +\func{connect}; una volta completato il \itindex{three~way~handshake} +\textit{three way handshake} la connessione è stabilita; la \func{connect} +ritornerà nel client\footnote{si noti che è sempre la \func{connect} del + client a ritornare per prima, in quanto questo avviene alla ricezione del + secondo segmento (l'ACK del server) del \textit{three way handshake}, la + \func{accept} del server ritorna solo dopo un altro mezzo RTT quando il + terzo segmento (l'ACK del client) viene ricevuto.} e la \func{accept} nel +server, ed usando di nuovo \cmd{netstat} otterremmo che: \begin{verbatim} Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State @@ -2262,10 +2263,10 @@ Bench con dei server molto occupati. In tal caso, con una struttura del server simile a quella del nostro esempio, in cui la gestione delle singole connessioni è demandata a processi figli, può accadere che il \textit{three - way handshake}\index{\textit{three~way~handshake}} venga completato e la -relativa connessione abortita subito dopo, prima che il padre, per via del -carico della macchina, abbia fatto in tempo ad eseguire la chiamata ad -\func{accept}. Di nuovo si ha una situazione analoga a quella illustrata in + way handshake}\itindex{three~way~handshake} venga completato e la relativa +connessione abortita subito dopo, prima che il padre, per via del carico della +macchina, abbia fatto in tempo ad eseguire la chiamata ad \func{accept}. Di +nuovo si ha una situazione analoga a quella illustrata in fig.~\ref{fig:TCP_early_abort}, in cui la connessione viene stabilita, ma subito dopo si ha una condizione di errore che la chiude prima che essa sia stata accettata dal programma. @@ -2373,8 +2374,8 @@ anarres.echo > gont.34559: R 511689732:511689732(0) win 0 Le prime tre righe vengono prodotte al momento in cui lanciamo il nostro client, e corrispondono ai tre pacchetti del -\index{\textit{three~way~handshake}}\textit{three way handshake}. L'output -del comando riporta anche i numeri di sequenza iniziali, mentre la lettera +\itindex{three~way~handshake}\textit{three way handshake}. L'output del +comando riporta anche i numeri di sequenza iniziali, mentre la lettera \texttt{S} indica che per quel pacchetto si aveva il SYN flag attivo. Si noti come a partire dal secondo pacchetto sia sempre attivo il campo \texttt{ack}, seguito dal numero di sequenza per il quale si da il ricevuto; quest'ultimo, a @@ -2388,17 +2389,17 @@ server risponde dando il ricevuto con un secondo pacchetto, che a sua volta porta un SYN, cui il client risponde con un il terzo pacchetto di ricevuto. Ritorniamo allora alla nostra sessione con il servizio echo: dopo le tre righe -del \textit{three way handshake}\index{\textit{three~way~handshake}} non -avremo nulla fin tanto che non scriveremo una prima riga sul client; al -momento in cui facciamo questo si genera una sequenza di altri quattro -pacchetti. Il primo, dal client al server, contraddistinto da una lettera -\texttt{P} che significa che il flag PSH è impostato, contiene la nostra riga -(che è appunto di 11 caratteri), e ad esso il server risponde immediatamente -con un pacchetto vuoto di ricevuto. Poi tocca al server riscrivere indietro -quanto gli è stato inviato, per cui sarà lui a mandare indietro un terzo -pacchetto con lo stesso contenuto appena ricevuto, e a sua volta riceverà dal -client un ACK nel quarto pacchetto. Questo causerà la ricezione dell'eco nel -client che lo stamperà a video. +del \textit{three way handshake}\itindex{three~way~handshake} non avremo nulla +fin tanto che non scriveremo una prima riga sul client; al momento in cui +facciamo questo si genera una sequenza di altri quattro pacchetti. Il primo, +dal client al server, contraddistinto da una lettera \texttt{P} che significa +che il flag PSH è impostato, contiene la nostra riga (che è appunto di 11 +caratteri), e ad esso il server risponde immediatamente con un pacchetto vuoto +di ricevuto. Poi tocca al server riscrivere indietro quanto gli è stato +inviato, per cui sarà lui a mandare indietro un terzo pacchetto con lo stesso +contenuto appena ricevuto, e a sua volta riceverà dal client un ACK nel quarto +pacchetto. Questo causerà la ricezione dell'eco nel client che lo stamperà a +video. A questo punto noi procediamo ad interrompere l'esecuzione del server con un \texttt{C-c} (cioè con l'invio di \const{SIGTERM}): nel momento in cui