From: Simone Piccardi Date: Thu, 4 Jan 2007 15:17:44 +0000 (+0000) Subject: Aggiornamenti del copyright all'anno nuovo, e risistemazione delle X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=ff76d56c6a2c280cbe4f153173488871d7b12336 Aggiornamenti del copyright all'anno nuovo, e risistemazione delle indicizzazioni. --- diff --git a/errors.tex b/errors.tex index 4141761..1931455 100644 --- a/errors.tex +++ b/errors.tex @@ -1,6 +1,6 @@ %% errors.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{I codici di errore} \label{cha:errors} @@ -15,9 +16,10 @@ Si riportano in questa appendice tutti i codici di errore. Essi sono accessibili attraverso l'inclusione del file di header \file{errno.h}, che definisce anche la variabile globale \var{errno}. Per ogni errore definito riporteremo la stringa stampata da \func{perror} ed una breve spiegazione. Si -tenga presente che spiegazioni più particolareggiate, qualora necessarie per -il caso specifico, possono essere trovate nella descrizione del prototipo -della funzione. +tenga presente che spiegazioni più particolareggiate del significato +dell'errore, qualora necessarie per casi specifici, possono essere trovate +nella descrizione del prototipo della funzione per cui detto errore si è +verificato. I codici di errore sono riportati come costanti di tipo \ctyp{int}, i valori delle costanti sono definiti da macro di preprocessore nel file citato, e @@ -417,8 +419,6 @@ messaggio. - - % \section{Errori del kernel} % \label{sec:err_kernel_err} @@ -470,12 +470,6 @@ messaggio. % \end{description} - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "gapil" -%%% End: - % LocalWords: header errno perror int strerror sez EPERM Operation not ENOENT % LocalWords: permitted such pathname EIO error ENXIO device address kernel Is % LocalWords: ENOEXEC Invalid executable format exec EBADF Bad descriptor Too @@ -506,3 +500,9 @@ messaggio. % LocalWords: SysV EMULTIHOP Multihop attempted ENODATA ENOLINK been severed % LocalWords: ENOMSG desired ENOSR streams resources ENOSTR stream EOVERFLOW % LocalWords: Value large defined STAT EPROTO ETIME Timer expired + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: diff --git a/fileadv.tex b/fileadv.tex index 0ae94e3..b4c7d00 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1,6 +1,6 @@ %% fileadv.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -50,12 +50,12 @@ pi possibile prevedere quando questo può avvenire (il caso più classico è quello di un server in attesa di dati in ingresso da vari client). Quello che può accadere è di restare bloccati nell'eseguire una operazione su un file -descriptor che non è ``\textsl{pronto}'', quando ce ne potrebbe essere -un altro disponibile. Questo comporta nel migliore dei casi una operazione +descriptor che non è ``\textsl{pronto}'', quando ce ne potrebbe essere 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}\itindex{deadlock}. +potrebbe addirittura arrivare ad un \itindex{deadlock} \textit{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 @@ -65,7 +65,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}\itindex{polling}, è +Ovviamente questa tecnica, detta \itindex{polling} \textit{polling}, è estremamente inefficiente: si tiene costantemente impiegata la CPU solo per eseguire in continuazione delle system call che nella gran parte dei casi falliranno. @@ -572,7 +572,7 @@ tipo (molto richiesta specialmente nello sviluppo dei programmi ad interfaccia grafica) sono state successivamente introdotte delle estensioni che permettessero la creazione di meccanismi di notifica più efficienti dell'unica soluzione disponibile con l'interfaccia tradizionale, che è quella del -\itindex{polling}\textit{polling}. +\itindex{polling} \textit{polling}. Queste nuove funzionalità sono delle estensioni specifiche, non standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel @@ -783,7 +783,7 @@ effettuare in contemporanea le operazioni di calcolo e quelle di I/O. Benché la modalità di apertura asincrona di un file possa risultare utile in varie occasioni (in particolar modo con i socket e gli altri file per i quali -le funzioni di I/O sono \index{system~call~lente}system call lente), essa è +le funzioni di I/O sono \index{system~call~lente} system call lente), essa è comunque limitata alla notifica della disponibilità del file descriptor per le operazioni di I/O, e non ad uno svolgimento asincrono delle medesime. Lo standard POSIX.1b definisce una interfaccia apposita per l'I/O asincrono vero @@ -1221,7 +1221,7 @@ si sono specificati nel vettore \param{vector}. 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 -\textsl{paginazione}\index{paginazione} usato dalla memoria virtuale (vedi +\textsl{paginazione} \index{paginazione} usato dalla memoria virtuale (vedi sez.~\ref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un file in una sezione dello spazio di indirizzi del processo. @@ -1229,7 +1229,7 @@ Il meccanismo file viene \textsl{mappata} direttamente nello spazio degli indirizzi del programma. Tutte le operazioni di lettura e scrittura su variabili contenute in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto -del file attraverso il sistema della memoria virtuale\index{memoria~virtuale} +del file attraverso il sistema della memoria virtuale \index{memoria~virtuale} che in maniera analoga a quanto avviene per le pagine che vengono salvate e rilette nella swap, si incaricherà di sincronizzare il contenuto di quel segmento di memoria con quello del file mappato su di esso. Per questo motivo @@ -1252,10 +1252,10 @@ interfaccia di caricare in memoria solo le parti del file che sono effettivamente usate ad un dato istante. -Infatti, dato che l'accesso è fatto direttamente attraverso la memoria -virtuale,\index{memoria~virtuale} la sezione di memoria mappata su cui si -opera sarà a sua volta letta o scritta sul file una pagina alla volta e solo -per le parti effettivamente usate, il tutto in maniera completamente +Infatti, dato che l'accesso è fatto direttamente attraverso la +\index{memoria~virtuale} memoria virtuale, la sezione di memoria mappata su +cui si opera sarà a sua volta letta o scritta sul file una pagina alla volta e +solo per le parti effettivamente usate, il tutto in maniera completamente trasparente al processo; l'accesso alle pagine non ancora caricate avverrà allo stesso modo con cui vengono caricate in memoria le pagine che sono state salvate sullo swap. @@ -1383,20 +1383,20 @@ 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}\itindex{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 mappata. Incompatibile con \const{MAP\_SHARED}. \\ \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare - \textit{DoS}\itindex{Denial~of~Service~(DoS)} + \textit{DoS} \itindex{Denial~of~Service~(DoS)} (veniva usato per segnalare che tentativi di scrittura sul file dovevano fallire con \errcode{ETXTBSY}).\\ \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}\itindex{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ù @@ -1434,21 +1434,21 @@ tab.~\ref{tab:file_mmap_flag}. Gli effetti dell'accesso ad una zona di memoria mappata su file possono essere piuttosto complessi, essi si possono comprendere solo tenendo presente che -tutto quanto è comunque basato sul meccanismo della memoria -virtuale.\index{memoria~virtuale} Questo comporta allora una serie di -conseguenze. La più ovvia è che se si cerca di scrivere su una zona mappata in -sola lettura si avrà l'emissione di un segnale di violazione di accesso -(\const{SIGSEGV}), dato che i permessi sul segmento di memoria relativo non -consentono questo tipo di accesso. +tutto quanto è comunque basato sul meccanismo della \index{memoria~virtuale} +memoria virtuale. Questo comporta allora una serie di conseguenze. La più +ovvia è che se si cerca di scrivere su una zona mappata in sola lettura si +avrà l'emissione di un segnale di violazione di accesso (\const{SIGSEGV}), +dato che i permessi sul segmento di memoria relativo non consentono questo +tipo di accesso. È invece assai diversa la questione relativa agli accessi al di fuori della regione di cui si è richiesta la mappatura. A prima vista infatti si potrebbe ritenere che anch'essi debbano generare un segnale di violazione di accesso; questo però non tiene conto del fatto che, essendo basata sul meccanismo della -paginazione\index{paginazione}, la mappatura in memoria non può che essere +paginazione \index{paginazione}, la mappatura in memoria non può che essere eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una pagina, ed in generale queste potranno non corrispondere alle dimensioni -effettive del file o della sezione che si vuole mappare. +effettive del file o della sezione che si vuole mappare. \footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di memoria.} @@ -1884,7 +1884,7 @@ 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 \textit{race condition}\itindex{race~condition}, attraverso una +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. @@ -2139,7 +2139,7 @@ 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}\itindex{deadlock}. Non è garantito che il sistema + \itindex{deadlock} \textit{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. @@ -2259,7 +2259,7 @@ stato effettivamente acquisito. \begin{figure}[htb] \centering \includegraphics[width=9cm]{img/file_lock_dead} - \caption{Schema di una situazione di \textit{deadlock}\itindex{deadlock}.} + \caption{Schema di una situazione di \itindex{deadlock} \textit{deadlock}.} \label{fig:file_flock_dead} \end{figure} @@ -2271,11 +2271,12 @@ 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}\itindex{deadlock}, dato che a quel punto anche +porta ad un \itindex{deadlock} \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}. +cerca di acquisire un lock che porterebbe ad un \itindex{deadlock} +\textit{deadlock}. \begin{figure}[!bht] \centering \includegraphics[width=13cm]{img/file_posix_lock} @@ -2297,7 +2298,7 @@ di fig.~\ref{fig:file_flock_struct}:\footnote{in questo caso nella figura si bloccata grazie ai campi \var{fl\_start} e \var{fl\_end}. La struttura è comunque la stessa, solo che in questo caso nel campo \var{fl\_flags} è impostato il bit \const{FL\_POSIX} ed il campo \var{fl\_file} non viene - usato.} il lock è sempre associato all'inode\index{inode}, solo che in + usato.} il lock è sempre associato \index{inode} all'inode, solo che in questo caso la titolarità non viene identificata con il riferimento ad una voce nella \itindex{file~table} \textit{file table}, ma con il valore del \acr{pid} del processo. @@ -2707,17 +2708,12 @@ implementativa\footnote{per i dettagli si possono leggere le note relative soltanto quando si chiama \func{mmap} con l'opzione \const{MAP\_SHARED} (nel qual caso la funzione fallisce con il solito \errcode{EAGAIN}) che comporta la possibilità di modificare il file. -\index{file!locking|)} -\itindend{mandatory~locking|(} +\index{file!locking|)} +\itindend{mandatory~locking|(} -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "gapil" -%%% End: - % LocalWords: dell'I locking multiplexing cap dell' sez system call socket BSD % LocalWords: descriptor client deadlock NONBLOCK EAGAIN polling select kernel % LocalWords: pselect like sys unistd int fd readfds writefds exceptfds struct @@ -2753,3 +2749,9 @@ possibilit % LocalWords: EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP % LocalWords: switch bsd lockf mandatory SVr sgid group root mount mand TRUNC % LocalWords: SVID UX Documentation sendfile + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: diff --git a/filedir.tex b/filedir.tex index a268c13..239c995 100644 --- a/filedir.tex +++ b/filedir.tex @@ -1,6 +1,6 @@ %% filedir.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -53,7 +53,7 @@ sez.~\ref{sec:file_arch_func}) ci sono due metodi sostanzialmente diversi per fare questa operazione. Come spiegato in sez.~\ref{sec:file_filesystem} l'accesso al contenuto di un -file su disco avviene passando attraverso il suo inode\index{inode}, che è la +file su disco avviene passando attraverso il suo \index{inode} inode, che è la struttura usata dal kernel che lo identifica univocamente all'interno di un singolo filesystem. Il nome del file che si trova nella voce di una directory è solo un'etichetta, mantenuta all'interno della directory, che viene @@ -61,16 +61,16 @@ associata ad un puntatore che fa riferimento al suddetto inode. Questo significa che, fintanto che si resta sullo stesso filesystem, la realizzazione di un link è immediata, ed uno stesso file può avere tanti nomi -diversi, dati da altrettante diverse associazioni allo stesso -inode\index{inode} di etichette diverse in directory diverse. Si noti anche -che nessuno di questi nomi viene ad assumere una particolare preferenza o -originalità rispetto agli altri, in quanto tutti fanno comunque riferimento -allo stesso inode\index{inode}. +diversi, dati da altrettante diverse associazioni allo stesso \index{inode} +inode di etichette diverse in directory diverse. Si noti anche che nessuno di +questi nomi viene ad assumere una particolare preferenza o originalità +rispetto agli altri, in quanto tutti fanno comunque riferimento allo stesso +\index{inode} inode. Per aggiungere ad una directory una voce che faccia riferimento ad un -inode\index{inode} già esistente si utilizza la funzione \func{link}; si suole -chiamare questo tipo di associazione un collegamento diretto (o \textit{hard - link}). Il prototipo della funzione è: +\index{inode} inode già esistente si utilizza la funzione \func{link}; si +suole chiamare questo tipo di associazione un collegamento diretto (o +\textit{hard link}). Il prototipo della funzione è: \begin{prototype}{unistd.h} {int link(const char *oldpath, const char *newpath)} Crea un nuovo collegamento diretto. @@ -93,7 +93,7 @@ chiamare questo tipo di associazione un collegamento diretto (o \textit{hard \errval{ENOSPC}, \errval{EIO}.} \end{prototype} -La funzione crea sul \itindex{pathname}\textit{pathname} \param{newpath} un +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 @@ -103,10 +103,10 @@ 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 -\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). +collegamento diretto è possibile solo se entrambi i \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 @@ -153,10 +153,10 @@ suo prototipo abbia privilegi sufficienti.} La funzione cancella il nome specificato da \param{pathname} nella relativa -directory e decrementa il numero di riferimenti nel relativo -inode\index{inode}. Nel caso di link simbolico cancella il link simbolico; nel -caso di socket, fifo o file di dispositivo\index{file!di~dispositivo} rimuove -il nome, ma come per i file i processi che hanno aperto uno di questi oggetti +directory e decrementa il numero di riferimenti nel relativo \index{inode} +inode. Nel caso di link simbolico cancella il link simbolico; nel caso di +socket, fifo o file di dispositivo \index{file!di~dispositivo} rimuove il +nome, ma come per i file i processi che hanno aperto uno di questi oggetti possono continuare ad utilizzarlo. Per cancellare una voce in una directory è necessario avere il permesso di @@ -170,14 +170,14 @@ root, per cui nessuna delle restrizioni Una delle caratteristiche di queste funzioni è che la creazione/rimozione del nome dalla directory e l'incremento/decremento del numero di riferimenti -nell'inode\index{inode} devono essere effettuati in maniera atomica (si veda +\index{inode} nell'inode devono essere effettuati in maniera atomica (si veda sez.~\ref{sec:proc_atom_oper}) senza possibili interruzioni fra le due operazioni. Per questo entrambe queste funzioni sono realizzate tramite una singola system call. Si ricordi infine che un file non viene eliminato dal disco fintanto che tutti i riferimenti ad esso sono stati cancellati: solo quando il \textit{link - count} mantenuto nell'inode\index{inode} diventa zero lo spazio occupato su + count} mantenuto \index{inode} nell'inode diventa zero lo spazio occupato su disco viene rimosso (si ricordi comunque che a questo si aggiunge sempre un'ulteriore condizione,\footnote{come vedremo in cap.~\ref{cha:file_unix_interface} il kernel mantiene anche una tabella dei @@ -255,9 +255,9 @@ nello stesso filesystem) si usa invece la funzione \funcd{rename},\footnote{la \item[\errcode{EINVAL}] \param{newpath} contiene un prefisso di \param{oldpath} o più in generale si è cercato di creare una directory come sotto-directory di se stessa. - \item[\errcode{ENOTDIR}] Uno dei componenti dei - \itindex{pathname}\textit{pathname} non è una directory o \param{oldpath} - è una directory e \param{newpath} esiste e non è una directory. + \item[\errcode{ENOTDIR}] Uno dei componenti dei \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 @@ -306,7 +306,7 @@ riferimento allo stesso file. \label{sec:file_symlink} Come abbiamo visto in sez.~\ref{sec:file_link} la funzione \func{link} crea -riferimenti agli \index{inode}inode, pertanto può funzionare soltanto per file +riferimenti agli \index{inode} inode, pertanto può funzionare soltanto per file che risiedono sullo stesso filesystem e solo per un filesystem di tipo Unix. Inoltre abbiamo visto che in Linux non è consentito eseguire un link diretto ad una directory. @@ -456,7 +456,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 \itindex{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}. @@ -484,7 +484,7 @@ ci mostrerebbe invece l'esistenza di \file{temporaneo}. \label{sec:file_dir_creat_rem} Benché in sostanza le directory non siano altro che dei file contenenti -elenchi di nomi ed \index{inode}inode, non è possibile trattarle come file +elenchi di nomi ed \index{inode} inode, non è possibile trattarle come file ordinari e devono essere create direttamente dal kernel attraverso una opportuna system call.\footnote{questo permette anche, attraverso l'uso del VFS, l'utilizzo di diversi formati per la gestione dei suddetti elenchi.} @@ -521,8 +521,8 @@ prototipo 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 -\itindex{pathname}\textit{pathname} assoluto che relativo. +\param{dirname}. Il nome può essere indicato sia come \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 @@ -557,14 +557,14 @@ 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 -\itindex{pathname}\textit{pathname} assoluto o relativo. +\file{..}). Il nome può essere indicato con il \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 +\func{unlink}: fintanto che il numero di link \index{inode} all'inode della directory non diventa nullo e nessun processo ha la directory aperta lo spazio occupato su disco non viene rilasciato. Se un processo ha la directory aperta -la funzione rimuove il link all'inode\index{inode} e nel caso sia l'ultimo, +la funzione rimuove il link \index{inode} all'inode e nel caso sia l'ultimo, pure le voci standard \file{.} e \file{..}, a questo punto il kernel non consentirà di creare più nuovi file nella directory. @@ -574,9 +574,9 @@ consentir Finora abbiamo parlato esclusivamente di file, directory e link simbolici; in sez.~\ref{sec:file_file_types} abbiamo visto però che il sistema prevede pure -degli altri tipi di file speciali, come i file di dispositivo -\index{file!di~dispositivo} e le fifo (i socket sono un caso a parte, che -tratteremo in cap.~\ref{cha:socket_intro}). +degli altri tipi di file speciali, come i \index{file!di~dispositivo} file di +dispositivo e le fifo (i socket sono un caso a parte, che tratteremo in +cap.~\ref{cha:socket_intro}). La manipolazione delle caratteristiche di questi file e la loro cancellazione può essere effettuata con le stesse funzioni che operano sui file regolari; ma @@ -626,11 +626,11 @@ usando questa funzione; ma in Linux\footnote{la funzione non codici di errore.} l'uso per la creazione di una fifo è consentito anche agli utenti normali. -I nuovi inode\index{inode} creati con \func{mknod} apparterranno al +I nuovi \index{inode} inode creati con \func{mknod} apparterranno al proprietario e al gruppo del processo che li ha creati, a meno che non si sia attivato il bit \acr{sgid} per la directory o sia stata attivata la semantica BSD per il filesystem (si veda sez.~\ref{sec:file_ownership_management}) in -cui si va a creare l'inode\index{inode}. +cui si va a creare \index{inode} l'inode. Per creare una fifo (un file speciale, su cui torneremo in dettaglio in sez.~\ref{sec:ipc_named_pipe}) lo standard POSIX specifica l'uso della funzione @@ -659,7 +659,7 @@ modificati dal valore di \var{umask}. \label{sec:file_dir_read} Benché le directory alla fine non siano altro che dei file che contengono -delle liste di nomi ed \index{inode}inode, per il ruolo che rivestono nella +delle liste di nomi ed \index{inode} inode, per il ruolo che rivestono nella struttura del sistema, non possono essere trattate come dei normali file di dati. Ad esempio, onde evitare inconsistenze all'interno del filesystem, solo il kernel può scrivere il contenuto di una directory, e non può essere un @@ -696,7 +696,7 @@ cap.~\ref{cha:files_std_interface}). La prima funzione di questa interfaccia La funzione apre un \textit{directory stream} per la directory \param{dirname}, ritornando il puntatore ad un oggetto di tipo \type{DIR} (che -è il tipo opaco\index{tipo!opaco} usato dalle librerie per gestire i +è il \index{tipo!opaco} tipo opaco usato dalle librerie per gestire i \textit{directory stream}) da usare per tutte le operazioni successive, la funzione inoltre posiziona lo stream sulla prima voce contenuta nella directory. @@ -768,7 +768,7 @@ con i thread; il suo prototipo \end{functions} La funzione restituisce in \param{result} (come -\itindex{value~result~argument}\textit{value result argument}) l'indirizzo +\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). @@ -783,7 +783,7 @@ terminata da uno zero,\footnote{lo standard POSIX non specifica una lunghezza, ma solo un limite \const{NAME\_MAX}; in SVr4 la lunghezza del campo è definita come \code{NAME\_MAX+1} che di norma porta al valore di 256 byte usato anche in Linux.} ed il campo \var{d\_ino}, che contiene il numero di -\index{inode}inode cui il file è associato (di solito corrisponde al campo +\index{inode} inode cui il file è associato (di solito corrisponde al campo \var{st\_ino} di \struct{stat}). \begin{figure}[!htb] @@ -1065,8 +1065,8 @@ resta la stessa quando viene creato un processo figlio (vedi 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 \textit{pathname} +In genere il kernel tiene traccia per ciascun processo \index{inode} +dell'inode 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)} @@ -1165,8 +1165,8 @@ In molte occasioni sembri semplice, in realtà il problema è più sottile di quanto non appaia a 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}\itindex{race~condition} (si ricordi quanto visto in +controllo e la creazione si ha giusto lo spazio per una possibile +\itindex{race~condition} \textit{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, @@ -1245,8 +1245,8 @@ POSIX definisce la funzione \funcd{tmpfile}, il cui prototipo 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}\itindex{race~condition}. +funzione è rientrante e non soffre di problemi di \itindex{race~condition} +\textit{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 @@ -1267,7 +1267,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}\itindex{race~condition} date per +alle possibili \itindex{race~condition} \textit{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à @@ -1317,8 +1317,8 @@ In OpenBSD \end{prototype} \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}\itindex{race~condition} non si pongono. +della directory è sempre esclusiva i precedenti problemi di +\itindex{race~condition} \textit{race condition} non si pongono. \section{La manipolazione delle caratteristiche dei file} @@ -1326,11 +1326,11 @@ della directory Come spiegato in sez.~\ref{sec:file_filesystem} tutte le informazioni generali relative alle caratteristiche di ciascun file, a partire dalle informazioni -relative al controllo di accesso, sono mantenute nell'inode\index{inode}. +relative al controllo di accesso, sono mantenute \index{inode} nell'inode. Vedremo in questa sezione come sia possibile leggere tutte queste informazioni usando la funzione \func{stat}, che permette l'accesso a tutti i dati -memorizzati nell'inode\index{inode}; esamineremo poi le varie funzioni usate +memorizzati \index{inode} nell'inode; esamineremo poi le varie funzioni usate per manipolare tutte queste informazioni (eccetto quelle che riguardano la gestione del controllo di accesso, trattate in in sez.~\ref{sec:file_access_control}). @@ -1548,8 +1548,8 @@ dimensione si possono usare le due funzioni \funcd{truncate} e per \func{truncate} si hanno: \begin{errlist} \item[\errcode{EACCES}] il file non ha permesso di scrittura o non si ha il - permesso di esecuzione una delle directory del - \itindex{pathname}\textit{pathname}. + permesso di esecuzione una delle directory del \itindex{pathname} + \textit{pathname}. \item[\errcode{ETXTBSY}] Il file è un programma in esecuzione. \end{errlist} ed anche \errval{ENOTDIR}, \errval{ENAMETOOLONG}, \errval{ENOENT}, @@ -1567,9 +1567,9 @@ zeri (e in genere si ha la creazione di un \textit{hole} nel file). \label{sec:file_file_times} Il sistema mantiene per ciascun file tre tempi. Questi sono registrati -nell'inode\index{inode} insieme agli altri attributi del file e possono essere -letti tramite la funzione \func{stat}, che li restituisce attraverso tre campi -della struttura \struct{stat} di fig.~\ref{fig:file_stat_struct}. Il +\index{inode} nell'inode insieme agli altri attributi del file e possono +essere letti tramite la funzione \func{stat}, che li restituisce attraverso +tre campi della struttura \struct{stat} di fig.~\ref{fig:file_stat_struct}. Il significato di detti tempi e dei relativi campi è riportato nello schema in tab.~\ref{tab:file_file_times}, dove è anche riportato un esempio delle funzioni che effettuano cambiamenti su di essi. @@ -1599,9 +1599,9 @@ Il primo punto da tenere presente modifica (il \textit{modification time} \var{st\_mtime}) e il tempo di cambiamento di stato (il \textit{change time} \var{st\_ctime}). Il primo infatti fa riferimento ad una modifica del contenuto di un file, mentre il -secondo ad una modifica dell'inode\index{inode}; siccome esistono molte +secondo ad una modifica \index{inode} dell'inode; siccome esistono molte operazioni (come la funzione \func{link} e molte altre che vedremo in seguito) -che modificano solo le informazioni contenute nell'inode\index{inode} senza +che modificano solo le informazioni contenute \index{inode} nell'inode senza toccare il contenuto del file, diventa necessario l'utilizzo di un altro tempo. @@ -1717,7 +1717,7 @@ funzione \funcd{utime}, il cui prototipo \begin{prototype}{utime.h} {int utime(const char *filename, struct utimbuf *times)} -Cambia i tempi di ultimo accesso e modifica dell'inode\index{inode} +Cambia i tempi di ultimo accesso e modifica \index{inode} dell'inode specificato da \param{filename} secondo i campi \var{actime} e \var{modtime} di \param{times}. Se questa è \val{NULL} allora viene usato il tempo corrente. @@ -1753,7 +1753,7 @@ del file (o si hanno i privilegi di amministratore). Si tenga presente che non è comunque possibile specificare il tempo di cambiamento di stato del file, che viene comunque cambiato dal kernel tutte le -volte che si modifica l'inode\index{inode} (quindi anche alla chiamata di +volte che si modifica \index{inode} l'inode (quindi anche alla chiamata di \func{utime}). Questo serve anche come misura di sicurezza per evitare che si possa modificare un file nascondendo completamente le proprie tracce. In realtà la cosa resta possibile, se si è in grado di accedere al file di @@ -1835,7 +1835,7 @@ sez.~\ref{sec:file_special_perm}); lo schema di allocazione dei bit riportato in fig.~\ref{fig:file_perm_bit}. Anche i permessi, come tutte le altre informazioni pertinenti al file, sono -memorizzati nell'inode\index{inode}; in particolare essi sono contenuti in +memorizzati \index{inode} nell'inode; in particolare essi sono contenuti in alcuni bit del campo \var{st\_mode} della struttura \struct{stat} (si veda di nuovo fig.~\ref{fig:file_stat_struct}). @@ -1881,15 +1881,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 -\itindex{pathname}\textit{pathname} occorre il permesso di esecuzione in +\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 \itindex{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 diff --git a/fileintro.tex b/fileintro.tex index 628ab8a..baef2ca 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -1,6 +1,6 @@ %% fileintro.tex %% -%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Prefazione", @@ -19,10 +19,11 @@ file di dati. Questo significa che si può accedere a qualunque periferica del computer, dalla seriale, alla parallela, alla console, e agli stessi dischi attraverso i -cosiddetti file di dispositivo\index{file!di~dispositivo} (i \textit{device - file}). Questi sono dei file speciali agendo sui quali i programmi possono -leggere, scrivere e compiere operazioni direttamente sulle periferiche, usando -le stesse funzioni che si usano per i normali file di dati. +cosiddetti \index{file!di~dispositivo} file di dispositivo (i cosiddetti +\textit{device file}). Questi sono dei file speciali agendo sui quali i +programmi possono leggere, scrivere e compiere operazioni direttamente sulle +periferiche, usando le stesse funzioni che si usano per i normali file di +dati. In questo capitolo forniremo una descrizione dell'architettura dei file in Linux, iniziando da una panoramica sulle caratteristiche principali delle @@ -95,7 +96,7 @@ specificandone il nome\footnote{Il manuale delle \acr{glibc} chiama i nomi \textsl{voci}.} da essa contenuto. All'interno dello stesso albero si potranno poi inserire anche tutti gli altri oggetti visti attraverso l'interfaccia che manipola i file come le fifo, i link, i socket e gli stessi -file di dispositivo \index{file!di~dispositivo} (questi ultimi, per +\index{file!di~dispositivo} file di dispositivo (questi ultimi, per convenzione, sono inseriti nella directory \file{/dev}). Il nome completo di un file viene chiamato \textit{pathname} ed il @@ -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}\itindex{Virtual~File~System} è riportato in +\itindex{Virtual~File~System} \textit{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 @@ -146,7 +147,7 @@ Alcuni di essi, come le \textit{fifo} (che tratteremo in sez.~\ref{sec:ipc_named_pipe}) ed i \textit{socket} (che tratteremo in cap.~\ref{cha:socket_intro}) non sono altro che dei riferimenti per utilizzare delle funzionalità di comunicazione fornite dal kernel. Gli altri sono i -\textsl{file di dispositivo} \index{file!di~dispositivo} (o \textit{device +\index{file!di~dispositivo} \textsl{file di dispositivo} (o \textit{device file}) che costituiscono una interfaccia diretta per leggere e scrivere sui dispositivi fisici; essi vengono suddivisi in due grandi categorie, \textsl{a blocchi} e \textsl{a caratteri} a seconda delle modalità in cui il @@ -169,7 +170,7 @@ dispositivo sottostante effettua le operazioni di I/O.\footnote{in sostanza i un file che contiene dei dati (l'accezione normale di file) \\ \textit{directory} & \textsl{cartella o direttorio} & un file che contiene una lista di nomi associati a degli - \textit{inode}\index{inode} (vedi sez.~\ref{sec:file_vfs}). \\ + \index{inode} \textit{inode} (vedi sez.~\ref{sec:file_vfs}). \\ \textit{symbolic link} & \textsl{collegamento simbolico} & un file che contiene un riferimento ad un altro file/directory \\ \textit{char device} & \textsl{dispositivo a caratteri} & @@ -198,10 +199,10 @@ VMS.\footnote{questo vale anche per i dispositivi a blocchi: la strutturazione dell'I/O in blocchi di dimensione fissa avviene solo all'interno del kernel, ed è completamente trasparente all'utente. Inoltre talvolta si parla di \textsl{accesso diretto} riferendosi alla capacità, che non ha niente a che - fare con tutto ciò, di effettuare, attraverso degli appositi file di - dispositivo\index{file!di~dispositivo}, operazioni di I/O direttamente sui - dischi senza passare attraverso un filesystem (il cosiddetto \textit{raw - access}, introdotto coi kernel della serie 2.4.x).} + fare con tutto ciò, di effettuare, attraverso degli appositi + \index{file!di~dispositivo} file di dispositivo, operazioni di I/O + direttamente sui dischi senza passare attraverso un filesystem (il + cosiddetto \textit{raw access}, introdotto coi kernel della serie 2.4.x).} Una seconda differenza è nel formato dei file ASCII: in Unix la fine riga è codificata in maniera diversa da Windows o Mac, in particolare il fine riga è @@ -246,22 +247,27 @@ L'interfaccia bufferizzato in quanto la lettura e la scrittura vengono eseguite chiamando direttamente le system call del kernel (in realtà il kernel effettua al suo interno alcune bufferizzazioni per aumentare l'efficienza nell'accesso ai -dispositivi); i \textit{file descriptor}\index{file!descriptor} sono +dispositivi); i \index{file!descriptor} \textit{file descriptor} sono rappresentati da numeri interi (cioè semplici variabili di tipo \ctyp{int}). L'interfaccia è definita nell'header \file{unistd.h}. La seconda interfaccia è quella che il manuale della \acr{glibc} chiama degli -\textit{stream}\index{file!stream}. Essa fornisce funzioni più evolute e un -accesso bufferizzato (controllato dalla implementazione fatta dalle -\acr{glibc}), la tratteremo in dettaglio nel +\index{file!stream} \textit{stream}.\footnote{in realtà una interfaccia con lo + stesso nome è stata introdotta a livello di kernel negli Unix derivati da + \textit{System V}, come strato di astrazione per file e socket; in Linux + questa interfaccia, che comunque ha avuto poco successo, non esiste, per cui + facendo riferimento agli \index{file!stream} \textit{stream} useremo il + significato adottato dal manuale delle \acr{glibc}.} Essa fornisce funzioni +più evolute e un accesso bufferizzato (controllato dalla implementazione fatta +dalle \acr{glibc}), la tratteremo in dettaglio nel cap.~\ref{cha:files_std_interface}. Questa è l'interfaccia standard specificata dall'ANSI C e perciò si trova -anche su tutti i sistemi non Unix. Gli \textit{stream}\index{file!stream} sono -oggetti complessi e sono rappresentati da puntatori ad un opportuna struttura -definita dalle librerie del C; si accede ad essi sempre in maniera indiretta -utilizzando il tipo \ctyp{FILE *}. L'interfaccia è definita nell'header -\file{stdio.h}. +anche su tutti i sistemi non Unix. Gli \index{file!stream} \textit{stream} +sono oggetti complessi e sono rappresentati da puntatori ad un opportuna +struttura definita dalle librerie del C; si accede ad essi sempre in maniera +indiretta utilizzando il tipo \ctyp{FILE *}. L'interfaccia è definita +nell'header \file{stdio.h}. Entrambe le interfacce possono essere usate per l'accesso ai file come agli altri oggetti del VFS (fifo, socket, dispositivi, sui quali torneremo in @@ -269,8 +275,8 @@ dettaglio a tempo opportuno), ma per poter accedere alle operazioni di controllo (descritte in sez.~\ref{sec:file_fcntl} e sez.~\ref{sec:file_ioctl}) su un qualunque tipo di oggetto del VFS occorre usare l'interfaccia standard di Unix con i \textit{file descriptor}. Allo stesso modo devono essere usati i -\textit{file descriptor} \index{file!descriptor} se si vuole ricorrere a -modalità speciali di I/O come il \textit{file locking}\index{file!locking} o +\index{file!descriptor} \textit{file descriptor} se si vuole ricorrere a +modalità speciali di I/O come il \index{file!locking} \textit{file locking} o l'I/O non-bloccante (vedi cap.~\ref{cha:file_advanced}). Gli \textit{stream} forniscono un'interfaccia di alto livello costruita sopra @@ -279,20 +285,20 @@ diversi stili di bufferizzazione. Il maggior vantaggio degli \textit{stream} è che l'interfaccia per le operazioni di input/output è enormemente più ricca di quella dei \textit{file descriptor}, che forniscono solo funzioni elementari per la lettura/scrittura diretta di blocchi di byte. In -particolare gli \textit{stream}\index{file!stream} dispongono di tutte le +particolare gli \index{file!stream} \textit{stream} dispongono di tutte le funzioni di formattazione per l'input e l'output adatte per manipolare anche i dati in forma di linee o singoli caratteri. In ogni caso, dato che gli stream sono implementati sopra l'interfaccia standard di Unix, è sempre possibile estrarre il \textit{file descriptor} da uno stream ed eseguirvi operazioni di basso livello, o associare in un secondo -tempo uno \textit{stream}\index{file!stream} ad un \textit{file - descriptor}\index{file!descriptor}. +tempo uno \index{file!stream} \textit{stream} ad un \index{file!descriptor} +\textit{file descriptor}. In generale, se non necessitano specificatamente le funzionalità di basso -livello, è opportuno usare sempre gli \textit{stream}\index{file!stream} per +livello, è opportuno usare sempre gli \index{file!stream} \textit{stream} per la loro maggiore portabilità, essendo questi ultimi definiti nello standard -ANSI C; l'interfaccia con i \textit{file descriptor}\index{file!descriptor} +ANSI C; l'interfaccia con i \index{file!descriptor} \textit{file descriptor} infatti segue solo lo standard POSIX.1 dei sistemi Unix, ed è pertanto di portabilità più limitata. @@ -301,18 +307,18 @@ portabilit \section{L'architettura della gestione dei file} \label{sec:file_arch_func} - In questa sezione esamineremo come viene implementato l'accesso ai file in Linux, come il kernel può gestire diversi tipi di filesystem, descrivendo prima le caratteristiche generali di un filesystem di un sistema unix-like, per poi trattare in maniera un po' più dettagliata il filesystem più usato con -Linux, l'\acr{ext2}. +Linux, l'\acr{ext2} (e derivati). \subsection{Il \textit{Virtual File System} di Linux} \label{sec:file_vfs} \itindbeg{Virtual~File~System} + In Linux il concetto di \textit{everything is a file} è stato implementato 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 @@ -341,7 +347,7 @@ fig.~\ref{fig:file_VFS_scheme}. Il VFS definisce un insieme di funzioni che tutti i filesystem devono implementare. L'interfaccia comprende tutte le funzioni che riguardano i file; le operazioni sono suddivise su tre tipi di oggetti: \textit{filesystem}, -\textit{inode}\index{inode} e \textit{file}, corrispondenti a tre apposite +\index{inode} \textit{inode} e \textit{file}, corrispondenti a tre apposite strutture definite nel kernel. Il VFS usa una tabella mantenuta dal kernel che contiene il nome di ciascun @@ -371,7 +377,7 @@ Gli altri due descrittori usati dal VFS sono relativi agli altri due oggetti su cui è strutturata l'interfaccia. Ciascuno di essi contiene le informazioni relative al file in uso, insieme ai puntatori alle funzioni dello specifico filesystem usate per l'accesso dal VFS; in particolare il descrittore -dell'inode\index{inode} contiene i puntatori alle funzioni che possono essere +\index{inode} dell'inode contiene i puntatori alle funzioni che possono essere usate su qualunque file (come \func{link}, \func{stat} e \func{open}), mentre il descrittore di file contiene i puntatori alle funzioni che vengono usate sui file già aperti. @@ -381,17 +387,17 @@ sui file gi \label{sec:file_vfs_work} La funzione più importante implementata dal VFS è la system call \func{open} -che permette di aprire un file. Dato un \itindex{pathname}\textit{pathname} +che permette di aprire un file. Dato un \itindex{pathname} \textit{pathname} viene eseguita una ricerca dentro la \textit{directory entry cache} (in breve \textit{dcache}), una tabella che contiene tutte le \textit{directory entry} (in breve \textit{dentry}) che permette di associare in maniera rapida ed efficiente il \textit{pathname} a una specifica \textit{dentry}. Una singola \textit{dentry} contiene in genere il puntatore ad un -\textit{inode}\index{inode}; quest'ultimo è la struttura base che sta sul +\index{inode} \textit{inode}; quest'ultimo è la struttura base che sta sul disco e che identifica un singolo oggetto del VFS sia esso un file ordinario, una directory, un link simbolico, una FIFO, un file di -dispositivo\index{file!di~dispositivo}, o una qualsiasi altra cosa che possa +\index{file!di~dispositivo} dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal VFS (i tipi di file riportati in tab.~\ref{tab:file_file_types}). A ciascuno di essi è associata pure una struttura che sta in memoria, e che, oltre alle informazioni sullo specifico @@ -399,28 +405,28 @@ file, contiene anche il riferimento alle funzioni (i \textsl{metodi} del VFS) da usare per poterlo manipolare. Le \textit{dentry} ``vivono'' in memoria e non vengono mai salvate su disco, -vengono usate per motivi di velocità, gli \textit{inode}\index{inode} invece +vengono usate per motivi di velocità, gli \index{inode} \textit{inode} invece stanno su disco e vengono copiati in memoria quando serve, ed ogni cambiamento -viene copiato all'indietro sul disco, gli inode\index{inode} che stanno in -memoria sono inode\index{inode} del VFS ed è ad essi che puntano le singole +viene copiato all'indietro sul disco, gli \index{inode} inode che stanno in +memoria sono \index{inode} inode del VFS ed è ad essi che puntano le singole \textit{dentry}. La \textit{dcache} costituisce perciò una sorta di vista completa di tutto l'albero dei file, ovviamente per non riempire tutta la memoria questa vista è parziale (la \textit{dcache} cioè contiene solo le \textit{dentry} per i file per i quali è stato richiesto l'accesso), quando si vuole risolvere un nuovo -\itindex{pathname}\textit{pathname} il VFS deve creare una nuova -\textit{dentry} e caricare l'inode\index{inode} corrispondente in memoria. +\itindex{pathname} \textit{pathname} il VFS deve creare una nuova +\textit{dentry} e caricare \index{inode} l'inode corrispondente in memoria. -Questo procedimento viene eseguito dal metodo \code{lookup()} -dell'inode\index{inode} della directory che contiene il file; questo viene -installato nelle relative strutture in memoria quando si effettua il montaggio -lo specifico filesystem su cui l'inode va a vivere. +Questo procedimento viene eseguito dal metodo \code{lookup()} \index{inode} +dell'inode della directory che contiene il file; questo viene installato nelle +relative strutture in memoria quando si effettua il montaggio lo specifico +filesystem su cui l'inode va a vivere. Una volta che il VFS ha a disposizione la \textit{dentry} (ed il relativo \textit{inode}) diventa possibile accedere alle varie operazioni sul file come la \func{open} per aprire il file o la \func{stat} per leggere i dati -dell'inode\index{inode} e passarli in user space. +\index{inode} dell'inode e passarli in user space. L'apertura di un file richiede comunque un'altra operazione, l'allocazione di una struttura di tipo \struct{file} in cui viene inserito un puntatore alla @@ -500,7 +506,7 @@ superblock (ma sulle caratteristiche di \acr{ext2} torneremo in sez.~\ref{sec:file_ext2}). È comunque caratteristica comune di tutti i filesystem per Unix, indipendentemente da come poi viene strutturata nei dettagli questa informazione, prevedere una divisione fra la lista degli -inode\index{inode} e lo spazio a disposizione per i dati e le directory. +\index{inode} inode e lo spazio a disposizione per i dati e le directory. \begin{figure}[htb] \centering @@ -532,13 +538,13 @@ particolare \begin{enumerate} -\item L'\textit{inode}\index{inode} contiene tutte le informazioni riguardanti - il file: il tipo di file, i permessi di accesso, le dimensioni, i puntatori - ai blocchi fisici che contengono i dati e così via; le informazioni che la - funzione \func{stat} fornisce provengono dall'\textit{inode}; dentro una - directory si troverà solo il nome del file e il numero - dell'\textit{inode}\index{inode} ad esso associato, cioè quella che da qui - in poi chiameremo una \textsl{voce} (come traduzione dell'inglese +\item L'\textit{inode} \index{inode} contiene tutte le informazioni + riguardanti il file: il tipo di file, i permessi di accesso, le dimensioni, + i puntatori ai blocchi fisici che contengono i dati e così via; le + informazioni che la funzione \func{stat} fornisce provengono + dall'\textit{inode}; dentro una directory si troverà solo il nome del file e + il numero \index{inode} dell'\textit{inode} ad esso associato, cioè quella + che da qui in poi chiameremo una \textsl{voce} (come traduzione dell'inglese \textit{directory entry}, che non useremo anche per evitare confusione con le \textit{dentry} del kernel di cui si parlava in sez.~\ref{sec:file_vfs}). @@ -549,18 +555,18 @@ particolare file vengono effettivamente rimossi dal disco. Per questo la funzione per cancellare un file si chiama \func{unlink}, ed in realtà non cancella affatto i dati del file, ma si limita ad eliminare la relativa voce da una - directory e decrementare il numero di riferimenti - nell'\textit{inode}\index{inode}. + directory e decrementare il numero di riferimenti \index{inode} + nell'\textit{inode}. \item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode} nello stesso filesystem e non ci può essere una directory che contiene - riferimenti ad \textit{inode}\index{inode} relativi ad altri filesystem. + riferimenti ad \index{inode} \textit{inode} relativi ad altri filesystem. Questo limita l'uso del comando \cmd{ln} (che crea una nuova voce per un file esistente, con la funzione \func{link}) al filesystem corrente. \item Quando si cambia nome ad un file senza cambiare filesystem, il contenuto del file non viene spostato fisicamente, viene semplicemente creata una - nuova voce per l'\textit{inode}\index{inode} in questione e rimossa la + nuova voce per \index{inode} l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità in cui opera normalmente il comando \cmd{mv} attraverso la funzione \func{rename}). @@ -571,7 +577,7 @@ riferimenti anche per le directory; per cui, se a partire dalla situazione mostrata in fig.~\ref{fig:file_filesys_detail} creiamo una nuova directory \file{img} nella directory \file{gapil}, avremo una situazione come quella in fig.~\ref{fig:file_dirs_link}, dove per chiarezza abbiamo aggiunto dei numeri -di inode\index{inode}. +di \index{inode} inode. \begin{figure}[htb] \centering @@ -617,7 +623,7 @@ non sono presenti sugli altri filesystem Unix. Le principali sono le seguenti: in fase di creazione, a seconda delle sue esigenze (blocchi più grandi permettono un accesso più veloce, ma sprecano più spazio disco). \item il filesystem implementa link simbolici veloci, in cui il nome del file - non è salvato su un blocco, ma tenuto all'interno dell'inode\index{inode} + non è salvato su un blocco, ma tenuto all'interno \index{inode} dell'inode (evitando letture multiple e spreco di spazio), non tutti i nomi però possono essere gestiti così per limiti di spazio (il limite è 60 caratteri). \item vengono supportati i file immutabili (che possono solo essere letti) per @@ -650,23 +656,18 @@ superblock principale. \label{fig:file_ext2_dirs} \end{figure} -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}. +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 \index{inode} inode. -Le directory sono implementate come una \itindex{linked~list}\textit{linked +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 +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. -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "gapil" -%%% End: - % LocalWords: everything is device kernel filesystem sez pathname root glibc % LocalWords: path filename bootloader proc name components fifo socket dev LF % LocalWords: resolution chroot parent Virtual System like tab cap l'I regular @@ -678,3 +679,9 @@ caratteri) senza sprecare spazio disco. % LocalWords: multiplexing mmap fsync fasync seek MacOs group dall' dell' img % LocalWords: count unlink nell' rename gapil second Tb attributes BSD SVr gid % LocalWords: sgid append only log fs linux extented linked list + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: diff --git a/filestd.tex b/filestd.tex index b2a3c18..15da6a7 100644 --- a/filestd.tex +++ b/filestd.tex @@ -1,6 +1,6 @@ %% filestd.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{I file: l'interfaccia standard ANSI C} \label{cha:files_std_interface} @@ -37,6 +38,7 @@ costituire il nucleo\footnote{queste funzioni sono state implementate la prima \label{sec:file_stream} \index{file!stream|(} + Come più volte ribadito, l'interfaccia dei file descriptor è un'interfaccia di basso livello, che non provvede nessuna forma di formattazione dei dati e nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O. @@ -69,6 +71,7 @@ formattazioni), i file stream restano del tutto equivalenti ai file descriptor (sui quali sono basati), ed in particolare continua a valere quanto visto in sez.~\ref{sec:file_sharing} a proposito dell'accesso condiviso ed in sez.~\ref{sec:file_access_control} per il controllo di accesso. + \index{file!stream|)} @@ -83,7 +86,7 @@ stream, come la posizione corrente, lo stato del buffer e degli indicatori di stato e di fine del file. Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare -queste strutture (che sono dei \textsl{tipi opachi}\index{tipo!opaco}) ma +queste strutture (che sono dei \index{tipo!opaco} \textsl{tipi opachi}) ma usare sempre puntatori del tipo \texttt{FILE *} ottenuti dalla libreria stessa (tanto che in certi casi il termine di puntatore a file è diventato sinonimo di stream). Tutte le funzioni della libreria che operano sui file accettano @@ -748,10 +751,11 @@ dentro la stringa. Se la lettura incontra la fine del file (o c' 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}\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}.} +stringa letta superi le dimensioni del buffer, si avrà un +\itindex{buffer~overflow} \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}.} Questa è una delle vulnerabilità più sfruttate per guadagnare accessi non autorizzati al sistema (i cosiddetti \textit{exploit}), basta infatti inviare @@ -867,7 +871,7 @@ Se il buffer di destinazione subito, altrimenti il buffer viene allargato usando \func{realloc} e la nuova dimensione ed il nuovo puntatore vengono restituiti indietro (si noti infatti come per entrambi gli argomenti si siano usati dei -\itindex{value~result~argument}\textit{value result argument}, passando dei +\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}). @@ -877,7 +881,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 \textit{memory leak}\itindex{memory~leak} occorre ricordarsi di +e per evitare \itindex{memory~leak} \textit{memory leak} occorre ricordarsi di liberare \var{ptr} con una \func{free}. Il valore di ritorno della funzione indica il numero di caratteri letti @@ -932,8 +936,9 @@ 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}\itindex{buffer~overflow}; per questo motivo -si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo è: +possibili \itindex{buffer~overflow} \textit{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 @@ -943,7 +948,7 @@ si consiglia l'uso dell'alternativa \funcd{snprintf}, il cui prototipo La parte più complessa delle funzioni di scrittura formattata è il formato della stringa \param{format} che indica le conversioni da fare, e da cui deriva anche il numero degli argomenti che dovranno essere passati a seguire -(si noti come tutte queste funzioni siano \textit{variadic}\index{variadic}, +(si noti come tutte queste funzioni siano \index{variadic} \textit{variadic}, prendendo un numero di argomenti variabile che dipende appunto da quello che si è specificato in \param{format}). @@ -1117,8 +1122,8 @@ scritti sulla stringa di destinazione: Identica a \func{vsprintf}, ma non scrive su \param{str} più di \param{size} caratteri. \end{prototype} -\noindent in modo da evitare possibili buffer -overflow\itindex{buffer~overflow}. +\noindent in modo da evitare possibili \itindex{buffer~overflow} buffer +overflow. Per eliminare alla radice questi problemi, le \acr{glibc} supportano una @@ -1144,11 +1149,11 @@ sono: 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 \itindex{value~result~argument}\textit{value result argument}) +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}. +la stringa non serve più, onde evitare \itindex{memory~leak} \textit{memory + leak}. Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e \func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre @@ -1230,9 +1235,9 @@ all'interno di un file per effettuare operazioni di lettura o scrittura in un punto prestabilito; sempre che l'operazione di riposizionamento sia supportata dal file sottostante lo stream, quando cioè si ha a che fare con quello che viene detto un file ad \textsl{accesso casuale}.\footnote{dato che in un - sistema Unix esistono vari tipi di file, come le fifo ed i file di - dispositivo\index{file!di~dispositivo}, non è scontato che questo sia sempre - vero.} + sistema Unix esistono vari tipi di file, come le fifo ed i + \index{file!di~dispositivo} file di dispositivo, non è scontato che questo + sia sempre vero.} In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel file è espressa da un intero positivo, rappresentato dal tipo \type{off\_t}, il diff --git a/fileunix.tex b/fileunix.tex index 95dc184..7ff6ca0 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -1,6 +1,6 @@ %% fileunix.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -13,7 +13,7 @@ Esamineremo in questo capitolo la prima delle due interfacce di programmazione -per i file, quella dei \textit{file descriptor}\index{file!descriptor}, +per i file, quella dei \index{file!descriptor} \textit{file descriptor}, nativa di Unix. Questa è l'interfaccia di basso livello provvista direttamente dalle system call, che non prevede funzionalità evolute come la bufferizzazione o funzioni di lettura o scrittura formattata, e sulla quale è @@ -36,12 +36,12 @@ tutte le implementazione di un sistema unix-like. \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 -l'inode\index{inode} del file e inizializzare i puntatori che rendono -disponibili le funzioni che il VFS mette a disposizione (riportate in +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 \index{inode} l'inode +del file e inizializzare i puntatori che rendono disponibili le funzioni che +il VFS mette a disposizione (riportate in tab.~\ref{tab:file_file_operations}). Una volta terminate le operazioni, il file dovrà essere chiuso, e questo chiuderà il canale di comunicazione impedendo ogni ulteriore operazione. @@ -83,9 +83,9 @@ informazioni relative al file, fra cui: \item il valore della posizione corrente (l'\textit{offset}) nel file (nel campo \var{f\_pos}). \item un puntatore \index{inode} all'inode\footnote{nel kernel 2.4.x si è in - realtà passati ad un puntatore ad una struttura \struct{dentry} che punta a - sua volta all'inode\index{inode} passando per la nuova struttura del VFS.} - del file. + realtà passati ad un puntatore ad una struttura \struct{dentry} che punta + a sua volta \index{inode} all'inode passando per la nuova struttura del + VFS.} del file. %\item un puntatore alla tabella delle funzioni \footnote{la struttura % \var{f\_op} descritta in sez.~\ref{sec:file_vfs_work}} che si possono usare % sul file. @@ -97,6 +97,7 @@ varie strutture di dati sulla quale essa Ritorneremo su questo schema più volte, dato che esso è fondamentale per capire i dettagli del funzionamento dell'interfaccia dei \textit{file descriptor}. + \index{file!descriptor|)} \begin{figure}[htb] @@ -160,7 +161,7 @@ In fig.~\ref{fig:file_proc_file} si facendo riferimento ad un programma in cui lo \textit{standard input} è associato ad un file mentre lo \textit{standard output} e lo \textit{standard error} sono entrambi associati ad un altro file (e quindi utilizzano lo -stesso inode\index{inode}). +stesso \index{inode} inode). Nelle vecchie versioni di Unix (ed anche in Linux fino al kernel 2.0.x) il numero di file aperti era anche soggetto ad un limite massimo dato dalle @@ -188,8 +189,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 \itindex{pathname}\textit{pathname} ed -un file descriptor, il suo prototipo è: +quella che crea l'associazione fra un \itindex{pathname} \textit{pathname} ed +un \index{file!descriptor} file descriptor, il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/stat.h} @@ -235,15 +236,15 @@ ritorno il file descriptor con il 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 - \textit{race condition}\itindex{race~condition}. Si consiglia come + \index{file!di lock} \textsl{file di lock} possono incorrere in una + \itindex{race~condition} \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}).} -\footnotetext[3]{acronimo di \textit{Denial of - Service}\itindex{Denial~of~Service~(DoS)}, si chiamano così attacchi - miranti ad impedire un servizio causando una qualche forma di carico - eccessivo per il sistema, che resta bloccato nelle risposte all'attacco.} +\footnotetext[3]{acronimo di \itindex{Denial~of~Service~(DoS)} \textit{Denial + of Service}, si chiamano così attacchi miranti ad impedire un servizio + causando una qualche forma di carico eccessivo per il sistema, che resta + bloccato nelle risposte all'attacco.} \begin{table}[!htb] \centering @@ -549,7 +550,7 @@ 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 \itindex{race~condition}\textit{race +(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 @@ -768,35 +769,35 @@ confronti dell'accesso allo stesso file da parte di processi diversi. \label{fig:file_mult_acc} \end{figure} -Il primo caso è quello in cui due processi diversi aprono lo stesso file -su disco; sulla base di quanto visto in sez.~\ref{sec:file_fd} avremo una +Il primo caso è quello in cui due processi diversi aprono lo stesso file su +disco; sulla base di quanto visto in sez.~\ref{sec:file_fd} avremo una situazione come quella illustrata in fig.~\ref{fig:file_mult_acc}: ciascun processo avrà una sua voce nella \textit{file table} referenziata da un diverso file descriptor nella sua \struct{file\_struct}. Entrambe le voci -nella \textit{file table} faranno però riferimento allo stesso -inode\index{inode} su disco. +nella \itindex{file~table} \textit{file table} faranno però riferimento allo +stesso \index{inode} inode su disco. Questo significa che ciascun processo avrà la sua posizione corrente sul file, la sua modalità di accesso e versioni proprie di tutte le proprietà che -vengono mantenute nella sua voce della \textit{file table}. Questo ha -conseguenze specifiche sugli effetti della possibile azione simultanea sullo -stesso file, in particolare occorre tenere presente che: +vengono mantenute nella sua voce della \itindex{file~table} \textit{file + table}. Questo ha conseguenze specifiche sugli effetti della possibile +azione simultanea sullo stesso file, in particolare occorre tenere presente +che: \begin{itemize} \item ciascun processo può scrivere indipendentemente; dopo ciascuna \func{write} la posizione corrente sarà cambiata solo nel processo. Se la scrittura eccede la dimensione corrente del file questo verrà esteso - automaticamente con l'aggiornamento del campo \var{i\_size} - nell'inode\index{inode}. + automaticamente con l'aggiornamento del campo \var{i\_size} \index{inode} + nell'inode. \item se un file è in modalità \itindex{append~mode} \const{O\_APPEND} tutte le volte che viene effettuata una scrittura la posizione corrente viene - prima impostata alla dimensione corrente del file letta - dall'inode\index{inode}. Dopo la scrittura il file viene automaticamente - esteso. + prima impostata alla dimensione corrente del file letta \index{inode} + dall'inode. Dopo la scrittura il file viene automaticamente esteso. \item l'effetto di \func{lseek} è solo quello di cambiare il campo - \var{f\_pos} nella struttura \struct{file} della \textit{file table}, non - c'è nessuna operazione sul file su disco. Quando la si usa per porsi alla - fine del file la posizione viene impostata leggendo la dimensione corrente - dall'inode\index{inode}. + \var{f\_pos} nella struttura \struct{file} della \itindex{file~table} + \textit{file table}, non c'è nessuna operazione sul file su disco. Quando la + si usa per porsi alla fine del file la posizione viene impostata leggendo la + dimensione corrente \index{inode} dall'inode. \end{itemize} \begin{figure}[htb] @@ -807,12 +808,13 @@ stesso file, in particolare occorre tenere presente che: \end{figure} Il secondo caso è quello in cui due file descriptor di due processi diversi -puntino alla stessa voce nella \textit{file table}; questo è ad esempio il -caso dei file aperti che vengono ereditati dal processo figlio all'esecuzione -di una \func{fork} (si ricordi quanto detto in sez.~\ref{sec:proc_fork}). La -situazione è illustrata in fig.~\ref{fig:file_acc_child}; dato che il processo -figlio riceve una copia dello spazio di indirizzi del padre, riceverà anche -una copia di \struct{file\_struct} e relativa tabella dei file aperti. +puntino alla stessa voce nella \itindex{file~table} \textit{file table}; +questo è ad esempio il caso dei file aperti che vengono ereditati dal processo +figlio all'esecuzione di una \func{fork} (si ricordi quanto detto in +sez.~\ref{sec:proc_fork}). La situazione è illustrata in +fig.~\ref{fig:file_acc_child}; dato che il processo figlio riceve una copia +dello spazio di indirizzi del padre, riceverà anche una copia di +\struct{file\_struct} e relativa tabella dei file aperti. In questo modo padre e figlio avranno gli stessi file descriptor che faranno riferimento alla stessa voce nella \textit{file table}, condividendo così la @@ -852,13 +854,13 @@ 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 -\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 -\func{lseek} che non corrisponde più alla fine del file, e la successiva -\func{write} sovrascriverà i dati del secondo processo. +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 \func{lseek} che non corrisponde +più alla fine del file, e la successiva \func{write} sovrascriverà i dati del +secondo processo. Il problema è che usare due system call in successione non è un'operazione atomica; il problema è stato risolto introducendo la modalità @@ -870,12 +872,12 @@ che non essendo interrompibile da un altro processo costituisce un'operazione atomica. Un altro caso tipico in cui è necessaria l'atomicità è quello in cui si vuole -creare un \textsl{file di lock}\index{file!di lock}, bloccandosi se il file +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 \textit{race - condition}\itindex{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 \itindex{race~condition} \textit{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 @@ -946,7 +948,7 @@ Entrambe le funzioni forzano la sincronizzazione col disco di tutti i dati del file specificato, ed attendono fino alla conclusione delle operazioni; \func{fsync} forza anche la sincronizzazione dei metadati del file (che riguardano sia le modifiche alle tabelle di allocazione dei settori, che gli -altri dati contenuti nell'inode\index{inode} che si leggono con \func{fstat}, +altri dati contenuti \index{inode} nell'inode che si leggono con \func{fstat}, come i tempi del file). Si tenga presente che questo non comporta la sincronizzazione della @@ -1059,8 +1061,8 @@ descriptor, che non riguardano la normale lettura e scrittura di dati, ma la gestione sia delle loro proprietà, che di tutta una serie di ulteriori funzionalità che il kernel può mettere a disposizione.\footnote{ad esempio si gestiscono con questa funzione varie modalità di I/O asincrono (vedi - sez.~\ref{sec:file_asyncronous_operation}) e il \textit{file locking} - \index{file!locking} (vedi sez.~\ref{sec:file_locking}).} + sez.~\ref{sec:file_asyncronous_operation}) e il \index{file!locking} + \textit{file locking} (vedi sez.~\ref{sec:file_locking}).} Per queste operazioni di manipolazione e di controllo delle varie proprietà e caratteristiche di un file descriptor, viene usata la funzione \funcd{fcntl}, @@ -1101,7 +1103,7 @@ 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}\itindex{close-on-exec}, identificato dalla costante + \itindex{close-on-exec} \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. @@ -1145,7 +1147,7 @@ per \var{cmd} dei segnali \const{SIGIO} e \const{SIGURG} per gli eventi associati al file descriptor \param{fd}. Nel caso di un \textit{process group} viene restituito un valore negativo il cui valore assoluto corrisponde - all'identificatore del \itindex{process~group}\textit{process group}. In + all'identificatore del \itindex{process~group} \textit{process group}. In caso di errore viene restituito $-1$. \item[\const{F\_SETOWN}] imposta, con il valore dell'argomento \param{arg}, l'identificatore del processo o del \itindex{process~group} \textit{process @@ -1184,11 +1186,11 @@ per \var{cmd} valore nullo in caso di successo o $-1$ in caso di errore. Questa funzionalità avanzata è trattata in dettaglio in sez.~\ref{sec:file_asyncronous_lease}. -\item[\const{F\_GETLEASE}] restituisce il tipo di \textit{file lease} - \index{file!lease} che il processo detiene nei confronti del file descriptor - \var{fd} o $-1$ in caso di errore. Con questo comando il terzo argomento può - essere omesso. Questa funzionalità avanzata è trattata in dettaglio in - sez.~\ref{sec:file_asyncronous_lease}. +\item[\const{F\_GETLEASE}] restituisce il tipo di \index{file!lease} + \textit{file lease} che il processo detiene nei confronti del file + descriptor \var{fd} o $-1$ in caso di errore. Con questo comando il terzo + argomento può essere omesso. Questa funzionalità avanzata è trattata in + dettaglio in sez.~\ref{sec:file_asyncronous_lease}. \item[\const{F\_NOTIFY}] attiva un meccanismo di notifica per cui viene riportata al processo chiamante, tramite il segnale \const{SIGIO} (o altro segnale specificato con \const{F\_SETSIG}) ogni modifica eseguita o @@ -1203,8 +1205,8 @@ poter essere affrontate in tutti i loro aspetti a questo punto; saranno pertanto riprese più avanti quando affronteremo le problematiche ad esse relative. In particolare le tematiche relative all'I/O asincrono e ai vari meccanismi di notifica saranno trattate in maniera esaustiva in -sez.~\ref{sec:file_asyncronous_access} mentre quelle relative al \textit{file - locking}\index{file!locking} saranno esaminate in +sez.~\ref{sec:file_asyncronous_access} mentre quelle relative al +\index{file!locking} \textit{file locking} saranno esaminate in sez.~\ref{sec:file_locking}). L'uso di questa funzione con i socket verrà trattato in sez.~\ref{sec:sock_ctrl_func}. @@ -1293,16 +1295,16 @@ imprevedibili o indesiderati. Data la assoluta specificità della funzione, il cui comportamento varia da dispositivo a dispositivo, non è possibile fare altro che dare una descrizione sommaria delle sue caratteristiche; torneremo ad esaminare in -seguito\footnote{per l'uso con i socket si veda - sez.~\ref{sec:sock_ctrl_func}.} quelle relative ad alcuni casi specifici -(ad esempio la gestione dei terminali è effettuata attraverso \func{ioctl} in +seguito\footnote{per l'uso di \func{ioctl} con i socket si veda + sez.~\ref{sec:sock_ctrl_func}.} quelle relative ad alcuni casi specifici (ad +esempio la gestione dei terminali è 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 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{FIOCLEX}] Imposta il flag di \itindex{close-on-exec} + \textit{close-on-exec}. +\item[\const{FIONCLEX}] Cancella il flag di \itindex{close-on-exec} + \textit{close-on-exec}. \item[\const{FIOASYNC}] Abilita l'I/O asincrono. \item[\const{FIONBIO}] Abilita l'I/O in modalità non bloccante. \end{basedescript} @@ -1310,7 +1312,7 @@ relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}. -% TODO estendere la lista delle ioctl +% TODO estendere la lista delle ioctl sui file %%% Local Variables: diff --git a/gapil.tex b/gapil.tex index 47ddf37..7f35473 100644 --- a/gapil.tex +++ b/gapil.tex @@ -1,6 +1,6 @@ %% gapil.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -87,7 +87,7 @@ \begin{quote} - Copyright \copyright\ 2000-2004 Simone Piccardi. Permission is granted to + Copyright \copyright\ 2000-2007 Simone Piccardi. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being ``Un preambolo'' diff --git a/macro.tex b/macro.tex index 2980b69..d8af80e 100644 --- a/macro.tex +++ b/macro.tex @@ -1,6 +1,6 @@ %% macro.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", diff --git a/netlayer.tex b/netlayer.tex index 61db5ce..b143281 100644 --- a/netlayer.tex +++ b/netlayer.tex @@ -1,6 +1,6 @@ %% netlayer.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -9,8 +9,6 @@ %% License". %% - - \chapter{Il livello di rete} \label{cha:network_layer} @@ -159,7 +157,7 @@ classe A occorre passare a una classe B, che ne prevede 65536,\footnote{in realtà i valori esatti sarebbero 254 e 65536, una rete con a disposizione $N$ bit dell'indirizzo IP, ha disponibili per le singole macchine soltanto $@^N-2$ numeri, dato che uno deve essere utilizzato come indirizzo di rete e - uno per l'indirizzo di \itindex{broadcast}\textit{broadcast}.} con un + uno per l'indirizzo di \itindex{broadcast} \textit{broadcast}.} con un conseguente spreco di numeri. Inoltre, in particolare per le reti di classe C, la presenza di tanti diff --git a/network.tex b/network.tex index 869907f..d7d6e8c 100644 --- a/network.tex +++ b/network.tex @@ -1,6 +1,6 @@ %% network.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{Introduzione alla programmazione di rete} \label{cha:network} @@ -616,7 +617,7 @@ grande pregio della velocit presta bene per le applicazioni in cui la connessione non è necessaria, e costituirebbe solo un peso in termini di prestazioni, mentre una perdita di pacchetti può essere tollerata: ad esempio le applicazioni di streaming e -quelle che usano il \textit{multicast}. \itindex{multicast} +quelle che usano il \itindex{multicast} \textit{multicast}. \subsection{Transport Control Protocol (TCP)} \label{sec:net_tcp} @@ -787,6 +788,7 @@ che pu impostato alla dimensione della MTU dell'interfaccia meno la lunghezza delle intestazioni di IP e TCP, in Linux il default, mantenuto nella costante \const{TCP\_MSS} è 512. + \itindend{Maximum~Transfer~Unit} diff --git a/othersock.tex b/othersock.tex index 439ccef..9ffb653 100644 --- a/othersock.tex +++ b/othersock.tex @@ -1,6 +1,6 @@ %% othersock.tex %% -%% Copyright (C) 2004-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2004-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,12 +8,13 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{Gli altri tipi di socket} \label{cha:other_socket} -Dopo aver trattato in cap.~\ref{cha:TCP_socket} i socket TCP, che costituiscono -l'esempio più comune dell'interfaccia dei socket, esamineremo in questo -capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket +Dopo aver trattato in cap.~\ref{cha:TCP_socket} i socket TCP, che +costituiscono l'esempio più comune dell'interfaccia dei socket, esamineremo in +questo capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket \textit{Unix domain} già incontrati in sez.~\ref{sec:ipc_socketpair}. @@ -54,7 +55,7 @@ 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 \itindex{three~way~handshake}\textit{three way handshake} né quello degli +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 @@ -266,7 +267,7 @@ 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 -\itindex{value~result~argument}\textit{value result argument}). Se non si è +\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}. diff --git a/preambolo.tex b/preambolo.tex index c92a25e..3212d7a 100644 --- a/preambolo.tex +++ b/preambolo.tex @@ -1,6 +1,6 @@ %% preambolo.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", diff --git a/pref.tex b/pref.tex index e8d059a..d091a94 100644 --- a/pref.tex +++ b/pref.tex @@ -1,6 +1,6 @@ %% pref.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", diff --git a/process.tex b/process.tex index 4db223d..3f50045 100644 --- a/process.tex +++ b/process.tex @@ -1,6 +1,6 @@ %% process.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{L'interfaccia base con i processi} \label{cha:process_interface} @@ -261,13 +262,12 @@ esecuzione, e le varie funzioni utilizzabili per la sua gestione. Ci sono vari modi in cui i sistemi operativi organizzano la memoria, ed i dettagli di basso livello dipendono spesso in maniera diretta dall'architettura dell'hardware, ma quello più tipico, usato dai sistemi -unix-like come Linux è la cosiddetta \textsl{memoria - virtuale}\index{memoria~virtuale} che consiste nell'assegnare ad ogni -processo uno spazio virtuale di indirizzamento lineare, in cui gli indirizzi -vanno da zero ad un qualche valore massimo.\footnote{nel caso di Linux fino al - kernel 2.2 detto massimo era, per macchine a 32bit, di 2Gb. Con il kernel - 2.4 ed il supporto per la \textit{high-memory} il limite è stato esteso - anche per macchine a 32 bit.} +unix-like come Linux è la cosiddetta \index{memoria~virtuale} \textsl{memoria + virtuale} che consiste nell'assegnare ad ogni processo uno spazio virtuale +di indirizzamento lineare, in cui gli indirizzi vanno da zero ad un qualche +valore massimo.\footnote{nel caso di Linux fino al kernel 2.2 detto massimo + era, per macchine a 32bit, di 2Gb. Con il kernel 2.4 ed il supporto per la + \textit{high-memory} il limite è stato esteso anche per macchine a 32 bit.} Come accennato in cap.~\ref{cha:intro_unix} questo spazio di indirizzi è virtuale e non corrisponde all'effettiva posizione dei dati nella RAM del @@ -285,7 +285,7 @@ indirizzi virtuale memoria reale o ad un dispositivo di stoccaggio secondario (come lo spazio disco riservato alla swap, o i file che contengono il codice). Per ciascun processo il kernel si cura di mantenere un mappa di queste corrispondenze -nella cosiddetta \itindex{page~table}\textit{page table}.\footnote{questa è +nella cosiddetta \itindex{page~table} \textit{page table}.\footnote{questa è una semplificazione brutale, il meccanismo è molto più complesso; una buona trattazione di come Linux gestisce la memoria virtuale si trova su \cite{LinVM}.} @@ -306,7 +306,7 @@ gestita in maniera trasparente dal kernel.\footnote{in genere con l'ausilio Poiché in genere la memoria fisica è solo una piccola frazione della memoria virtuale, è necessario un meccanismo che permetta di trasferire le pagine che servono dal supporto su cui si trovano in memoria, eliminando quelle che non -servono. Questo meccanismo è detto \textsl{paginazione} \index{paginazione} +servono. Questo meccanismo è detto \index{paginazione} \textsl{paginazione} (o \textit{paging}), ed è uno dei compiti principali del kernel. Quando un processo cerca di accedere ad una pagina che non è nella memoria @@ -325,10 +325,9 @@ a tempi molto pi Normalmente questo è il prezzo da pagare per avere un multitasking reale, ed in genere il sistema è molto efficiente in questo lavoro; quando però ci siano esigenze specifiche di prestazioni è possibile usare delle funzioni che -permettono di bloccare il meccanismo della paginazione\index{paginazione} e -mantenere fisse delle pagine in memoria (vedi -sez.~\ref{sec:proc_mem_lock}). Inoltre per certe applicazioni gli algoritmi di -gestione della memoria +permettono di bloccare il meccanismo della \index{paginazione} paginazione e +mantenere fisse delle pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}). +Inoltre per certe applicazioni gli algoritmi di gestione della memoria \subsection{La struttura della memoria di un processo} @@ -344,8 +343,8 @@ virtuale, il kernel risponde al relativo \itindex{page~fault} \textit{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{memoria~virtuale} di un processo. Essa viene divisa in +È pertanto importante capire come viene strutturata \index{memoria~virtuale} +\textsl{la 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: @@ -387,7 +386,7 @@ seguenti segmenti: Storicamente questa seconda parte del segmento dati viene chiamata BSS (da \textit{Block Started by Symbol}). La sua dimensione è fissa. -\item Lo \itindex{heap}\textit{heap}. Tecnicamente lo si può considerare +\item Lo \itindex{heap} \textit{heap}. Tecnicamente lo si può considerare l'estensione del segmento dati, a cui di solito è posto giusto di seguito. È qui che avviene l'allocazione dinamica della memoria; può essere ridimensionato allocando e disallocando la memoria dinamica con le apposite @@ -446,7 +445,7 @@ loro occupato non viene liberato fino alla sua conclusione. L'\textsl{allocazione automatica} è quella che avviene per gli argomenti di una funzione e per le sue variabili locali (le cosiddette \textsl{variabili automatiche}), che esistono solo per la durata della funzione. Lo spazio -per queste variabili viene allocato nello \itindex{stack}\textit{stack} quando +per queste variabili viene allocato nello \itindex{stack} \textit{stack} quando viene eseguita la funzione e liberato quando si esce dalla medesima. Esiste però un terzo tipo di allocazione, l'\textsl{allocazione dinamica} @@ -458,7 +457,8 @@ Il C non consente di usare variabili allocate dinamicamente, non cioè definire in fase di programmazione una variabile le cui dimensioni possano essere modificate durante l'esecuzione del programma. Per questo le librerie del C forniscono una serie opportuna di funzioni per eseguire -l'allocazione dinamica di memoria (in genere nello \itindex{heap} heap). +l'allocazione dinamica di memoria (in genere nello \itindex{heap} +\textit{heap}). Le variabili il cui contenuto è allocato in questo modo non potranno essere usate direttamente come le altre (quelle nello \itindex{stack} @@ -473,14 +473,16 @@ loro prototipi sono i seguenti: \begin{functions} \headdecl{stdlib.h} \funcdecl{void *calloc(size\_t nmemb, size\_t size)} - Alloca nello heap un'area di memoria per un vettore di \param{nmemb} membri - di \param{size} byte di dimensione. La memoria viene inizializzata a 0. + Alloca nello \textit{heap} un'area di memoria per un vettore di + \param{nmemb} membri di \param{size} byte di dimensione. La memoria viene + inizializzata a 0. La funzione restituisce il puntatore alla zona di memoria allocata in caso di successo e \val{NULL} in caso di fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}. \funcdecl{void *malloc(size\_t size)} - Alloca \param{size} byte nello heap. La memoria non viene inizializzata. + Alloca \param{size} byte nello \textit{heap}. La memoria non viene + inizializzata. La funzione restituisce il puntatore alla zona di memoria allocata in caso di successo e \val{NULL} in caso di fallimento, nel qual caso @@ -568,8 +570,8 @@ 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 funzioni di allocazione è quando non viene opportunamente liberata la memoria -non più utilizzata, quello che in inglese viene chiamato \textit{memory - leak}\itindex{memory~leak}, cioè una \textsl{perdita di memoria}. +non più utilizzata, quello che in inglese viene chiamato \itindex{memory~leak} +\textit{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 @@ -582,13 +584,13 @@ 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}\itindex{memory~leak}. +\itindex{memory~leak} \textit{memory leak}. In C e C++ il problema è particolarmente sentito. In C++, per mezzo della -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. +programmazione ad oggetti, il problema dei \itindex{memory~leak} +\textit{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. % TODO decidere cosa fare di questo che segue % In altri linguaggi come il java e recentemente il C\# il problema non si pone @@ -596,7 +598,7 @@ genere va a scapito delle prestazioni dell'applicazione in esecuzione. % 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, +% \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 @@ -626,11 +628,11 @@ molto complesse riguardo l'allocazione della memoria. Una possibile alternativa all'uso di \func{malloc}, che non soffre dei -problemi di \textit{memory leak}\itindex{memory~leak} descritti in precedenza, -è la funzione \funcd{alloca}, che invece di allocare la memoria nello -\itindex{heap}\textit{heap} usa il segmento di \itindex{stack} \textit{stack} -della funzione corrente. La sintassi è identica a quella di \func{malloc}, il -suo prototipo è: +problemi di \itindex{memory~leak} \textit{memory leak} descritti in +precedenza, è la funzione \funcd{alloca}, che invece di allocare la memoria +nello \itindex{heap} \textit{heap} usa il segmento di \itindex{stack} +\textit{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. @@ -646,7 +648,7 @@ la memoria allocata (e 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 \textit{memory leak}\itindex{memory~leak}, +evitare alla radice i problemi di \itindex{memory~leak} \textit{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 @@ -729,24 +731,25 @@ standard descritte in precedenza, che sono costruite su di esse. \label{sec:proc_mem_lock} \index{memoria~virtuale|(} + Come spiegato in sez.~\ref{sec:proc_mem_gen} il kernel gestisce la memoria virtuale in maniera trasparente ai processi, decidendo quando rimuovere pagine dalla memoria per metterle nello swap, sulla base dell'utilizzo corrente da parte dei vari processi. Nell'uso comune un processo non deve preoccuparsi di tutto ciò, in quanto il -meccanismo della paginazione\index{paginazione} riporta in RAM, ed in maniera +meccanismo della \index{paginazione} paginazione riporta in RAM, ed in maniera trasparente, tutte le pagine che gli occorrono; esistono però esigenze particolari in cui non si vuole che questo meccanismo si attivi. In generale i motivi per cui si possono avere di queste necessità sono due: \begin{itemize} -\item \textsl{La velocità}. Il processo della paginazione\index{paginazione} è - trasparente solo se il programma in esecuzione non è sensibile al tempo che - occorre a riportare la pagina in memoria; per questo motivo processi critici - che hanno esigenze di tempo reale o tolleranze critiche nelle risposte (ad - esempio processi che trattano campionamenti sonori) possono non essere in - grado di sopportare le variazioni della velocità di accesso dovuta alla - paginazione. +\item \textsl{La velocità}. Il processo della \index{paginazione} paginazione + è trasparente solo se il programma in esecuzione non è sensibile al tempo + che occorre a riportare la pagina in memoria; per questo motivo processi + critici che hanno esigenze di tempo reale o tolleranze critiche nelle + risposte (ad esempio processi che trattano campionamenti sonori) possono non + essere in grado di sopportare le variazioni della velocità di accesso dovuta + alla paginazione. In certi casi poi un programmatore può conoscere meglio dell'algoritmo di allocazione delle pagine le esigenze specifiche del suo programma e decidere @@ -757,7 +760,7 @@ motivi per cui si possono avere di queste necessit \item \textsl{La sicurezza}. Se si hanno password o chiavi segrete in chiaro in memoria queste possono essere portate su disco dal meccanismo della - paginazione\index{paginazione}. Questo rende più lungo il periodo di tempo + \index{paginazione} paginazione. Questo rende più lungo il periodo di tempo in cui detti segreti sono presenti in chiaro e più complessa la loro cancellazione (un processo può cancellare la memoria su cui scrive le sue variabili, ma non può toccare lo spazio disco su cui una pagina di memoria @@ -767,22 +770,22 @@ motivi per cui si possono avere di queste necessit \itindbeg{memory~locking} -Il meccanismo che previene la paginazione\index{paginazione} di parte della +Il meccanismo che previene la \index{paginazione} 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 memoria virtuale del processo, e non al segmento reale di RAM su cui essa viene mantenuta. La regola è che se un segmento di RAM fa da supporto ad almeno una pagina bloccata allora esso viene escluso dal meccanismo della -paginazione\index{paginazione}. I blocchi non si accumulano, se si blocca due +\index{paginazione} paginazione. I blocchi non si accumulano, se si blocca due volte la stessa pagina non è necessario sbloccarla due volte, una pagina o è -bloccata oppure no. +bloccata oppure no. 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 - \itindex{copy~on~write}\textit{copy on write} (vedi + \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.} e @@ -792,9 +795,9 @@ con \func{exec} (vedi sez.~\ref{sec:proc_exec}). 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 tutti gli altri processi, per cui fino al kernel 2.6.9 solo un processo con i -privilegi opportuni (la \itindex{capabilities}\textit{capability} +privilegi opportuni (la \itindex{capabilities} \textit{capability} \const{CAP\_IPC\_LOCK}, vedi sez.~\ref{sec:proc_capabilities}) aveva la -capacità di bloccare una pagina. +capacità di bloccare una pagina. Il sistema pone dei limiti all'ammontare di memoria di un processo che può essere bloccata e al totale di memoria fisica che si può dedicare a questo, lo @@ -817,7 +820,7 @@ poi ogni processo pu però diversi processi bloccano la stessa pagina questa resterà bloccata fintanto che ci sarà almeno un processo che la blocca. -Le funzioni per bloccare e sbloccare la paginazione \index{paginazione} di +Le funzioni per bloccare e sbloccare la \index{paginazione} paginazione di singole sezioni di memoria sono \funcd{mlock} e \funcd{munlock}; i loro prototipi sono: \begin{functions} @@ -845,7 +848,7 @@ prototipi sono: \end{functions} Le due funzioni permettono rispettivamente di bloccare e sbloccare la -paginazione\index{paginazione} per l'intervallo di memoria specificato dagli +\index{paginazione} paginazione per l'intervallo di memoria specificato dagli argomenti, che ne indicano nell'ordine l'indirizzo iniziale e la lunghezza. Tutte le pagine che contengono una parte dell'intervallo bloccato sono mantenute in RAM per tutta la durata del blocco.\footnote{con altri kernel si @@ -853,7 +856,7 @@ mantenute in RAM per tutta la durata del blocco.\footnote{con altri kernel si della dimensione delle pagine di memoria.} Altre due funzioni, \funcd{mlockall} e \funcd{munlockall}, consentono di -bloccare genericamente la paginazione\index{paginazione} per l'intero spazio +bloccare genericamente la \index{paginazione} paginazione per l'intero spazio di indirizzi di un processo. I prototipi di queste funzioni sono: \begin{functions} \headdecl{sys/mman.h} @@ -866,7 +869,7 @@ di indirizzi di un processo. I prototipi di queste funzioni sono: \bodydesc{Codici di ritorno ed errori sono gli stessi di \func{mlock} e \func{munlock}, con un kernel successivo al 2.6.9 l'uso di - \func{munlockall} senza la \itindex{capabilities}\textit{capability} + \func{munlockall} senza la \itindex{capabilities} \textit{capability} \const{CAP\_IPC\_LOCK} genera un errore di \errcode{EPERM}.} \end{functions} @@ -882,28 +885,28 @@ costanti: Con \func{mlockall} si possono bloccare tutte le pagine mappate nello spazio di indirizzi del processo, sia che comprendano il \index{segmento!dati} -\index{segmento!testo} segmento di testo, di dati, lo \itindex{stack} stack, -lo \itindex{heap} heap e pure le funzioni di libreria chiamate, i file mappati -in memoria, i dati del kernel mappati in user space, la memoria condivisa. -L'uso dei flag permette di selezionare con maggior finezza le pagine da -bloccare, ad esempio limitandosi a tutte le pagine allocate a partire da un -certo momento. +\index{segmento!testo} segmento di testo, di dati, lo \itindex{stack} +\textit{stack}, lo \itindex{heap} \textit{heap} e pure le funzioni di libreria +chiamate, i file mappati in memoria, i dati del kernel mappati in user space, +la memoria condivisa. L'uso dei flag permette di selezionare con maggior +finezza le pagine da bloccare, ad 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 \index{sezione~critica} sezione critica deve provvedere a riservare memoria sufficiente prima dell'ingresso, per scongiurare l'occorrenza di un eventuale -\textit{page fault}\itindex{page~fault} causato dal meccanismo di \textit{copy - on write}\itindex{copy~on~write}. Infatti se nella \index{sezione~critica} -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. +\itindex{page~fault} \textit{page fault} causato dal meccanismo di +\itindex{copy~on~write} \textit{copy on write}. Infatti se nella +\index{sezione~critica} 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 \itindex{stack} stack, dopo di che, per -essere sicuri che esse siano state effettivamente portate in memoria, ci si -scrive sopra. +che esse vengano mappate in RAM dallo \itindex{stack} \textit{stack}, dopo di +che, per essere sicuri che esse siano state effettivamente portate in memoria, +ci si scrive sopra. \itindend{memory~locking} @@ -1274,8 +1277,8 @@ corrente sar fatta in precedenza da un'altra \func{putenv}. Questo perché il vettore delle variabili di ambiente iniziale, creato dalla chiamata ad \func{exec} (vedi sez.~\ref{sec:proc_exec}) è piazzato al di sopra dello \itindex{stack} stack, -(vedi fig.~\ref{fig:proc_mem_layout}) e non nello \itindex{heap} heap e non -può essere deallocato. Inoltre la memoria associata alle variabili di +(vedi fig.~\ref{fig:proc_mem_layout}) e non nello \itindex{heap} \textit{heap} +e non può essere deallocato. Inoltre la memoria associata alle variabili di ambiente eliminate non viene liberata. L'ultima funzione è \funcd{clearenv}, che viene usata per cancellare @@ -1341,7 +1344,7 @@ 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 \itindex{value~result~argument}\textit{value +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 @@ -1354,10 +1357,10 @@ strutture degli indirizzi utilizzate, viene usato questo meccanismo. Come vedremo nei capitoli successivi, non sempre è possibile specificare un numero fisso di argomenti per una funzione. Lo standard ISO C prevede nella -sua sintassi la possibilità di definire delle \textit{variadic - function}\index{variadic} che abbiano un numero variabile di argomenti, +sua sintassi la possibilità di definire delle \index{variadic} +\textit{variadic function} che abbiano un numero variabile di argomenti, attraverso l'uso nella dichiarazione della funzione dello speciale costrutto -``\texttt{\textellipsis}'', che viene chiamato \textit{ellipsis}. +``\texttt{\textellipsis}'', che viene chiamato \textit{ellipsis}. Lo standard però non provvede a livello di linguaggio alcun meccanismo con cui dette funzioni possono accedere ai loro argomenti. L'accesso viene pertanto @@ -1374,7 +1377,7 @@ tre punti: a seguire quelli addizionali. \end{itemize} -Lo standard ISO C prevede che una \textit{variadic function}\index{variadic} +Lo standard ISO C prevede che una \index{variadic} \textit{variadic function} abbia sempre almeno un argomento fisso; prima di effettuare la dichiarazione deve essere incluso l'apposito header file \file{stdarg.h}; un esempio di dichiarazione è il prototipo della funzione \func{execl} che vedremo in @@ -1399,9 +1402,9 @@ quando la si va a definire. Gli argomenti fissi infatti hanno un loro nome, ma quelli variabili vengono indicati in maniera generica dalla \textit{ellipsis}. L'unica modalità in cui essi possono essere recuperati è pertanto quella -sequenziale; essi verranno estratti dallo \itindex{stack} stack secondo -l'ordine in cui sono stati scritti. Per fare questo in \file{stdarg.h} sono -definite delle apposite macro; la procedura da seguire è la seguente: +sequenziale; essi verranno estratti dallo \itindex{stack} \textit{stack} +secondo l'ordine in cui sono stati scritti. Per fare questo in \file{stdarg.h} +sono definite delle apposite macro; la procedura da seguire è la seguente: \begin{enumerate} \item Inizializzare un puntatore alla lista degli argomenti di tipo \macro{va\_list} attraverso la macro \macro{va\_start}. @@ -1457,11 +1460,12 @@ argomenti e poter memorizzare una posizione durante la stessa. La cosa pi naturale in questo caso sembrerebbe quella di copiarsi il puntatore alla lista degli argomenti con una semplice assegnazione. Dato che una delle realizzazioni più comuni di \macro{va\_list} è quella di un puntatore nello -\itindex{stack} stack all'indirizzo dove sono stati salvati gli argomenti, è -assolutamente normale pensare di poter effettuare questa operazione. +\itindex{stack} \textit{stack} all'indirizzo dove sono stati salvati gli +argomenti, è assolutamente normale pensare di poter effettuare questa +operazione. In generale però possono esistere anche realizzazioni diverse, per questo -motivo \macro{va\_list} è definito come \textsl{tipo opaco}\index{tipo!opaco} +motivo \macro{va\_list} è definito come \index{tipo!opaco} \textsl{tipo opaco} e non può essere assegnato direttamente ad un'altra variabile dello stesso tipo. Per risolvere questo problema lo standard ISO C99\footnote{alcuni sistemi che non hanno questa macro provvedono al suo posto @@ -1511,9 +1515,9 @@ come ultimo argomento (come fa ad esempio \func{execl} che usa un puntatore Uno dei possibili problemi che si possono avere con le subroutine è quello di restituire alla funzione chiamante dei dati che sono contenuti in una variabile automatica. Ovviamente quando la subroutine ritorna la sezione -dello \itindex{stack} stack che conteneva la variabile automatica potrà essere -riutilizzata da una nuova funzione, con le immaginabili conseguenze di -sovrapposizione e sovrascrittura dei dati. +dello \itindex{stack} \textit{stack} che conteneva la variabile automatica +potrà essere riutilizzata da una nuova funzione, con le immaginabili +conseguenze di sovrapposizione e sovrascrittura dei dati. Per questo una delle regole fondamentali della programmazione in C è che all'uscita di una funzione non deve restare nessun riferimento alle variabili @@ -1559,11 +1563,11 @@ scartando l'input come errato.\footnote{a meno che, come precisa \cite{glibc}, essere eseguite con un salto non-locale.} Tutto ciò può essere realizzato proprio con un salto non-locale; questo di -norma viene realizzato salvando il contesto dello \itindex{stack} stack nel -punto in cui si vuole tornare in caso di errore, e ripristinandolo, in modo da -tornare nella funzione da cui si era partiti, quando serve. La funzione che -permette di salvare il contesto dello \itindex{stack} stack è \funcd{setjmp}, -il cui prototipo è: +norma viene realizzato salvando il contesto dello \itindex{stack} +\textit{stack} nel punto in cui si vuole tornare in caso di errore, e +ripristinandolo, in modo da tornare nella funzione da cui si era partiti, +quando serve. La funzione che permette di salvare il contesto dello +\itindex{stack} \textit{stack} è \funcd{setjmp}, il cui prototipo è: \begin{functions} \headdecl{setjmp.h} \funcdecl{int setjmp(jmp\_buf env)} @@ -1575,10 +1579,10 @@ il cui prototipo che usa il contesto salvato in precedenza.} \end{functions} -Quando si esegue la funzione il contesto corrente dello \itindex{stack} stack -viene salvato nell'argomento \param{env}, una variabile di tipo +Quando si esegue la funzione il contesto corrente dello \itindex{stack} +\textit{stack} viene salvato nell'argomento \param{env}, una variabile di tipo \type{jmp\_buf}\footnote{questo è un classico esempio di variabile di - \textsl{tipo opaco}\index{tipo!opaco}. Si definiscono così strutture ed + \index{tipo!opaco} \textsl{tipo opaco}. Si definiscono così strutture ed altri oggetti usati da una libreria, la cui struttura interna non deve essere vista dal programma chiamante (da cui il nome) che li devono utilizzare solo attraverso dalle opportune funzioni di gestione.} che deve @@ -1589,8 +1593,8 @@ essere viste in tutte le funzioni del programma. Quando viene eseguita direttamente la funzione ritorna sempre zero, un valore diverso da zero viene restituito solo quando il ritorno è dovuto ad una chiamata di \func{longjmp} in un'altra parte del programma che ripristina lo -\itindex{stack} stack effettuando il salto non-locale. Si tenga conto che il -contesto salvato in \param{env} viene invalidato se la funzione che ha +\itindex{stack} \textit{stack} effettuando il salto non-locale. Si tenga conto +che il contesto salvato in \param{env} viene invalidato se la funzione che ha chiamato \func{setjmp} ritorna, nel qual caso un successivo uso di \func{longjmp} può comportare conseguenze imprevedibili (e di norma fatali) per il processo. @@ -1607,10 +1611,11 @@ un punto precedentemente stabilito con \func{setjmp} si usa la funzione \bodydesc{La funzione non ritorna.} \end{functions} -La funzione ripristina il contesto dello \itindex{stack} stack salvato da una -chiamata a \func{setjmp} nell'argomento \param{env}. Dopo l'esecuzione della -funzione il programma prosegue nel codice successivo al ritorno della -\func{setjmp} con cui si era salvato \param{env}, che restituirà il valore +La funzione ripristina il contesto dello \itindex{stack} \textit{stack} +salvato da una chiamata a \func{setjmp} nell'argomento \param{env}. Dopo +l'esecuzione della funzione il programma prosegue nel codice successivo al +ritorno della \func{setjmp} con cui si era salvato \param{env}, che restituirà +il valore \param{val} invece di zero. Il valore di \param{val} specificato nella chiamata deve essere diverso da zero, se si è specificato 0 sarà comunque restituito 1 al suo posto. @@ -1622,11 +1627,11 @@ il ritorno pu annidate. L'implementazione di queste funzioni comporta alcune restrizioni dato che esse -interagiscono direttamente con la gestione dello \itindex{stack} stack ed il -funzionamento del compilatore stesso. In particolare \func{setjmp} è -implementata con una macro, pertanto non si può cercare di ottenerne -l'indirizzo, ed inoltre delle chiamate a questa funzione sono sicure solo in -uno dei seguenti casi: +interagiscono direttamente con la gestione dello \itindex{stack} +\textit{stack} ed il funzionamento del compilatore stesso. In particolare +\func{setjmp} è implementata con una macro, pertanto non si può cercare di +ottenerne l'indirizzo, ed inoltre delle chiamate a questa funzione sono sicure +solo in uno dei seguenti casi: \begin{itemize} \item come espressione di controllo in un comando condizionale, di selezione o di iterazione (come \code{if}, \code{switch} o \code{while}); @@ -1661,24 +1666,21 @@ Quello che succede infatti memoria manterranno il valore avuto al momento della chiamata di \func{longjmp}, mentre quelli tenuti nei registri del processore (che nella chiamata ad un'altra funzione vengono salvati nel contesto nello -\itindex{stack} stack) torneranno al valore avuto al momento della chiamata di -\func{setjmp}; per questo quando si vuole avere un comportamento coerente si -può bloccare l'ottimizzazione che porta le variabili nei registri -dichiarandole tutte come \direct{volatile}\footnote{la direttiva +\itindex{stack} \textit{stack}) torneranno al valore avuto al momento della +chiamata di \func{setjmp}; per questo quando si vuole avere un comportamento +coerente si può bloccare l'ottimizzazione che porta le variabili nei registri +dichiarandole tutte come \direct{volatile}.\footnote{la direttiva \direct{volatile} informa il compilatore che la variabile che è dichiarata può essere modificata, durante l'esecuzione del nostro, da altri programmi. Per questo motivo occorre dire al compilatore che non deve essere mai utilizzata l'ottimizzazione per cui quanto opportuno essa viene mantenuta in un registro, poiché in questo modo si perderebbero le eventuali modifiche fatte dagli altri programmi (che avvengono solo in una copia posta in - memoria).}. + memoria).} \index{salto~non-locale|)} -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "gapil" -%%% End: + % LocalWords: like exec kernel thread main ld linux static linker char envp Gb % LocalWords: sez POSIX exit system call cap abort shell diff errno stdlib int @@ -1700,3 +1702,8 @@ dichiarandole tutte come \direct{volatile}\footnote{la direttiva % LocalWords: socket variadic ellipsis header stdarg execl self promoting last % LocalWords: float double short register type dest src extern setjmp jmp buf % LocalWords: env return if while sottoprocesso Di + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: diff --git a/prochand.tex b/prochand.tex index e78ebb8..225e9c4 100644 --- a/prochand.tex +++ b/prochand.tex @@ -1,6 +1,6 @@ %% prochand.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{La gestione dei processi} \label{cha:process_handling} @@ -143,11 +144,11 @@ fig.~\ref{fig:proc_task_struct}. \label{fig:proc_task_struct} \end{figure} -Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \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.} -% TODO completare questa parte. +Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \itindex{scheduler} +\textit{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.} +% TODO completare questa parte su quando viene chiamato lo scheduler. (ma può essere anche attivato esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato periodicamente, generando un interrupt periodico secondo la frequenza specificata dalla costante \const{HZ}, definita @@ -159,7 +160,7 @@ in \file{asm/param.h}, ed il cui valore % TODO verificare gli ultimi cambiamenti del 2.6 % Si ha cioè un interrupt dal timer ogni centesimo di secondo. -Ogni volta che viene eseguito, lo \textit{scheduler} \itindex{scheduler} +Ogni volta che viene eseguito, lo \itindex{scheduler} \textit{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. @@ -270,8 +271,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 \itindex{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 @@ -319,22 +320,23 @@ prototipo della funzione Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che il processo figlio continuano ad essere eseguiti normalmente a partire dall'istruzione successiva alla \func{fork}; il processo figlio è però una -copia del padre, e riceve una copia dei segmenti di testo, \itindex{stack} -stack e dati (vedi sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo -stesso codice del padre. Si tenga presente però che la memoria è copiata, non -condivisa, pertanto padre e figlio vedono variabili diverse. - -Per quanto riguarda la gestione della memoria, in generale -il\index{segmento!testo} 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} -\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ù efficiente il meccanismo della -creazione di un nuovo processo, non essendo più necessaria la copia di tutto -lo spazio degli indirizzi virtuali del padre, ma solo delle pagine di memoria -che sono state modificate, e solo al momento della modifica stessa. +copia del padre, e riceve una copia dei \index{segmento!testo} segmenti di +testo, \itindex{stack} stack e \index{segmento!dati} dati (vedi +sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del +padre. Si tenga presente però che la memoria è copiata, non condivisa, +pertanto padre e figlio vedono variabili diverse. + +Per quanto riguarda la gestione della memoria, in generale il +\index{segmento!testo} 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 \itindex{copy~on~write} \textit{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ù efficiente il meccanismo della creazione di +un nuovo processo, non essendo più necessaria la copia di tutto lo spazio +degli indirizzi virtuali del padre, ma solo delle pagine di memoria che sono +state modificate, e solo al momento della modifica stessa. La differenza che si ha nei due processi è che nel processo padre il valore di ritorno della funzione \func{fork} è il \acr{pid} del processo figlio, mentre @@ -443,8 +445,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\itindex{scheduler} di Ingo Molnar che esegue sempre per primo il - figlio; per mantenere la portabilità è opportuno non fare comunque + \itindex{scheduler} \textit{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 @@ -465,8 +467,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} -\itindex{race~condition} (vedi sez.~\ref{sec:proc_race_cond}). +rischio di incorrere nelle cosiddette \itindex{race~condition} \textit{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 @@ -585,20 +587,20 @@ Oltre ai file aperti i processi figli ereditano dal padre una serie di altre proprietà; la lista dettagliata delle proprietà che padre e figlio hanno in 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}\itindex{close-on-exec} impostati (vedi - sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}); +\item i file aperti e gli eventuali flag di \itindex{close-on-exec} + \textit{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 \textsl{group-ID effettivo} ed i \textit{group-ID supplementari} (vedi sez.~\ref{sec:proc_access_id}); -\item gli identificatori per il controllo di sessione: il \textit{process - group-ID} e il \textit{session id} ed il terminale di controllo (vedi - sez.~\ref{sec:sess_proc_group}); +\item gli identificatori per il controllo di sessione: il + \itindex{process~group} \textit{process group-ID} e il \textit{session id} + ed il terminale di controllo (vedi sez.~\ref{sec:sess_proc_group}); \item la directory di lavoro e la directory radice (vedi sez.~\ref{sec:file_work_dir} e sez.~\ref{sec:file_chroot}); \item la maschera dei permessi di creazione (vedi - sez.~\ref{sec:file_perm_managemen}); + sez.~\ref{sec:file_perm_managemen}); \item la maschera dei segnali bloccati (vedi sez.~\ref{sec:sig_sigmask}) e le azioni installate (vedi sez.~\ref{sec:sig_gen_beha}); \item i segmenti di memoria condivisa agganciati al processo (vedi @@ -640,7 +642,7 @@ 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} \itindex{copy~on~write} la +Dato che Linux supporta il \itindex{copy~on~write} \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. @@ -762,7 +764,7 @@ memorizzando alcuni dati essenziali, come il \acr{pid}, i tempi di CPU usati dal processo (vedi sez.~\ref{sec:sys_unix_time}) e lo stato di terminazione, mentre la memoria in uso ed i file aperti vengono rilasciati immediatamente. I processi che sono terminati, ma il cui stato di terminazione non è stato -ancora ricevuto dal padre sono chiamati \textit{zombie}\index{zombie}, essi +ancora ricevuto dal padre sono chiamati \index{zombie} \textit{zombie}, essi restano presenti nella tabella dei processi ed in genere possono essere identificati dall'output di \cmd{ps} per la presenza di una \texttt{Z} nella colonna che ne indica lo stato (vedi tab.~\ref{tab:proc_proc_states}). Quando @@ -789,34 +791,35 @@ terminale (prima dello scadere dei 10 secondi) otterremo: \end{verbatim} %$ \normalsize e come si vede, dato che non si è fatto nulla per riceverne lo stato di terminazione, i tre processi figli sono ancora presenti pur essendosi -conclusi, con lo stato di zombie \index{zombie} e l'indicazione che sono stati -terminati. - -La possibilità di avere degli zombie \index{zombie} deve essere tenuta sempre -presente quando si scrive un programma che deve essere mantenuto in esecuzione -a lungo e creare molti figli. In questo caso si deve sempre avere cura di far -leggere l'eventuale stato di uscita di tutti i figli (in genere questo si fa -attraverso un apposito \textit{signal handler}, che chiama la funzione -\func{wait}, vedi sez.~\ref{sec:sig_sigchld} e sez.~\ref{sec:proc_wait}). -Questa operazione è necessaria perché anche se gli \textit{zombie} -\index{zombie} non consumano risorse di memoria o processore, occupano -comunque una voce nella tabella dei processi, che a lungo andare potrebbe -esaurirsi. +conclusi, con lo stato di \index{zombie} \textit{zombie} e l'indicazione che +sono stati terminati. + +La possibilità di avere degli \index{zombie} \textit{zombie} deve essere +tenuta sempre presente quando si scrive un programma che deve essere mantenuto +in esecuzione a lungo e creare molti figli. In questo caso si deve sempre +avere cura di far leggere l'eventuale stato di uscita di tutti i figli (in +genere questo si fa attraverso un apposito \textit{signal handler}, che chiama +la funzione \func{wait}, vedi sez.~\ref{sec:sig_sigchld} e +sez.~\ref{sec:proc_wait}). Questa operazione è necessaria perché anche se gli +\index{zombie} \textit{zombie} non consumano risorse di memoria o processore, +occupano comunque una voce nella tabella dei processi, che a lungo andare +potrebbe esaurirsi. Si noti che quando un processo adottato da \cmd{init} termina, esso non -diviene uno \textit{zombie}\index{zombie}; questo perché una delle funzioni di -\cmd{init} è appunto quella di chiamare la funzione \func{wait} per i processi -cui fa da padre, completandone la terminazione. Questo è quanto avviene anche -quando, come nel caso del precedente esempio con \cmd{forktest}, il padre -termina con dei figli in stato di zombie\index{zombie}: alla sua terminazione -infatti tutti i suoi figli (compresi gli zombie\index{zombie}) verranno -adottati da \cmd{init}, il quale provvederà a completarne la terminazione. - -Si tenga presente infine che siccome gli zombie\index{zombie} sono processi -già usciti, non c'è modo di eliminarli con il comando \cmd{kill}; l'unica -possibilità di cancellarli dalla tabella dei processi è quella di terminare il -processo che li ha generati, in modo che \cmd{init} possa adottarli e -provvedere a concluderne la terminazione. +diviene uno \index{zombie} \textit{zombie}; questo perché una delle funzioni +di \cmd{init} è appunto quella di chiamare la funzione \func{wait} per i +processi cui fa da padre, completandone la terminazione. Questo è quanto +avviene anche quando, come nel caso del precedente esempio con \cmd{forktest}, +il padre termina con dei figli in stato di \index{zombie} \textit{zombie}: +alla sua terminazione infatti tutti i suoi figli (compresi gli \index{zombie} +\textit{zombie}) verranno adottati da \cmd{init}, il quale provvederà a +completarne la terminazione. + +Si tenga presente infine che siccome gli \index{zombie} \textit{zombie} sono +processi già usciti, non c'è modo di eliminarli con il comando \cmd{kill}; +l'unica possibilità di cancellarli dalla tabella dei processi è quella di +terminare il processo che li ha generati, in modo che \cmd{init} possa +adottarli e provvedere a concluderne la terminazione. \subsection{Le funzioni \func{wait} e \func{waitpid}} @@ -827,7 +830,7 @@ consiste nella creazione di programmi di tipo server, in cui un processo principale attende le richieste che vengono poi soddisfatte da una serie di processi figli. Si è già sottolineato al paragrafo precedente come in questo caso diventi necessario gestire esplicitamente la conclusione dei figli onde -evitare di riempire di \textit{zombie}\index{zombie} la tabella dei processi; +evitare di riempire di \index{zombie} \textit{zombie} la tabella dei processi; le funzioni deputate a questo compito sono sostanzialmente due, \funcd{wait} e \func{waitpid}. La prima, il cui prototipo è: \begin{functions} @@ -946,11 +949,11 @@ kernel avverte il processo padre che uno dei suoi figli In genere in un programma non si vuole essere forzati ad attendere la conclusione di un processo per proseguire, specie se tutto questo serve solo -per leggerne lo stato di chiusura (ed evitare la presenza di -\textit{zombie}\index{zombie}), per questo la modalità più usata per chiamare -queste funzioni è quella di utilizzarle all'interno di un \textit{signal - handler} (vedremo un esempio di come gestire \const{SIGCHLD} con i segnali -in sez.~\ref{sec:sig_example}). In questo caso infatti, dato che il segnale è +per leggerne lo stato di chiusura (ed evitare la presenza di \index{zombie} +\textit{zombie}), per questo la modalità più usata per chiamare queste +funzioni è quella di utilizzarle all'interno di un \textit{signal handler} +(vedremo un esempio di come gestire \const{SIGCHLD} con i segnali in +sez.~\ref{sec:sig_example}). In questo caso infatti, dato che il segnale è generato dalla terminazione di un figlio, avremo la certezza che la chiamata a \func{wait} non si bloccherà. @@ -979,7 +982,7 @@ generato dalla terminazione di un figlio, avremo la certezza che la chiamata a valutata solo se \val{WIFSIGNALED} ha restituito un valore non nullo.\\ \macro{WCOREDUMP(s)} & Vera se il processo terminato ha generato un - file di \itindex{core~dump}\textit{core + file di \itindex{core~dump} \textit{core dump}. Può essere valutata solo se \val{WIFSIGNALED} ha restituito un valore non nullo.\footnotemark \\ @@ -1007,7 +1010,7 @@ entrambe le funzioni dipende dall'implementazione, e tradizionalmente alcuni bit (in genere 8) sono riservati per memorizzare lo stato di uscita, e altri per indicare il segnale che ha causato la terminazione (in caso di conclusione anomala), uno per indicare se è stato generato un -\itindex{core~dump}\textit{core dump}, ecc.\footnote{le definizioni esatte +\itindex{core~dump} \textit{core dump}, ecc.\footnote{le definizioni esatte si possono trovare in \file{} ma questo file non deve mai essere usato direttamente, esso viene incluso attraverso \file{}.} @@ -1064,7 +1067,8 @@ fatto attraverso una delle funzioni della famiglia \func{exec}. Quando un processo chiama una di queste funzioni esso viene completamente sostituito dal nuovo programma; il \acr{pid} del processo non cambia, dato che non viene creato un nuovo processo, la funzione semplicemente rimpiazza lo -\itindex{stack} stack, lo \itindex{heap} heap, i dati ed il testo del processo +\itindex{stack} \textit{stack}, lo \itindex{heap} \textit{heap}, i +\index{segmento!dati} dati ed il \index{segmento!testo} testo del processo corrente con un nuovo programma letto da disco. Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata @@ -1193,7 +1197,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 -\itindex{pathname}\textit{pathname} del programma. +\itindex{pathname} \textit{pathname} del programma. \begin{figure}[htb] \centering @@ -1242,7 +1246,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}\itindex{close-on-exec} (vedi anche +\itindex{close-on-exec} \textit{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 @@ -1252,14 +1256,14 @@ 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}\itindex{close-on-exec} sulle -directory che apre, in maniera trasparente all'utente. +l'impostazione del flag di \itindex{close-on-exec} \textit{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 l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} (il significato di questi identificatori è trattato in sez.~\ref{sec:proc_access_id}), tranne -quando il file che si va ad eseguire abbia o il \itindex{suid~bit}\acr{suid} +quando il file che si va ad eseguire abbia o il \itindex{suid~bit} \acr{suid} bit o lo \itindex{sgid~bit} \acr{sgid} bit impostato, in questo caso l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} vengono impostati rispettivamente all'utente o al gruppo cui il file appartiene (per i @@ -1315,16 +1319,16 @@ Come accennato in sez.~\ref{sec:intro_multiuser} il modello base\footnote{in realtà già esistono estensioni di questo modello base, che lo rendono più flessibile e controllabile, come le \itindex{capabilities} \textit{capabilities} illustrate in sez.~\ref{sec:proc_capabilities}, le ACL - per i file o il \textit{Mandatory Access Control} - \itindex{Mandatory~Access~Control~(MAC)} di SELinux; inoltre basandosi sul - lavoro effettuato con SELinux, a partire dal kernel 2.5.x, è iniziato lo - sviluppo di una infrastruttura di sicurezza, il \textit{Linux Security - Modules}, o LSM, in grado di fornire diversi agganci a livello del kernel - per modularizzare tutti i possibili controlli di accesso.} di sicurezza di -un sistema unix-like è fondato sui concetti di utente e gruppo, e sulla -separazione fra l'amministratore (\textsl{root}, detto spesso anche -\textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli -utenti, per i quali invece vengono effettuati i vari controlli di accesso. + per i file o il \itindex{Mandatory~Access~Control~(MAC)} \textit{Mandatory + Access Control} di SELinux; inoltre basandosi sul lavoro effettuato con + SELinux, a partire dal kernel 2.5.x, è iniziato lo sviluppo di una + infrastruttura di sicurezza, il \textit{Linux Security Modules}, o LSM, in + grado di fornire diversi agganci a livello del kernel per modularizzare + tutti i possibili controlli di accesso.} di sicurezza di un sistema +unix-like è fondato sui concetti di utente e gruppo, e sulla separazione fra +l'amministratore (\textsl{root}, detto spesso anche \textit{superuser}) che +non è sottoposto a restrizioni, ed il resto degli utenti, per i quali invece +vengono effettuati i vari controlli di accesso. Abbiamo già accennato come il sistema associ ad ogni utente e gruppo due identificatori univoci, lo user-ID ed il group-ID; questi servono al kernel per @@ -1460,7 +1464,7 @@ dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo} del processo padre, e vengono impostati dalla funzione \func{exec} all'avvio del processo, come copie dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo} dopo che questi sono stati impostati tenendo conto di eventuali -\itindex{suid~bit}\acr{suid} o \itindex{sgid~bit} \acr{sgid}. Essi quindi +\itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid}. Essi quindi consentono di tenere traccia di quale fossero utente e gruppo effettivi all'inizio dell'esecuzione di un nuovo programma. @@ -1704,7 +1708,7 @@ 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 -\itindex{value~result~argument}\textit{value result argument}). Si noti che +\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}. @@ -2571,7 +2575,7 @@ funzione. \label{sec:proc_priority} In questa sezione tratteremo più approfonditamente i meccanismi con il quale -lo \textit{scheduler}\itindex{scheduler} assegna la CPU ai vari processi +lo \itindex{scheduler} \textit{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. @@ -2581,6 +2585,7 @@ gestione. \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 @@ -2588,9 +2593,9 @@ 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 \itindex{prehemptive~multitasking}\textit{prehemptive +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 +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 @@ -2869,11 +2874,11 @@ 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 -\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 -esecuzione di qualunque processo. +\itindex{page~fault} \textit{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 esecuzione di qualunque processo. Occorre usare le priorità assolute con molta attenzione: se si dà ad un processo una priorità assoluta e questo finisce in un loop infinito, nessun @@ -3118,7 +3123,7 @@ 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{effetto~ping-pong} Può accadere cioè +\index{effetto~ping-pong} dell'\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 @@ -3145,6 +3150,7 @@ e si ha una continua invalidazione della cache, che non diventa mai disponibile. \itindbeg{CPU~affinity} + Per ovviare a questo tipo di problemi è nato il concetto di \textsl{affinità di processore} (o \textit{CPU affinity}); la possibilità cioè di far sì che un processo possa essere assegnato per @@ -3286,6 +3292,7 @@ particolari. 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} @@ -3318,10 +3325,9 @@ 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}\itindex{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 \itindex{race~condition} \textit{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 @@ -3381,7 +3387,7 @@ file, o nell'accesso a meccanismi di intercomunicazione come la memoria condivisa. In questi casi, se non si dispone della possibilità di eseguire atomicamente le operazioni necessarie, occorre che quelle parti di codice in cui si compiono le operazioni sulle risorse condivise (le cosiddette -\textsl{sezioni critiche}\index{sezione~critica}) del programma, siano +\index{sezione~critica} \textsl{sezioni critiche}) del programma, siano opportunamente protette da meccanismi di sincronizzazione (torneremo su queste problematiche di questo tipo in cap.~\ref{cha:IPC}). diff --git a/ringraziamenti.tex b/ringraziamenti.tex index 0412a43..84d2aee 100644 --- a/ringraziamenti.tex +++ b/ringraziamenti.tex @@ -1,6 +1,6 @@ %% ringraziamenti.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -15,7 +15,7 @@ Desidero ringraziare tutti coloro che a vario titolo e a pi aiutato ed han contribuito a migliorare in molteplici aspetti la qualità di GaPiL. In ordine rigorosamente alfabetico desidero citare: \begin{description} -\item[\textbf{Alessio Frusciante}] per l'apprezzamento, le molteplici +\item[\textbf{Alessio Frusciante}] per l'apprezzamento, le innumerevoli correzioni ed i suggerimenti per rendere più chiara l'esposizione. \item[\textbf{Daniele Masini}] per la rilettura puntuale, le innumerevoli correzioni, i consigli sull'esposizione ed i contributi relativi alle @@ -39,10 +39,12 @@ nuovo repository SVN ed il sistema di tracciamento dei sorgenti su {\texttt{http://gapil.truelite.it/sources}}. +% LocalWords: GaPiL Masini calling convention Maischberger HTML Group FLUG CVS +% LocalWords: repository Truelite Srl SVN + + %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: -% LocalWords: GaPiL Masini calling convention Maischberger HTML Group FLUG CVS -% LocalWords: repository Truelite Srl SVN diff --git a/session.tex b/session.tex index 5b4d30f..5427840 100644 --- a/session.tex +++ b/session.tex @@ -1,6 +1,6 @@ %% session.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{Terminali e sessioni di lavoro} \label{cha:session} @@ -85,11 +86,11 @@ esso. In generale allora all'interno di una sessione avremo un eventuale (può non esserci) \itindex{process~group} \textit{process group} in \textit{foreground}, che riunisce i processi che possono accedere al -terminale, e più \textit{process group} in \textit{background}, che non -possono accedervi. Il job control prevede che quando un processo appartenente -ad un raggruppamento in \textit{background} cerca di accedere al terminale, -venga inviato un segnale a tutti i processi del raggruppamento, in modo da -bloccarli (vedi sez.~\ref{sec:sess_ctrl_term}). +terminale, e più \itindex{process~group} \textit{process group} in +\textit{background}, che non possono accedervi. Il job control prevede che +quando un processo appartenente ad un raggruppamento in \textit{background} +cerca di accedere al terminale, venga inviato un segnale a tutti i processi +del raggruppamento, in modo da bloccarli (vedi sez.~\ref{sec:sess_ctrl_term}). Un comportamento analogo si ha anche per i segnali generati dai comandi di tastiera inviati dal terminale che vengono inviati a tutti i processi del @@ -182,7 +183,7 @@ stessa sessione del padre. Vedremo poi come sia possibile creare pi processi dall'uno all'altro, ma sempre all'interno di una stessa sessione. Ciascun raggruppamento di processi ha sempre un processo principale, il -cosiddetto \itindex{process~group~leader}\textit{process group leader}, che è +cosiddetto \itindex{process~group~leader} \textit{process group leader}, che è identificato dall'avere un \acr{pgid} uguale al suo \acr{pid}, in genere questo è il primo processo del raggruppamento, che si incarica di lanciare tutti gli altri. Un nuovo raggruppamento si crea con la funzione @@ -238,8 +239,8 @@ sia dal 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 \textit{race - condition}\itindex{race~condition}. +occorre eseguirle comunque entrambe per evitare di esporsi ad una +\itindex{race~condition} \textit{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 @@ -447,15 +448,15 @@ tutto ci controllo. Consideriamo allora cosa avviene di norma nel \textit{job control}: una sessione viene creata con \func{setsid} che crea anche un nuovo \itindex{process~group} \textit{process group}: per definizione -quest'ultimo è sempre \textsl{orfano}, dato che il padre del leader di -sessione è fuori dalla stessa e il nuovo \textit{process group} -\itindex{process~group} contiene solo il leader di sessione. Questo è un caso -limite, e non viene emesso nessun segnale perché quanto previsto dallo -standard riguarda solo i raggruppamenti che diventano orfani in seguito alla -terminazione di un processo.\footnote{l'emissione dei segnali infatti avviene - solo nella fase di uscita del processo, come una delle operazioni legate - all'esecuzione di \func{\_exit}, secondo quanto illustrato in - sez.~\ref{sec:proc_termination}.} +quest'ultimo è sempre \itindex{process~group~orphaned} \textsl{orfano}, dato +che il padre del leader di sessione è fuori dalla stessa e il nuovo +\textit{process group} \itindex{process~group} contiene solo il leader di +sessione. Questo è un caso limite, e non viene emesso nessun segnale perché +quanto previsto dallo standard riguarda solo i raggruppamenti che diventano +orfani in seguito alla terminazione di un processo.\footnote{l'emissione dei + segnali infatti avviene solo nella fase di uscita del processo, come una + delle operazioni legate all'esecuzione di \func{\_exit}, secondo quanto + illustrato in sez.~\ref{sec:proc_termination}.} Il leader di sessione provvederà a creare nuovi raggruppamenti che a questo punto non sono orfani in quanto esso resta padre per almeno uno dei processi @@ -1047,7 +1048,7 @@ prototipo \textit{pathname} del terminale.} \end{prototype} -La funzione scrive il \itindex{pathname}\textit{pathname} del terminale di +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 @@ -1081,7 +1082,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 \itindex{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. @@ -1997,10 +1998,6 @@ Qui vanno spiegati i terminali virtuali, \file{/dev/pty} e compagnia. Qui vanno le cose su \func{openpty} e compagnia. -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "gapil" -%%% End: % LocalWords: kernel multitasking dell'I job control BSD POSIX shell sez group % LocalWords: foreground process bg fg Di waitpid WUNTRACED pgrp session sched @@ -2036,3 +2033,9 @@ Qui vanno le cose su \func{openpty} e compagnia. % LocalWords: cfgetospeed quest'ultime tcsendbreak duration break tcdrain % LocalWords: tcflush queue TCIFLUSH TCOFLUSH TCIOFLUSH tcflow action TCOOFF % LocalWords: TCOON TCIOFF TCION timer openpty Window nochdir + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: \ No newline at end of file diff --git a/signal.tex b/signal.tex index edd354a..edbc674 100644 --- a/signal.tex +++ b/signal.tex @@ -1,6 +1,6 @@ %% signal.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{I segnali} \label{cha:signals} @@ -116,7 +117,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 \textit{race condition}\itindex{race~condition} +sono sempre possibili delle \itindex{race~condition} \textit{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 +137,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 \itindex{scheduler} quando, +procedura viene effettuata dallo \itindex{scheduler} 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,7 +210,7 @@ ignorarlo). Normalmente l'invio al processo che deve ricevere il segnale è immediato ed avviene non appena questo viene rimesso in esecuzione dallo -scheduler \itindex{scheduler} che esegue l'azione specificata. Questo a meno +\itindex{scheduler} 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 @@ -244,8 +245,8 @@ Un programma pu 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}). +automaticamente bloccato (così si possono evitare \itindex{race~condition} +\textit{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 @@ -260,7 +261,7 @@ un eventuale messaggio di errore. I segnali che rappresentano errori del programma (divisione per zero o violazioni di accesso) hanno anche la caratteristica di scrivere un file di -\itindex{core~dump}\textit{core dump} che registra lo stato del processo (ed +\itindex{core~dump} \textit{core dump} che registra lo stato del processo (ed in particolare della memoria e dello \itindex{stack} stack) prima della terminazione. Questo può essere esaminato in seguito con un debugger per investigare sulla causa dell'errore. Lo stesso avviene se i suddetti segnali @@ -347,7 +348,7 @@ colonna standard sono stati indicati anche gli standard in cui ciascun segnale In alcuni casi alla terminazione del processo è associata la creazione di un file (posto nella directory corrente del processo e chiamato \file{core}) su cui viene salvata un'immagine della memoria del processo (il cosiddetto -\itindex{core~dump}\textit{core dump}), che può essere usata da un debugger +\itindex{core~dump} \textit{core dump}), che può essere usata da un debugger per esaminare lo stato dello \itindex{stack} stack e delle variabili al momento della ricezione del segnale. @@ -418,7 +419,7 @@ tipologia, verr \label{sec:sig_prog_error} Questi segnali sono generati quando il sistema, o in certi casi direttamente -l'hardware (come per i \itindex{page~fault}\textit{page fault} non validi) +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 @@ -426,7 +427,7 @@ una operazione aritmetica proibita) e l'esecuzione non pu In genere si intercettano questi segnali per permettere al programma di terminare in maniera pulita, ad esempio per ripristinare le impostazioni della -console o eliminare i file di lock\index{file!di lock} prima dell'uscita. In +console o eliminare i \index{file!di lock} file di lock prima dell'uscita. In questo caso il gestore deve concludersi ripristinando l'azione predefinita e rialzando il segnale, in questo modo il programma si concluderà senza effetti spiacevoli, ma riportando lo stesso stato di uscita che avrebbe avuto se il @@ -434,7 +435,7 @@ gestore non ci fosse stato. L'azione predefinita per tutti questi segnali è causare la terminazione del processo che li ha causati. In genere oltre a questo il segnale provoca pure -la registrazione su disco di un file di \itindex{core~dump}\textit{core dump} +la registrazione su disco di un file di \itindex{core~dump} \textit{core dump} che viene scritto in un file \file{core} nella directory corrente del processo al momento dell'errore, che il debugger può usare per ricostruire lo stato del programma al momento della terminazione. Questi segnali sono: @@ -518,19 +519,19 @@ segnali sono: comando \cmd{kill} o dall'invio sul terminale del carattere di controllo INTR (interrupt, generato dalla sequenza \cmd{C-c}). -\item[\const{SIGQUIT}] È analogo a \const{SIGINT} con la differenza - che è controllato da un altro carattere di controllo, QUIT, - corrispondente alla sequenza \texttt{C-\bslash}. A differenza del - precedente l'azione predefinita, oltre alla terminazione del - processo, comporta anche la creazione di un - \itindex{core~dump}\textit{core dump}. +\item[\const{SIGQUIT}] È analogo a \const{SIGINT} con la differenza che è + controllato da un altro carattere di controllo, QUIT, corrispondente alla + sequenza \texttt{C-\bslash}. A differenza del precedente l'azione + predefinita, oltre alla terminazione del processo, comporta anche la + creazione di un \itindex{core~dump} \textit{core dump}. In genere lo si può pensare come corrispondente ad una condizione di errore del programma rilevata dall'utente. Per questo motivo non è opportuno fare eseguire al gestore di questo segnale le operazioni di pulizia normalmente previste (tipo la cancellazione di file temporanei), dato che in certi casi - esse possono eliminare informazioni utili nell'esame dei \textit{core dump}. - \itindex{core~dump} + esse possono eliminare informazioni utili nell'esame dei \itindex{core~dump} + \textit{core dump}. + \item[\const{SIGKILL}] Il nome è utilizzato per terminare in maniera immediata qualunque programma. Questo segnale non può essere né intercettato, né @@ -805,7 +806,7 @@ programmi eseguiti in background, che altrimenti sarebbero interrotti da una successiva pressione di \texttt{C-c} o \texttt{C-y}. Per quanto riguarda il comportamento di tutte le altre system call si danno -sostanzialmente due casi, a seconda che esse siano\index{system~call~lente} +sostanzialmente due casi, a seconda che esse siano \index{system~call~lente} \textsl{lente} (\textit{slow}) o \textsl{veloci} (\textit{fast}). La gran parte di esse appartiene a quest'ultima categoria, che non è influenzata dall'arrivo di un segnale. Esse sono dette \textsl{veloci} in quanto la loro @@ -821,7 +822,7 @@ eseguito prima che la system call sia ritornata. Un elenco dei casi in cui si presenta questa situazione è il seguente: \begin{itemize*} \item la lettura da file che possono bloccarsi in attesa di dati non ancora - presenti (come per certi file di dispositivo\index{file!di~dispositivo}, i + presenti (come per certi \index{file!di~dispositivo} file di dispositivo, i socket o le pipe); \item la scrittura sugli stessi file, nel caso in cui dati non possano essere accettati immediatamente (di nuovo comune per i socket); @@ -1376,7 +1377,7 @@ 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 \itindex{scheduler} +occorrerà almeno attendere il successivo giro di \itindex{scheduler} 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 @@ -1400,16 +1401,16 @@ conclusione di un processo padre.\footnote{in realtà in SVr4 eredita la semantica di System V, in cui il segnale si chiama \const{SIGCLD} e viene trattato in maniera speciale; in System V infatti se si imposta esplicitamente l'azione a \const{SIG\_IGN} il - segnale non viene generato ed il sistema non genera zombie\index{zombie} (lo - stato di terminazione viene scartato senza dover chiamare una \func{wait}). - L'azione predefinita è sempre quella di ignorare il segnale, ma non attiva - questo comportamento. Linux, come BSD e POSIX, non supporta questa semantica - ed usa il nome di \const{SIGCLD} come sinonimo di \const{SIGCHLD}.} In -generale dunque, quando non interessa elaborare lo stato di uscita di un -processo, si può completare la gestione della terminazione installando un -gestore per \const{SIGCHLD} il cui unico compito sia quello di chiamare -\func{waitpid} per completare la procedura di terminazione in modo da evitare -la formazione di zombie\index{zombie}. + segnale non viene generato ed il sistema non genera \index{zombie} zombie + (lo stato di terminazione viene scartato senza dover chiamare una + \func{wait}). L'azione predefinita è sempre quella di ignorare il segnale, + ma non attiva questo comportamento. Linux, come BSD e POSIX, non supporta + questa semantica ed usa il nome di \const{SIGCLD} come sinonimo di + \const{SIGCHLD}.} In generale dunque, quando non interessa elaborare lo +stato di uscita di un processo, si può completare la gestione della +terminazione installando un gestore per \const{SIGCHLD} il cui unico compito +sia quello di chiamare \func{waitpid} per completare la procedura di +terminazione in modo da evitare la formazione di \index{zombie} zombie. In fig.~\ref{fig:sig_sigchld_handl} è mostrato il codice contenente una implementazione generica di una funzione di gestione per \const{SIGCHLD}, (che @@ -1417,7 +1418,7 @@ si trova nei sorgenti allegati nel file \file{SigHand.c}); se ripetiamo i test di sez.~\ref{sec:proc_termination}, invocando \cmd{forktest} con l'opzione \cmd{-s} (che si limita ad effettuare l'installazione di questa funzione come gestore di \const{SIGCHLD}) potremo verificare che non si ha più la creazione -di zombie\index{zombie}. +di \index{zombie} zombie. \begin{figure}[!htb] \footnotesize \centering @@ -1457,7 +1458,7 @@ rimosso verr Allora, nel caso della terminazione dei processi figli, se si chiamasse \func{waitpid} una sola volta, essa leggerebbe lo stato di terminazione per un solo processo, anche se i processi terminati sono più di uno, e gli altri -resterebbero in stato di zombie\index{zombie} per un tempo indefinito. +resterebbero in stato di \index{zombie} zombie per un tempo indefinito. Per questo occorre ripetere la chiamata di \func{waitpid} fino a che essa non ritorni un valore nullo, segno che non resta nessun processo di cui si debba @@ -1473,9 +1474,9 @@ 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 \textit{race - condition}\itindex{race~condition} che i segnali possono generare e alla -natura asincrona degli stessi. +considerazione le tematiche più complesse, collegate alle varie +\itindex{race~condition} \textit{race condition} che i segnali possono +generare e alla natura asincrona degli stessi. Affronteremo queste problematiche in questa sezione, partendo da un esempio che le evidenzi, per poi prendere in esame le varie funzioni che permettono di @@ -1516,12 +1517,12 @@ 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 \textit{race condition}\itindex{race~condition}. +presenta una pericolosa \itindex{race~condition} \textit{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\itindex{deadlock}, in quanto \func{pause} +troverebbe di fronte ad un \itindex{deadlock} 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 @@ -1578,12 +1579,12 @@ quale potr 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 -\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 -occorrenza sarà perduta. +sez.~\ref{sec:proc_race_cond}, in cui si genera una \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 occorrenza sarà +perduta. Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono delle funzioni più sofisticate di quelle finora illustrate, queste hanno la @@ -1973,7 +1974,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 \textit{race condition}\itindex{race~condition} restano aperte +dei casi di \itindex{race~condition} \textit{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 @@ -2032,12 +2033,11 @@ 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 \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 -i seguenti: +In questo modo non sono più possibili \itindex{race~condition} \textit{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 i seguenti: \begin{enumerate*} \item Leggere la maschera dei segnali corrente e bloccare il segnale voluto con \func{sigprocmask}; @@ -2047,8 +2047,8 @@ 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\itindex{deadlock} dovuto all'arrivo del segnale prima dell'esecuzione -di \func{sigsuspend}. +\itindex{deadlock} deadlock dovuto all'arrivo del segnale prima +dell'esecuzione di \func{sigsuspend}. \itindend{signal~mask} @@ -2200,7 +2200,7 @@ due comportamenti il programma deve assumere; i loro prototipi sono: \headdecl{setjmp.h} \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto - dello stack per un salto non-locale\index{salto~non-locale}. + dello stack per un \index{salto~non-locale} salto non-locale. \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto non-locale su un precedente contesto. @@ -2212,7 +2212,7 @@ due comportamenti il programma deve assumere; i loro prototipi sono: Le due funzioni prendono come primo argomento la variabile su cui viene salvato il contesto dello \itindex{stack} stack per permettere il -\index{salto~non-locale}salto non-locale; nel caso specifico essa è di tipo +\index{salto~non-locale} salto non-locale; nel caso specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} come per le analoghe di sez.~\ref{sec:proc_longjmp} in quanto in questo caso viene salvata anche la maschera dei segnali. diff --git a/sockadv.tex b/sockadv.tex index c505760..6ec7824 100644 --- a/sockadv.tex +++ b/sockadv.tex @@ -1,6 +1,6 @@ %% sockadv.tex %% -%% Copyright (C) 2004-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2004-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{Socket avanzati} \label{cha:advanced_socket} diff --git a/sockctrl.tex b/sockctrl.tex index 1b8d37a..df3ed69 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -1,6 +1,6 @@ %% sockctrl.tex %% -%% Copyright (C) 2004-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2004-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Prefazione", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{La gestione dei socket} \label{cha:sock_generic_management} @@ -617,7 +618,7 @@ argomento (che si presume sia dato da \var{h\_errno}). \subsection{La risoluzione dei nomi a dominio} \label{sec:sock_name_services} -La principale funzionalità del \itindex{resolver}\textit{resolver} resta +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 @@ -682,7 +683,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 \itindex{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 è: @@ -719,7 +720,7 @@ 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 -\itindex{resolver}\textit{resolver} usando \func{gethostbyname} e poi ne +\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. @@ -776,14 +777,14 @@ chiamate i dati potranno essere sovrascritti. Si tenga presente poi che copiare il contenuto della sola struttura non è sufficiente per salvare tutti 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 -\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.} +una chiamata, occorrerà eseguire quella che si chiama una \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.} Per ovviare a questi problemi nelle \acr{glibc} sono definite anche delle versioni rientranti delle precedenti funzioni, al solito queste sono @@ -818,7 +819,7 @@ 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 \itindex{value~result~argument}\textit{value result argument}, si deve +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}. @@ -1255,7 +1256,7 @@ utilizzata dalla funzione per riportare (come \itindex{value~result~argument} 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 +\itindex{linked~list} \textit{linked list} di strutture di tipo \struct{addrinfo} contenenti tutte le informazioni ottenute. \begin{figure}[!htb] @@ -1462,13 +1463,13 @@ lista illustrata in fig.~\ref{fig:sock_addrinfo_list}. \begin{figure}[!htb] \centering \includegraphics[width=10cm]{img/addrinfo_list} - \caption{La \itindex{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 \itindex{resolver}\textit{resolver} basato +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 @@ -1559,7 +1560,7 @@ IPv4 address: \end{Verbatim} %$ -Una volta estratti i risultati dalla \itindex{linked~list}\textit{linked list} +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 è: @@ -1581,7 +1582,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 \itindex{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,7 +1980,7 @@ 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 \itindex{value~result~argument}\textit{value result +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. diff --git a/socket.tex b/socket.tex index 052e8c5..b2f9033 100644 --- a/socket.tex +++ b/socket.tex @@ -1,6 +1,6 @@ %% socket.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{Introduzione ai socket} \label{cha:socket_intro} @@ -243,7 +244,7 @@ Si tenga presente che non tutte le famiglie di protocolli sono utilizzabili dall'utente generico, ad esempio in generale tutti i socket di tipo \const{SOCK\_RAW} possono essere creati solo da processi che hanno i privilegi di amministratore (cioè con user-ID effettivo uguale a zero) o dotati della -\itindex{capabilities}\textit{capability} \const{CAP\_NET\_RAW}. +\itindex{capabilities} \textit{capability} \const{CAP\_NET\_RAW}. \subsection{Il tipo di socket} @@ -468,7 +469,7 @@ altrimenti si avr specifica il \textsl{numero di porta}. I numeri di porta sotto il 1024 sono chiamati \textsl{riservati} in quanto utilizzati da servizi standard e soltanto processi con i privilegi di amministratore (con user-ID effettivo -uguale a zero) o con la \itindex{capabilities}\textit{capability} +uguale a zero) o con la \itindex{capabilities} \textit{capability} \const{CAP\_NET\_BIND\_SERVICE} possono usare la funzione \func{bind} (che vedremo in sez.~\ref{sec:TCP_func_bind}) su queste porte. @@ -552,7 +553,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 -\itindex{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. @@ -648,7 +649,7 @@ speciale \const{ETH\_P\_ALL} passeranno sul \textit{packet socket} tutti i pacchetti, qualunque sia il loro protocollo di collegamento. Ovviamente l'uso di questi socket è una operazione privilegiata e può essere effettuati solo da un processo con i privilegi di amministratore (user-ID effettivo nullo) o con -la \itindex{capabilities}\textit{capability} \const{CAP\_NET\_RAW}. +la \itindex{capabilities} \textit{capability} \const{CAP\_NET\_RAW}. Una volta aperto un \textit{packet socket}, tutti i pacchetti del protocollo specificato passeranno attraverso di esso, qualunque sia l'interfaccia da cui @@ -857,7 +858,7 @@ il valore del confronto delle due variabili. \subsection{Le funzioni per il riordinamento} \label{sec:sock_func_ord} -Il problema connesso all'endianess\itindex{endianess} è che quando si passano +Il problema connesso \itindex{endianess} all'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 diff --git a/system.tex b/system.tex index 629c48c..f2569bf 100644 --- a/system.tex +++ b/system.tex @@ -1,6 +1,6 @@ %% system.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{La gestione del sistema, del tempo e degli errori} \label{cha:system} @@ -403,7 +404,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 - \itindex{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 @@ -434,7 +435,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 - \itindex{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 @@ -477,12 +478,12 @@ 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 -\itindex{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 \itindex{pathname}\textit{pathname}; pertanto gli errori + 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}. @@ -601,7 +602,7 @@ 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 \itindex{pathname}\textit{pathname} (da cui l'uso +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 @@ -645,7 +646,7 @@ 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 \itindex{pathname}\textit{pathname} e leggendo e scrivendo sul +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 @@ -701,7 +702,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 \itindex{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}. @@ -767,7 +768,7 @@ valori riportati in tab.~\ref{tab:sys_mount_flags}. \hline \const{MS\_RDONLY} & 1 & monta in sola lettura.\\ \const{MS\_NOSUID} & 2 & ignora i bit \itindex{suid~bit} \acr{suid} e - \itindex{sgid~bit}\acr{sgid}.\\ + \itindex{sgid~bit} \acr{sgid}.\\ \const{MS\_NODEV} & 4 & impedisce l'accesso ai file di dispositivo.\\ \const{MS\_NOEXEC} & 8 & impedisce di eseguire programmi.\\ \const{MS\_SYNCHRONOUS}& 16 & abilita la scrittura sincrona.\\ @@ -949,7 +950,7 @@ 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 \itindex{Name~Service~Switch}\textit{Name Service Switch} che tratteremo +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. @@ -1083,7 +1084,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 \itindex{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 @@ -1381,7 +1382,7 @@ 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}\itindex{page~fault} (vedi sez.~\ref{sec:proc_mem_gen}) +\itindex{page~fault} \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 @@ -1456,12 +1457,12 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard stack il processo riceverà un segnale di \const{SIGSEGV}. \\ \const{RLIMIT\_CORE} & La massima dimensione per di un file di - \textit{core dump}\itindex{core~dump} (vedi + \itindex{core~dump} \textit{core dump} (vedi sez.~\ref{sec:sig_prog_error}) creato nella terminazione di un processo; file di dimensioni maggiori verranno troncati a questo valore, mentre con un valore si bloccherà la creazione - dei \textit{core dump}\itindex{core~dump}.\\ + dei \itindex{core~dump} \textit{core dump}.\\ \const{RLIMIT\_CPU} & Il massimo tempo di CPU (vedi sez.~\ref{sec:sys_cpu_times}) che il processo può usare. Il superamento del limite corrente @@ -1548,7 +1549,7 @@ In generale il superamento di un limite corrente\footnote{di norma quanto dei due limiti.} comporta o l'emissione di un segnale o il fallimento della system call che lo ha provocato;\footnote{si nuovo c'è una eccezione per \const{RLIMIT\_CORE} che influenza soltanto la dimensione (o l'eventuale - creazione) dei file di \itindex{core~dump}\textit{core dump}.} per + creazione) dei file di \itindex{core~dump} \textit{core dump}.} per permettere di leggere e di impostare i limiti di utilizzo delle risorse da parte di un processo sono previste due funzioni, \funcd{getrlimit} e \funcd{setrlimit}, i cui prototipi sono: @@ -1603,7 +1604,7 @@ Nello specificare un limite, oltre a fornire dei valori specifici, si pu anche usare la costante \const{RLIM\_INFINITY} che permette di sbloccare l'uso di una risorsa; ma si ricordi che solo un processo con i privilegi di amministratore\footnote{per essere precisi in questo caso quello che serve è - la \itindex{capabilities}\textit{capability} \const{CAP\_SYS\_RESOURCE}.} + la \itindex{capabilities} \textit{capability} \const{CAP\_SYS\_RESOURCE}.} può innalzare un limite al di sopra del valore corrente del limite massimo ed usare un valore qualsiasi per entrambi i limiti. Si tenga conto infine che tutti i limiti vengono ereditati dal processo padre attraverso una \func{fork} @@ -1616,7 +1617,7 @@ attraverso una \func{exec} (vedi sez.~\ref{sec:proc_exec}). La gestione della memoria è già stata affrontata in dettaglio in sez.~\ref{sec:proc_memory}; abbiamo visto allora che il kernel provvede il -meccanismo della memoria virtuale\index{memoria~virtuale} attraverso la +meccanismo della \index{memoria~virtuale} memoria virtuale attraverso la divisione della memoria fisica in pagine. In genere tutto ciò è del tutto trasparente al singolo processo, ma in certi @@ -1624,7 +1625,7 @@ casi, come per l'I/O mappato in memoria (vedi sez.~\ref{sec:file_memory_map}) che usa lo stesso meccanismo per accedere ai file, è necessario conoscere le dimensioni delle pagine usate dal kernel. Lo stesso vale quando si vuole gestire in maniera ottimale l'interazione della memoria che si sta allocando -con il meccanismo della paginazione\index{paginazione}. +con il meccanismo della \index{paginazione} paginazione. Di solito la dimensione delle pagine di memoria è fissata dall'architettura hardware, per cui il suo valore di norma veniva mantenuto in una costante che @@ -1697,8 +1698,8 @@ Il suo prototipo \end{prototype} La funzione restituisce in ciascun elemento di \param{loadavg} il numero medio -di processi attivi sulla coda dello scheduler\itindex{scheduler}, calcolato su -diversi intervalli di tempo. Il numero di intervalli che si vogliono +di processi attivi sulla coda dello \itindex{scheduler} scheduler, calcolato +su diversi 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. @@ -1822,7 +1823,7 @@ mantenuto dal sistema e non dall'orologio hardware del calcolatore. Anche il \itindex{process~time} \textit{process time} di solito si esprime in -secondi, ma provvede una precisione ovviamente superiore al \textit{calendar +secondi, ma fornisce una precisione ovviamente superiore al \textit{calendar time} (che è mantenuto dal sistema con una granularità di un secondo) e viene usato per tenere conto dei tempi di esecuzione dei processi. Per ciascun processo il kernel calcola tre tempi diversi: diff --git a/tcpsock.tex b/tcpsock.tex index e55e06f..a976ecd 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -1,6 +1,6 @@ %% tcpsock.tex %% -%% Copyright (C) 2000-2006 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -8,6 +8,7 @@ %% license is included in the section entitled "GNU Free Documentation %% License". %% + \chapter{I socket TCP} \label{cha:TCP_socket} @@ -304,10 +305,10 @@ che il protocollo viene ad assumere per i due lati, server e client. \label{fig:TCP_conn_example} \end{figure} -La connessione viene iniziata dal client che annuncia una MSS -\itindex{Maximum~Segment~Size} di 1460, un valore tipico con Linux per IPv4 su -Ethernet, il server risponde con lo stesso valore (ma potrebbe essere anche un -valore diverso). +La connessione viene iniziata dal client che annuncia una +\itindex{Maximum~Segment~Size} MSS di 1460, un valore tipico con Linux per +IPv4 su Ethernet, il server risponde con lo stesso valore (ma potrebbe essere +anche un valore diverso). Una volta che la connessione è stabilita il client scrive al server una richiesta (che assumiamo stare in un singolo segmento, cioè essere minore dei @@ -733,9 +734,9 @@ 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}\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}. +\itindex{endianess} l'\textit{endianess} della macchina, ed anche se esse +possono essere invarianti rispetto all'ordinamento dei bit, è comunque buona +norma usare sempre la funzione \func{htonl}. \begin{table}[htb] \centering @@ -782,7 +783,7 @@ 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 \itindex{three~way~handshake}\textit{three way handshake}) della + 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 @@ -827,11 +828,11 @@ 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 -\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 -o problemi nella chiamata della funzione sono le seguenti: +\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 o problemi +nella chiamata della funzione sono le seguenti: \begin{enumerate} \item Il client non riceve risposta al SYN: l'errore restituito è \errcode{ETIMEDOUT}. Stevens riporta che BSD invia un primo SYN alla @@ -2041,7 +2042,7 @@ esaminato in sez.~\ref{sec:proc_termination}). In questo caso avremo l'invio del segnale \const{SIGCHLD} al padre, ma dato che non si è installato un gestore e che l'azione predefinita per questo segnale è quella di essere ignorato, non avendo predisposto la ricezione dello stato di terminazione, -otterremo che il processo figlio entrerà nello stato di zombie\index{zombie} +otterremo che il processo figlio entrerà nello stato di \index{zombie} zombie (si riveda quanto illustrato in sez.~\ref{sec:sig_sigchld}), come risulterà ripetendo il comando \cmd{ps}: \begin{verbatim} @@ -2049,7 +2050,7 @@ ripetendo il comando \cmd{ps}: 2359 pts/0 Z 0:00 [echod ] \end{verbatim} -Dato che non è il caso di lasciare processi zombie\index{zombie}, occorrerà +Dato che non è il caso di lasciare processi \index{zombie} zombie, occorrerà ricevere opportunamente lo stato di terminazione del processo (si veda sez.~\ref{sec:proc_wait}), cosa che faremo utilizzando \const{SIGCHLD} secondo quanto illustrato in sez.~\ref{sec:sig_sigchld}. Una prima modifica al nostro @@ -2411,13 +2412,13 @@ 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} \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 +del \itindex{three~way~handshake} \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 @@ -3215,8 +3216,8 @@ precedente versione causava l'immediato ritorno della funzione; in questo caso prima (\texttt{\small 19}) si imposta opportunamente \var{eof} ad un valore non nullo, dopo di che (\texttt{\small 20}) si effettua la chiusura del lato in scrittura del socket con \func{shutdown}. Infine (\texttt{\small 21}) si -usa la macro \macro{FD\_CLR} per togliere lo standard input dal file -descriptor set. \itindex{file~descriptor~set} +usa la macro \macro{FD\_CLR} per togliere lo standard input dal +\itindex{file~descriptor~set} \textit{file descriptor set}. In questo modo anche se la lettura del file in ingresso è conclusa, la funzione non esce dal ciclo principale (\texttt{\small 11--50}), ma continua @@ -3356,13 +3357,13 @@ vi sono dati sui socket connessi, per questo si ripete un ciclo diverso da zero; in questo modo se l'unico socket con attività era quello connesso, avendo opportunamente decrementato il contatore, il ciclo verrà saltato, e si ritornerà immediatamente (ripetuta l'inizializzazione del -\itindex{file~descriptor~set} file descriptor set con i nuovi valori nella -tabella) alla chiamata di \func{accept}. Se il socket attivo non è quello in -ascolto, o ce ne sono comunque anche altri, il valore di \var{n} non sarà -nullo ed il controllo sarà eseguito. Prima di entrare nel ciclo comunque si -inizializza (\texttt{\small 28}) il valore della variabile \var{i} che useremo -come indice nella tabella \var{fd\_open} al valore minimo, corrispondente al -file descriptor del socket in ascolto. +\itindex{file~descriptor~set} \textit{file descriptor set} con i nuovi valori +nella tabella) alla chiamata di \func{accept}. Se il socket attivo non è +quello in ascolto, o ce ne sono comunque anche altri, il valore di \var{n} non +sarà nullo ed il controllo sarà eseguito. Prima di entrare nel ciclo comunque +si inizializza (\texttt{\small 28}) il valore della variabile \var{i} che +useremo come indice nella tabella \var{fd\_open} al valore minimo, +corrispondente al file descriptor del socket in ascolto. Il primo passo (\texttt{\small 30}) nella verifica è incrementare il valore dell'indice \var{i} per posizionarsi sul primo valore possibile per un file @@ -3575,9 +3576,10 @@ uscita e notifica in caso si errore (\texttt{\small 49--52}). Come si può notare la logica del programma è identica a quella vista in fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select}; la sola differenza significativa è che in questo caso non c'è bisogno di -rigenerare i \itindex{file~descriptor~set} file descriptor set in quanto -l'uscita è indipendente dai dati in ingresso. Si applicano comunque anche a -questo server le considerazioni finali di sez.~\ref{sec:TCP_serv_select}. +rigenerare i \itindex{file~descriptor~set} \textit{file descriptor set} in +quanto l'uscita è indipendente dai dati in ingresso. Si applicano comunque +anche a questo server le considerazioni finali di +sez.~\ref{sec:TCP_serv_select}. % LocalWords: socket TCP client dell'I multiplexing stream three way handshake diff --git a/trasplayer.tex b/trasplayer.tex index 6ad3241..980d6f8 100644 --- a/trasplayer.tex +++ b/trasplayer.tex @@ -1,7 +1,7 @@ %% tcpprot.tex %% -%% Copyright (C) 2002-2006 Simone Piccardi. Permission is granted to -%% copy, distribute and/or modify this document under the terms of the GNU Free +%% Copyright (C) 2002-2007 Simone Piccardi. Permission is granted to copy, +%% distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", %% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the