From: Simone Piccardi Date: Tue, 13 Sep 2005 09:07:45 +0000 (+0000) Subject: Lavoro fatto a casa senza ADSL, correzioni multiple agli indici, documentato X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=6f8e0ca42d3d0b97b5e5747798a1eaffb44e8521;p=gapil.git Lavoro fatto a casa senza ADSL, correzioni multiple agli indici, documentato l'accounting BSD, parte delle capabilities, varie caratteristiche di mmap ed parecchia altra roba. --- diff --git a/errors.tex b/errors.tex index 7b92a3f..991a166 100644 --- a/errors.tex +++ b/errors.tex @@ -125,10 +125,11 @@ gestione dei file. \item \errcode{ENOLCK} \textit{No locks available}. È usato dalle utilità per la gestione del file lock; non viene generato da un sistema GNU, ma può risultare da un'operazione su un server NFS di un altro sistema. -\item \errcode{EFTYPE} \textit{Inappropriate file type or format}. Il file è di - tipo sbagliato rispetto all'operazione richiesta o un file di dati ha un +\item \errcode{EFTYPE} \textit{Inappropriate file type or format}. Il file è + di tipo sbagliato rispetto all'operazione richiesta o un file di dati ha un formato sbagliato. Alcuni sistemi restituiscono questo errore quando si - cerca di impostare lo \textit{sticky bit} su un file che non è una directory. + cerca di impostare lo \itindex{sticky~bit} \textit{sticky bit} su un file che + non è una directory. \end{description} @@ -152,6 +153,7 @@ gestione dei processi. figli. %\item \errcode{EPROCLIM} \textit{}. Il limite dell'utente per nuovi processi % sarà ecceduto alla prossima \func{fork}. (non credo esista in Linux) +% TODO verificare EPROCLIM \end{description} @@ -362,7 +364,8 @@ specificati nelle sezioni precedenti. % In questa sezione sono raccolti i codici di errore interni del kernel. Non % sono usati dalle funzioni di libreria, ma vengono riportati da alcune system -% call (TODO verificare i dettagli, eventualmente cassare). +% call +% TODO verificare i dettagli degli errori del kernel, eventualmente cassare. % \begin{description} % \item \errcode{ERESTART} \textit{Interrupted system call should be restarted}. diff --git a/fileadv.tex b/fileadv.tex index 67d6795..b49bcf8 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -52,7 +52,7 @@ possibile prevedere quando questo pu 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 +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 @@ -222,7 +222,7 @@ ha ovviamente delle conseguenze ampiamente negative per le prestazioni. Inoltre c'è anche il problema che il numero massimo dei file che si possono tenere sotto controllo, la funzione è nata quando il kernel consentiva un numero massimo di 1024 file descriptor per processo, adesso che il numero può -essere arbitario si viene a creare una dipendenza del tutto artificiale dalle +essere arbitrario si viene a creare una dipendenza del tutto artificiale dalle dimensioni della struttura \type{fd\_set}, che può necessitare di essere estesa, con ulteriori perdite di prestazioni. @@ -439,7 +439,7 @@ tramite \var{errno}. %\label{sec:file_epoll} % placeholder ... -%da fare +% TODO epoll \section{L'accesso \textsl{asincrono} ai file} \label{sec:file_asyncronous_access} @@ -504,7 +504,8 @@ POSIX.1b dei segnali real-time, che vengono accodati e che permettono di riconoscere il file descriptor che li ha emessi. In questo caso infatti si può fare ricorso alle informazioni aggiuntive restituite attraverso la struttura \struct{siginfo\_t}, utilizzando la forma estesa \var{sa\_sigaction} del -gestore (si riveda quanto illustrato in sez.~\ref{sec:sig_sigaction}). +gestore installata con il flag \const{SA\_SIGINFO} (si riveda quanto +illustrato in sez.~\ref{sec:sig_sigaction}). Per far questo però occorre utilizzare le funzionalità dei segnali real-time (vedi sez.~\ref{sec:sig_real_time}) impostando esplicitamente con il comando @@ -530,6 +531,243 @@ invier i segnali in eccesso, e si dovrà allora determinare con un ciclo quali sono i file diventati attivi. +% TODO fare esempio che usa O_ASYNC + + +\subsection{I meccanismi di notifica asincrona.} +\label{sec:file_asyncronous_lease} + +Una delle domande più frequenti nella programmazione in ambiente unix-like è +quella di come fare a sapere quando un file viene modificato. La +risposta\footnote{o meglio la non risposta, tanto che questa nelle Unix FAQ + \cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered + Question}.} è che nell'architettura classica di Unix questo non è +possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like +non prevede alcun meccanismo per cui un processo possa essere +\textsl{notificato} di eventuali modifiche avvenute su un file. Questo è il +motivo per cui i demoni devono essere \textsl{avvisati} in qualche +modo\footnote{in genere questo vien fatto inviandogli un segnale di + \const{SIGHUP} che, per convenzione adottata dalla gran parte di detti + programmi, causa la rilettura della configurazione.} se il loro file di +configurazione è stato modificato, perché possano rileggerlo e riconoscere le +modifiche. + +Questa scelta è stata fatta perché provvedere un simile meccanismo a livello +generale comporterebbe un notevole aumento di complessità dell'architettura +della gestione dei file, per fornire una funzionalità necessaria soltanto in +casi particolari. Dato che all'origine di Unix i soli programmi che potevano +avere una tale esigenza erano i demoni, attenendosi a uno dei criteri base +della progettazione, che era di far fare al kernel solo le operazioni +strettamente necessarie e lasciare tutto il resto a processi in user space, +non era stata prevista nessuna funzionalità di notifica. + +Visto però il crescente interesse nei confronti di una funzionalità di questo +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}. + +Queste nuove funzionalità sono delle estensioni specifiche, non +standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel +supportano meccanismi simili). Esse sono realizzate, e solo a partire dalla +versione 2.4 del kernel, attraverso l'uso di alcuni \textsl{comandi} +aggiuntivi per la funzione \func{fcntl} (vedi sez.~\ref{sec:file_fcntl}), che +divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE} +prima di includere \file{fcntl.h}. + +\index{file!lease|(} + +La prima di queste funzionalità è quella del cosiddetto \textit{file lease}; +questo è un meccanismo che consente ad un processo, detto \textit{lease + holder}, di essere notificato quando un altro processo, chiamato a sua volta +\textit{lease breaker}, cerca di eseguire una \func{open} o una +\func{truncate} sul file del quale l'\textit{holder} detiene il +\textit{lease}. + +La notifica avviene in maniera analoga a come illustrato in precedenza per +l'uso di \const{O\_ASYNC}: di default viene inviato al \textit{lease holder} +il segnale \const{SIGIO}, ma questo segnale può essere modificato usando il +comando \const{F\_SETSIG} di \func{fcntl}.\footnote{anche in questo caso si + può rispecificare lo stesso \const{SIGIO}.} Se si è fatto questo\footnote{è + in genere è opportuno farlo, come in precedenza, per utilizzare segnali + real-time.} e si è installato il manipolatore del segnale con +\const{SA\_SIGINFO} si riceverà nel campo \var{si\_fd} della struttura +\struct{siginfo\_t} il valore del file descriptor del file sul quale è stato +compiuto l'accesso; in questo modo un processo può mantenere anche più di un +\textit{file lease}. + +Esistono due tipi di \textit{file lease}: di lettura (\textit{read lease}) e +di scrittura (\textit{write lease}). Nel primo caso la notifica avviene quando +un altro processo esegue l'apertura del file in scrittura o usa +\func{truncate} per troncarlo. Nel secondo caso la notifica avviene anche se +il file viene aperto il lettura; in quest'ultimo caso però il \textit{lease} +può essere ottenuto solo se nessun altro processo ha aperto lo stesso file. + +Come accennato in sez.~\ref{sec:file_fcntl} il comando di \func{fcntl} che +consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che viene +utilizzato anche per rilasciarlo. In tal caso il file descriptor \param{fd} +passato a \func{fcntl} servirà come riferimento per il file su cui si vuole +operare, mentre per indicare il tipo di operazione (acquisizione o rilascio) +occorrerà specificare come valore dell'argomento \param{arg} di \func{fcntl} +uno dei tre valori di tab.~\ref{tab:file_lease_fctnl}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{F\_RDLCK} & Richiede un \textit{read lease}.\\ + \const{F\_WRLCK} & Richiede un \textit{write lease}.\\ + \const{F\_UNLCK} & Rilascia un \textit{file lease}.\\ + \hline + \end{tabular} + \caption{Costanti per i tre possibili valori dell'argomento \param{arg} di + \func{fcntl} quando usata con i comandi \const{F\_SETLEASE} e + \const{F\_GETLEASE}.} + \label{tab:file_lease_fctnl} +\end{table} + +Se invece si vuole conoscere lo stato di eventuali \textit{file lease} +occorrerà chiamare \func{fcntl} sul relativo file descriptor \param{fd} con il +comando \const{F\_GETLEASE}, e si otterrà indietro nell'argomento \param{arg} +uno dei valori di tab.~\ref{tab:file_lease_fctnl}, che indicheranno la +presenza del rispettivo tipo di \textit{lease}, o, nel caso di +\const{F\_UNLCK}, l'assenza di qualunque \textit{file lease}. + +Si tenga presente che un processo può mantenere solo un tipo di \textit{lease} +su un file, e che un \textit{lease} può essere ottenuto solo su file di dati +(pipe e dispositivi sono quindi esclusi). Inoltre un processo non privilegiato +può ottenere un \textit{lease} soltanto per un file appartenente ad un +\acr{uid} corrispondente a quello del processo. Soltanto un processo con +privilegi di amministratore (cioè con la \itindex{capabilities} capability +\const{CAP\_LEASE}) può acquisire \textit{lease} su qualunque file. + +Se su un file è presente un \textit{lease} quando il \textit{lease breaker} +esegue una \func{truncate} o una \func{open} che confligge con +esso,\footnote{in realtà \func{truncate} confligge sempre, mentre \func{open}, + se eseguita in sola lettura, non confligge se si tratta di un \textit{read + lease}.} la funzione si blocca\footnote{a meno di non avere aperto il file + con \const{O\_NONBLOCK}, nel qual caso \func{open} fallirebbe con un errore + di \errcode{EWOULDBLOCK}.} e viene eseguita la notifica al \textit{lease + holder}, così che questo possa completare le sue operazioni sul file e +rilasciare il \textit{lease}. In sostanza con un \textit{read lease} si +rilevano i tentativi di accedere al file per modificarne i dati da parte di un +altro processo, mentre con un \textit{write lease} si rilevano anche i +tentativi di accesso in lettura. Si noti comunque che le operazioni di +notifica avvengono solo in fase di apertura del file e non sulle singole +operazioni di lettura e scrittura. + +L'utilizzo dei \textit{file lease} consente al \textit{lease holder} di +assicurare la consistenza di un file, a seconda dei due casi, prima che un +altro processo inizi con le sue operazioni di scrittura o di lettura su di +esso. In genere un \textit{lease holder} che riceve una notifica deve +provvedere a completare le necessarie operazioni (ad esempio scaricare +eventuali buffer), per poi rilasciare il \textit{lease} così che il +\textit{lease breaker} possa eseguire le sue operazioni. Questo si fa con il +comando \const{F\_SETLEASE}, o rimuovendo il \textit{lease} con +\const{F\_UNLCK}, o, nel caso di \textit{write lease} che confligge con una +operazione di lettura, declassando il \textit{lease} a lettura con +\const{F\_RDLCK}. + +Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro +il numero di secondi specificato dal parametro di sistema mantenuto in +\file{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o +declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per + evitare che un processo blocchi indefinitamente l'accesso ad un file + acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato +rilasciato o declassato (che questo sia fatto dal \textit{lease holder} o dal +kernel è lo stesso) le chiamate a \func{open} o \func{truncate} eseguite dal +\textit{lease breaker} rimaste bloccate proseguono automaticamente. + + +\index{file!notify|(} + +Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da +parte di più processi, l'uso dei \textit{file lease} non consente comunque di +risolvere il problema di rilevare automaticamente quando un file viene +modificato, che è quanto necessario ad esempio ai programma di gestione dei +file dei vari desktop grafici. + +Per risolvere questo problema è stata allora creata un'altra interfaccia che +consente di richiedere una notifica quando una directory, o di uno qualunque +dei file in essa contenuti, viene modificato. Come per i \textit{file lease} +la notifica avviene di default attraverso il segnale \const{SIGIO}, ma questo +può essere modificato e si può ottenere nel manipolatore il file descriptor +che è stato modificato dal contenuto della struttura \struct{siginfo\_t}. + +\index{file!lease|)} + +Ci si può registrare per le notifiche dei cambiamenti al contenuto di una +certa directory eseguendo \func{fcntl} su un file descriptor \param{fd} +associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso +l'argomento \param{arg} serve ad indicare per quali classi eventi si vuole +ricevere la notifica, e prende come valore una maschera binaria composta +dall'OR aritmetico di una o più delle costanti riportate in +tab.~\ref{tab:file_notify}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{DN\_ACCESS} & Un file è stato acceduto, con l'esecuzione di una fra + \func{read}, \func{pread}, \func{readv}.\\ + \const{DN\_MODIFY} & Un file è stato modificato, con l'esecuzione di una + fra \func{write}, \func{pwrite}, \func{writev}, + \func{truncate}, \func{ftruncate}.\\ + \const{DN\_CREATE} & È stato creato un file nella directory, con + l'esecuzione di una fra \func{open}, \func{creat}, + \func{mknod}, \func{mkdir}, \func{link}, + \func{symlink}, \func{rename} (da un'altra + directory).\\ + \const{DN\_DELETE} & È stato cancellato un file dalla directory con + l'esecuzione di una fra \func{unlink}, \func{rename} + (su un'altra directory), \func{rmdir}.\\ + \const{DN\_RENAME} & È stato rinominato un file all'interno della + directory (con \func{rename}).\\ + \const{DN\_ATTRIB} & È stato modificato un attributo di un file con + l'esecuzione di una fra \func{chown}, \func{chmod}, + \func{utime}.\\ + \const{DN\_MULTISHOT}& richiede una notifica permanente di tutti gli + eventi.\\ + \hline + \end{tabular} + \caption{Le costanti che identificano le varie classi di eventi per i quali + si richiede la notifica con il comando \const{F\_NOTIFY} di \func{fcntl}.} + \label{tab:file_notify} +\end{table} + +A meno di non impostare in maniera esplicita una notifica permanente usando +\const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una sola +volta quando si verifica uno qualunque fra gli eventi per i quali la si è +richiesta. Questo significa che un programma deve registrarsi un'altra volta se +desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse +chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi +ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi +specificate in chiamate successive vengono aggiunte a quelle già impostate +nelle precedenti. Se si vuole rimuovere la notifica si deve invece +specificare un valore nullo. + +\index{file!notify|)} + + + + + + + + + +% TODO inserire anche inotify + + \subsection{L'interfaccia POSIX per l'I/O asincrono} \label{sec:file_asyncronous_io} @@ -554,11 +792,11 @@ usate normalmente. In generale questa interfaccia è completamente astratta e può essere implementata sia direttamente nel kernel, che in user space attraverso l'uso -di thread. Al momento esiste una sola versione stabile di questa interfaccia, -quella delle \acr{glibc}, che è realizzata completamente in user space, ed -accessibile linkando i programmi con la libreria \file{librt}. Nei kernel -della nuova serie è stato anche introdotta (a partire dal 2.5.32) un nuovo -layer per l'I/O asincrono. +di thread. Per le versioni del kernel meno recenti esiste una implementazione +di questa interfaccia fornita delle \acr{glibc}, che è realizzata +completamente in user space, ed è accessibile linkando i programmi con la +libreria \file{librt}. Nelle versioni più recenti (a partire dalla 2.5.32) è +stato introdotto direttamente nel kernel un nuovo layer per l'I/O asincrono. Lo standard prevede che tutte le operazioni di I/O asincrono siano controllate attraverso l'uso di una apposita struttura \struct{aiocb} (il cui nome sta per @@ -1149,9 +1387,10 @@ tab.~\ref{tab:file_mmap_flag}. vengano riportati sulla regione mappata. Incompatibile con \const{MAP\_SHARED}. \\ \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare - \textit{DoS}\index{DoS} (veniva usato per - segnalare che tentativi di scrittura sul file - dovevano fallire con \errcode{ETXTBSY}).\\ + \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 @@ -1193,7 +1432,7 @@ 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 basato sul meccanismo della memoria +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 @@ -1507,7 +1746,7 @@ fig.~\ref{fig:file_mmap_layout}. Quando un processo esegue un gran numero di mappature diverse\footnote{si può arrivare anche a centinaia di migliaia.} per realizzare a mano una mappatura -non-linare si avrà un accrescimento eccessivo della sua \itindex{page~table} +non-lineare si avrà un accrescimento eccessivo della sua \itindex{page~table} \textit{page table}, e lo stesso accadrà per tutti gli altri processi che utilizzano questa tecnica. In situazioni in cui le applicazioni hanno queste esigenze si avranno delle prestazioni ridotte, dato che il kernel dovrà @@ -1584,7 +1823,7 @@ mappatura vengono ``\textsl{popolate}'' in una sola volta, questo comportamento viene abilitato quando si usa con \func{mmap} il flag \const{MAP\_POPULATE}. -Dato che l'uso di \const{MAP\_POPULATE} comporta dell'l'I/O su disco che può +Dato che l'uso di \const{MAP\_POPULATE} comporta dell'I/O su disco che può rallentare l'esecuzione di \func{mmap} è stato introdotto anche un secondo flag, \const{MAP\_NONBLOCK}, che esegue un \itindex{prefaulting} \textit{prefaulting} più limitato in cui vengono popolate solo le pagine della @@ -1598,8 +1837,15 @@ mappatura che gi % i raw device %\subsection{I \textit{raw} device} %\label{sec:file_raw_device} +% +% TODO i raw device +%\subsection{L'utilizzo delle porte di I/O} +%\label{sec:file_io_port} +% +% TODO l'I/O sulle porte di I/O +% consultare le manpage di ioperm, iopl e outb \section{Il file locking} @@ -1634,7 +1880,7 @@ La prima modalit sistemi unix-like è quella che viene usualmente chiamata \textit{advisory locking},\footnote{Stevens in \cite{APUE} fa riferimento a questo argomento come al \textit{record locking}, dizione utilizzata anche dal manuale delle - \acr{glibc}; nelle pagine di manuale si parla di \textit{discretionary file + \acr{glibc}; nelle pagine di manuale si parla di \textit{discrectionary file lock} per \func{fcntl} e di \textit{advisory locking} per \func{flock}, mentre questo nome viene usato da Stevens per riferirsi al \textit{file locking} POSIX. Dato che la dizione \textit{record locking} è quantomeno @@ -1782,13 +2028,13 @@ anche se richiesto attraverso un file descriptor, agisce sempre su un file; perciò le informazioni relative agli eventuali \textit{file lock} sono mantenute a livello di inode\index{inode},\footnote{in particolare, come accennato in fig.~\ref{fig:file_flock_struct}, i \textit{file lock} sono - mantenuti un una \textit{linked~list} di strutture \struct{file\_lock}. La - lista è referenziata dall'indirizzo di partenza mantenuto dal campo - \var{i\_flock} della struttura \struct{inode} (per le definizioni esatte si - faccia riferimento al file \file{fs.h} nei sorgenti del kernel). Un bit del - campo \var{fl\_flags} di specifica se si tratta di un lock in semantica BSD - (\const{FL\_FLOCK}) o POSIX (\const{FL\_POSIX}).} \itindex{linked~list} dato -che questo è l'unico riferimento in comune che possono avere due processi + mantenuti in una \itindex{linked~list} \textit{linked list} di strutture + \struct{file\_lock}. La lista è referenziata dall'indirizzo di partenza + mantenuto dal campo \var{i\_flock} della struttura \struct{inode} (per le + definizioni esatte si faccia riferimento al file \file{fs.h} nei sorgenti + del kernel). Un bit del campo \var{fl\_flags} di specifica se si tratta di + un lock in semantica BSD (\const{FL\_FLOCK}) o POSIX (\const{FL\_POSIX}).} +dato che questo è l'unico riferimento in comune che possono avere due processi diversi che aprono lo stesso file. \begin{figure}[htb] @@ -2063,7 +2309,7 @@ lock relativi al file cui esso faceva riferimento, anche se questi fossero stati creati usando altri file descriptor che restano aperti. Dato che il controllo sull'accesso ai lock viene eseguito sulla base del -\acr{pid} del processo, possiamo anche prendere in considerazione un'altro +\acr{pid} del processo, possiamo anche prendere in considerazione un altro degli aspetti meno chiari di questa interfaccia e cioè cosa succede quando si richiedono dei lock su regioni che si sovrappongono fra loro all'interno stesso processo. Siccome il controllo, come nel caso della rimozione, si basa @@ -2358,32 +2604,33 @@ direttamente al sistema, cos opportune verifiche nei processi, questo verrebbe comunque rispettato. Per poter utilizzare il \textit{mandatory locking} è stato introdotto un -utilizzo particolare del bit \acr{sgid}. Se si ricorda quanto esposto in -sez.~\ref{sec:file_suid_sgid}), esso viene di norma utilizzato per cambiare il -group-ID effettivo con cui viene eseguito un programma, ed è pertanto sempre -associato alla presenza del permesso di esecuzione per il gruppo. Impostando -questo bit su un file senza permesso di esecuzione in un sistema che supporta -il \textit{mandatory locking}, fa sì che quest'ultimo venga attivato per il -file in questione. In questo modo una combinazione dei permessi -originariamente non contemplata, in quanto senza significato, diventa -l'indicazione della presenza o meno del \textit{mandatory +utilizzo particolare del bit \itindex{sgid~bit} \acr{sgid}. Se si ricorda +quanto esposto in sez.~\ref{sec:file_suid_sgid}), esso viene di norma +utilizzato per cambiare il group-ID effettivo con cui viene eseguito un +programma, ed è pertanto sempre associato alla presenza del permesso di +esecuzione per il gruppo. Impostando questo bit su un file senza permesso di +esecuzione in un sistema che supporta il \textit{mandatory locking}, fa sì che +quest'ultimo venga attivato per il file in questione. In questo modo una +combinazione dei permessi originariamente non contemplata, in quanto senza +significato, diventa l'indicazione della presenza o meno del \textit{mandatory locking}.\footnote{un lettore attento potrebbe ricordare quanto detto in - sez.~\ref{sec:file_chmod} e cioè che il bit \acr{sgid} viene cancellato (come - misura di sicurezza) quando di scrive su un file, questo non vale quando - esso viene utilizzato per attivare il \textit{mandatory locking}.} + sez.~\ref{sec:file_chmod} e cioè che il bit \acr{sgid} viene cancellato + (come misura di sicurezza) quando di scrive su un file, questo non vale + quando esso viene utilizzato per attivare il \textit{mandatory locking}.} L'uso del \textit{mandatory locking} presenta vari aspetti delicati, dato che neanche root può passare sopra ad un lock; pertanto un processo che blocchi un file cruciale può renderlo completamente inaccessibile, rendendo completamente inutilizzabile il sistema\footnote{il problema si potrebbe risolvere - rimuovendo il bit \acr{sgid}, ma non è detto che sia così facile fare questa - operazione con un sistema bloccato.} inoltre con il \textit{mandatory - locking} si può bloccare completamente un server NFS richiedendo una lettura -su un file su cui è attivo un lock. Per questo motivo l'abilitazione del -mandatory locking è di norma disabilitata, e deve essere attivata filesystem -per filesystem in fase di montaggio (specificando l'apposita opzione di -\func{mount} riportata in tab.~\ref{tab:sys_mount_flags}, o con l'opzione -\cmd{mand} per il comando). + rimuovendo il bit \itindex{sgid~bit} \acr{sgid}, ma non è detto che sia così + facile fare questa operazione con un sistema bloccato.} inoltre con il +\textit{mandatory locking} si può bloccare completamente un server NFS +richiedendo una lettura su un file su cui è attivo un lock. Per questo motivo +l'abilitazione del mandatory locking è di norma disabilitata, e deve essere +attivata filesystem per filesystem in fase di montaggio (specificando +l'apposita opzione di \func{mount} riportata in +tab.~\ref{tab:sys_mount_flags}, o con l'opzione \code{-o mand} per il comando +omonimo). Si tenga presente inoltre che il \textit{mandatory locking} funziona solo sull'interfaccia POSIX di \func{fcntl}. Questo ha due conseguenze: che non si diff --git a/filedir.tex b/filedir.tex index e492235..1912e1d 100644 --- a/filedir.tex +++ b/filedir.tex @@ -164,10 +164,10 @@ Per cancellare una voce in una directory scrittura su di essa, dato che si va a rimuovere una voce dal suo contenuto, e il diritto di esecuzione sulla directory che la contiene (affronteremo in dettaglio l'argomento dei permessi di file e directory in -sez.~\ref{sec:file_access_control}). Se inoltre lo \textit{sticky} bit (vedi -sez.~\ref{sec:file_sticky}) è impostato occorrerà anche essere proprietari del -file o proprietari della directory (o root, per cui nessuna delle restrizioni -è applicata). +sez.~\ref{sec:file_access_control}). Se inoltre lo +\itindex{sticky~bit}\textit{sticky bit} (vedi sez.~\ref{sec:file_sticky}) è +impostato occorrerà anche essere proprietari del file o proprietari della +directory (o root, per cui nessuna delle restrizioni è applicata). Una delle caratteristiche di queste funzioni è che la creazione/rimozione del nome dalla directory e l'incremento/decremento del numero di riferimenti @@ -183,11 +183,11 @@ 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 file aperti nei vari processi, che a sua volta contiene i riferimenti agli - inode ad essi relativi. Prima di procedere alla cancellazione dello spazio - occupato su disco dal contenuto di un file il kernel controlla anche questa - tabella, per verificare che anche in essa non ci sia più nessun riferimento - all'inode in questione.} e cioè che non ci siano processi che abbiano il -suddetto file aperto). + \index{inode} inode ad essi relativi. Prima di procedere alla cancellazione + dello spazio occupato su disco dal contenuto di un file il kernel controlla + anche questa tabella, per verificare che anche in essa non ci sia più nessun + riferimento all'inode in questione.} e cioè che non ci siano processi che +abbiano il suddetto file aperto). Questa proprietà viene spesso usata per essere sicuri di non lasciare file temporanei su disco in caso di crash dei programmi; la tecnica è quella di @@ -307,7 +307,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 inode\index{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. @@ -485,11 +485,12 @@ 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 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.} La funzione usata -per creare una directory è \funcd{mkdir}, ed il suo prototipo è: +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.} +La funzione usata per creare una directory è \funcd{mkdir}, ed il suo +prototipo è: \begin{functions} \headdecl{sys/stat.h} \headdecl{sys/types.h} @@ -540,9 +541,9 @@ prototipo errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} \item[\errcode{EPERM}] Il filesystem non supporta la cancellazione di - directory, oppure la directory che contiene \param{dirname} ha lo sticky - bit impostato e l'user-ID effettivo del processo non corrisponde al - proprietario della directory. + directory, oppure la directory che contiene \param{dirname} ha lo + \itindex{sticky~bit} \textit{sticky bit} impostato e l'user-ID effettivo + del processo non corrisponde al proprietario della directory. \item[\errcode{EACCES}] Non c'è il permesso di scrittura per la directory che contiene la directory che si vuole cancellare, o non c'è il permesso di attraversare (esecuzione) una delle directory specificate in @@ -659,11 +660,12 @@ 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 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 processo a -inserirvi direttamente delle voci con le usuali funzioni di scrittura. +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 +processo a inserirvi direttamente delle voci con le usuali funzioni di +scrittura. Ma se la scrittura e l'aggiornamento dei dati delle directory è compito del kernel, sono molte le situazioni in cui i processi necessitano di poterne @@ -782,8 +784,8 @@ 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 -inode cui il file è associato (di solito corrisponde al campo \var{st\_ino} di -\struct{stat}). +\index{inode}inode cui il file è associato (di solito corrisponde al campo +\var{st\_ino} di \struct{stat}). \begin{figure}[!htb] \footnotesize \centering @@ -1201,8 +1203,8 @@ directory per il file temporaneo (verificando che esista e sia accessibili), la prima valida delle seguenti: \begin{itemize*} \item La variabile di ambiente \const{TMPNAME} (non ha effetto se non è - definita o se il programma chiamante è \acr{suid} o \acr{sgid}, vedi - sez.~\ref{sec:file_suid_sgid}). + definita o se il programma chiamante è \itindex{suid~bit} \acr{suid} o + \itindex{sgid~bit} \acr{sgid}, vedi sez.~\ref{sec:file_suid_sgid}). \item il valore dell'argomento \param{dir} (se diverso da \val{NULL}). \item Il valore della costante \const{P\_tmpdir}. \item la directory \file{/tmp}. @@ -1244,7 +1246,7 @@ 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 modificano una stringa di input che serve da modello e che deve essere conclusa da 6 caratteri \code{X} che verranno sostituiti da un codice -unico. La prima delle due è analoga a \funcd{tmpnam} e genera un nome casuale, +unico. La prima delle due è analoga a \func{tmpnam} e genera un nome casuale, il suo prototipo è: \begin{prototype}{stlib.h}{char *mktemp(char *template)} Genera un filename univoco sostituendo le \code{XXXXXX} finali di @@ -1449,9 +1451,9 @@ un'opportuna combinazione. \const{S\_IFCHR} & 0020000 & dispositivo a caratteri \\ \const{S\_IFIFO} & 0010000 & fifo \\ \hline - \const{S\_ISUID} & 0004000 & set UID bit \\ - \const{S\_ISGID} & 0002000 & set GID bit \\ - \const{S\_ISVTX} & 0001000 & sticky bit \\ + \const{S\_ISUID} & 0004000 & set UID bit \itindex{suid~bit} \\ + \const{S\_ISGID} & 0002000 & set GID bit \itindex{sgid~bit} \\ + \const{S\_ISVTX} & 0001000 & sticky bit \itindex{sticky~bit}\\ \hline % \const{S\_IRWXU} & 00700 & bitmask per i permessi del proprietario \\ \const{S\_IRUSR} & 00400 & il proprietario ha permesso di lettura \\ @@ -1819,9 +1821,10 @@ rispettivamente al proprietario, al gruppo, a tutti gli altri. \label{fig:file_perm_bit} \end{figure} -I restanti tre bit (noti come \acr{suid}, \acr{sgid}, e \textsl{sticky}) sono -usati per indicare alcune caratteristiche più complesse del meccanismo del -controllo di accesso su cui torneremo in seguito (in +I restanti tre bit (noti come \itindex{suid~bit}\textit{suid bit}, +\itindex{sgid~bit}\textit{sgid bit}, e \itindex{sticky~bit} \textit{sticky + bit}) sono usati per indicare alcune caratteristiche più complesse del +meccanismo del controllo di accesso su cui torneremo in seguito (in sez.~\ref{sec:file_suid_sgid} e sez.~\ref{sec:file_sticky}); lo schema di allocazione dei bit è riportato in fig.~\ref{fig:file_perm_bit}. @@ -1912,8 +1915,8 @@ fa riferimento; per questo in genere il comando \cmd{ls} riporta per un link simbolico tutti i permessi come concessi; utente e gruppo a cui esso appartiene vengono pure ignorati quando il link viene risolto, vengono controllati solo quando viene richiesta la rimozione del link e quest'ultimo è -in una directory con lo \textsl{sticky bit} impostato (si veda -sez.~\ref{sec:file_sticky}). +in una directory con lo \itindex{sticky~bit} \textit{sticky bit} impostato (si +veda sez.~\ref{sec:file_sticky}). La procedura con cui il kernel stabilisce se un processo possiede un certo permesso (di lettura, scrittura o esecuzione) si basa sul confronto fra @@ -1972,6 +1975,9 @@ tutti gli altri non vengono controllati. \subsection{I bit \acr{suid} e \acr{sgid}} \label{sec:file_suid_sgid} +\itindbeg{suid~bit} +\itindbeg{sgid~bit} + Come si è accennato (in sez.~\ref{sec:file_perm_overview}) nei dodici bit del campo \var{st\_mode} di \struct{stat} che vengono usati per il controllo di accesso oltre ai bit dei permessi veri e propri, ci sono altri tre bit che @@ -2029,24 +2035,28 @@ sia anche il corrispondente bit di esecuzione viene utilizzato per attivare per quel file il \textit{mandatory locking} (affronteremo questo argomento in dettaglio più avanti, in sez.~\ref{sec:file_mand_locking}). +\itindend{suid~bit} +\itindend{sgid~bit} \subsection{Il bit \textsl{sticky}} \label{sec:file_sticky} +\itindbeg{sticky~bit} + L'ultimo dei bit rimanenti, identificato dalla costante \const{S\_ISVTX}, è in parte un rimasuglio delle origini dei sistemi Unix. A quell'epoca infatti la memoria virtuale e l'accesso ai files erano molto meno sofisticati e per ottenere la massima velocità possibile per i programmi usati più comunemente si poteva impostare questo bit. -L'effetto di questo bit era che il segmento di testo del programma (si veda -sez.~\ref{sec:proc_mem_layout} per i dettagli) veniva scritto nella swap la -prima volta che questo veniva lanciato, e vi permaneva fino al riavvio della -macchina (da questo il nome di \textsl{sticky bit}); essendo la swap un file -continuo o una partizione indicizzata direttamente si poteva risparmiare in -tempo di caricamento rispetto alla ricerca attraverso la struttura del -filesystem. Lo \textsl{sticky bit} è indicato usando la lettera \cmd{t} al -posto della \cmd{x} nei permessi per gli altri. +L'effetto di questo bit era che il \index{segmento!testo} segmento di testo +del programma (si veda sez.~\ref{sec:proc_mem_layout} per i dettagli) veniva +scritto nella swap la prima volta che questo veniva lanciato, e vi permaneva +fino al riavvio della macchina (da questo il nome di \textsl{sticky bit}); +essendo la swap un file continuo o una partizione indicizzata direttamente si +poteva risparmiare in tempo di caricamento rispetto alla ricerca attraverso la +struttura del filesystem. Lo \textsl{sticky bit} è indicato usando la lettera +\texttt{t} al posto della \texttt{x} nei permessi per gli altri. Ovviamente per evitare che gli utenti potessero intasare la swap solo l'amministratore era in grado di impostare questo bit, che venne chiamato @@ -2054,8 +2064,8 @@ anche con il nome di \textit{saved text bit}, da cui deriva quello della costante. Le attuali implementazioni di memoria virtuale e filesystem rendono sostanzialmente inutile questo procedimento. -Benché ormai non venga più utilizzato per i file, lo \textsl{sticky bit} ha -invece assunto un uso importante per le directory;\footnote{lo \textsl{sticky +Benché ormai non venga più utilizzato per i file, lo \textit{sticky bit} ha +invece assunto un uso importante per le directory;\footnote{lo \textit{sticky bit} per le directory è un'estensione non definita nello standard POSIX, Linux però la supporta, così come BSD e SVr4.} in questo caso se tale bit è impostato un file potrà essere rimosso dalla directory soltanto se l'utente ha @@ -2072,13 +2082,15 @@ permessi infatti di solito sono i seguenti: $ ls -ld /tmp drwxrwxrwt 6 root root 1024 Aug 10 01:03 /tmp \end{verbatim}%$ -quindi con lo \textsl{sticky bit} bit impostato. In questo modo qualunque +quindi con lo \textit{sticky bit} bit impostato. In questo modo qualunque utente nel sistema può creare dei file in questa directory (che, come suggerisce il nome, è normalmente utilizzata per la creazione di file temporanei), ma solo l'utente che ha creato un certo file potrà cancellarlo o rinominarlo. In questo modo si evita che un utente possa, più o meno consapevolmente, cancellare i file temporanei creati degli altri utenti. +\itindend{sticky~bit} + \subsection{La titolarità di nuovi file e directory} \label{sec:file_ownership} @@ -2184,8 +2196,8 @@ contrario (o di errore) ritorna -1. Un esempio tipico per l'uso di questa funzione è quello di un processo che sta eseguendo un programma coi privilegi di un altro utente (ad esempio attraverso -l'uso del \acr{suid} bit) che vuole controllare se l'utente originale ha i -permessi per accedere ad un certo file. +l'uso del \itindex{suid~bit} \textit{suid bit}) che vuole controllare se +l'utente originale ha i permessi per accedere ad un certo file. \subsection{Le funzioni \func{chmod} e \func{fchmod}} @@ -2229,9 +2241,9 @@ file. \textbf{\param{mode}} & \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{S\_ISUID} & 04000 & set user ID \\ - \const{S\_ISGID} & 02000 & set group ID \\ - \const{S\_ISVTX} & 01000 & sticky bit \\ + \const{S\_ISUID} & 04000 & set user ID \itindex{suid~bit} \\ + \const{S\_ISGID} & 02000 & set group ID \itindex{sgid~bit}\\ + \const{S\_ISVTX} & 01000 & sticky bit \itindex{sticky~bit}\\ \hline \const{S\_IRWXU} & 00700 & l'utente ha tutti i permessi \\ \const{S\_IRUSR} & 00400 & l'utente ha il permesso di lettura \\ @@ -2267,7 +2279,7 @@ Ad esempio i permessi standard assegnati ai nuovi file (lettura e scrittura per il proprietario, sola lettura per il gruppo e gli altri) sono corrispondenti al valore ottale $0644$, un programma invece avrebbe anche il bit di esecuzione attivo, con un valore di $0755$, se si volesse attivare il -bit \acr{suid} il valore da fornire sarebbe $4755$. +bit \itindex{suid~bit} \acr{suid} il valore da fornire sarebbe $4755$. Il cambiamento dei permessi di un file eseguito attraverso queste funzioni ha comunque alcune limitazioni, previste per motivi di sicurezza. L'uso delle @@ -2280,28 +2292,30 @@ limitazioni ulteriori. Per questo motivo, anche se si non tutti i valori possibili di \param{mode} sono permessi o hanno effetto; in particolare accade che: \begin{enumerate} -\item siccome solo l'amministratore può impostare lo \textit{sticky bit}, se - l'user-ID effettivo del processo non è zero esso viene automaticamente - cancellato (senza notifica di errore) qualora sia stato indicato in - \param{mode}. +\item siccome solo l'amministratore può impostare lo \itindex{sticky~bit} + \textit{sticky bit}, se l'user-ID effettivo del processo non è zero esso + viene automaticamente cancellato (senza notifica di errore) qualora sia + stato indicato in \param{mode}. \item per quanto detto in sez.~\ref{sec:file_ownership} riguardo la creazione dei nuovi file, si può avere il caso in cui il file creato da un processo è assegnato a un gruppo per il quale il processo non ha privilegi. Per evitare - che si possa assegnare il bit \acr{sgid} ad un file appartenente a un gruppo - per cui non si hanno diritti, questo viene automaticamente cancellato da - \param{mode} (senza notifica di errore) qualora il gruppo del file non - corrisponda a quelli associati al processo (la cosa non avviene quando - l'user-ID effettivo del processo è zero). + che si possa assegnare il bit \itindex{sgid~bit} \acr{sgid} ad un file + appartenente a un gruppo per cui non si hanno diritti, questo viene + automaticamente cancellato da \param{mode} (senza notifica di errore) + qualora il gruppo del file non corrisponda a quelli associati al processo + (la cosa non avviene quando l'user-ID effettivo del processo è zero). \end{enumerate} -Per alcuni filesystem\footnote{il filesystem \acr{ext2} supporta questa - caratteristica, che è mutuata da BSD.} è inoltre prevista una ulteriore -misura di sicurezza, volta a scongiurare l'abuso dei bit \acr{suid} e -\acr{sgid}; essa consiste nel cancellare automaticamente questi bit dai -permessi di un file qualora un processo che non appartenga all'amministratore -effettui una scrittura. In questo modo anche se un utente malizioso scopre un -file \acr{suid} su cui può scrivere, un'eventuale modifica comporterà la -perdita di questo privilegio. +Per alcuni filesystem\footnote{i filesystem più comuni (\textsl{ext2}, + \textsl{ext3}, \textsl{reiser}) supportano questa caratteristica, che è + mutuata da BSD.} è inoltre prevista una ulteriore misura di sicurezza, volta +a scongiurare l'abuso dei \itindex{suid~bit} bit \acr{suid} e \acr{sgid}; essa +consiste nel cancellare automaticamente questi bit dai permessi di un file +qualora un processo che non appartenga all'amministratore\footnote{per la + precisione un processo che non dispone della capability + \const{CAP\_FSETID}.} effettui una scrittura. In questo modo anche se un +utente malizioso scopre un file \acr{suid} su cui può scrivere, un'eventuale +modifica comporterà la perdita di questo privilegio. \subsection{La funzione \func{umask}} \label{sec:file_umask} @@ -2377,12 +2391,13 @@ sono: \errval{EACCES}, \errval{ELOOP}; \func{fchown} anche \errval{EBADF}.} \end{functions} -In Linux soltanto l'amministratore può cambiare il proprietario di un file, -seguendo la semantica di BSD che non consente agli utenti di assegnare i loro -file ad altri (per evitare eventuali aggiramenti delle quote). -L'amministratore può cambiare il gruppo di un file, il proprietario può -cambiare il gruppo dei file che gli appartengono solo se il nuovo gruppo è il -suo gruppo primario o uno dei gruppi a cui appartiene. +In Linux soltanto l'amministratore (in sostanza un processo con la +\itindex{capabilities} capability \const{CAP\_CHOWN}) può cambiare il +proprietario di un file, seguendo la semantica di BSD che non consente agli +utenti di assegnare i loro file ad altri (per evitare eventuali aggiramenti +delle quote). L'amministratore può cambiare il gruppo di un file, il +proprietario può cambiare il gruppo dei file che gli appartengono solo se il +nuovo gruppo è il suo gruppo primario o uno dei gruppi di cui fa parte. La funzione \func{chown} segue i link simbolici, per operare direttamente su un link simbolico si deve usare la funzione \func{lchown}.\footnote{fino alla @@ -2395,16 +2410,11 @@ Un'altra estensione rispetto allo standard POSIX valore per \param{owner} e \param{group} i valori restano immutati. Quando queste funzioni sono chiamate con successo da un processo senza i -privilegi di root entrambi i bit \acr{suid} e \acr{sgid} vengono -cancellati. Questo non avviene per il bit \acr{sgid} nel caso in cui esso -sia usato (in assenza del corrispondente permesso di esecuzione) per indicare -che per il file è attivo il \textit{mandatory locking}. - -%La struttura fondamentale che contiene i dati essenziali relativi ai file è il -%cosiddetto \textit{inode}; questo conterrà informazioni come il -%tipo di file (file di dispositivo, directory, file di dati, per un elenco -%completo vedi \ntab), i permessi (vedi sez.~\ref{sec:file_perms}), le date (vedi -%sez.~\ref{sec:file_times}). +privilegi di root entrambi i bit \itindex{suid~bit} \acr{suid} e +\itindex{sgid~bit} \acr{sgid} vengono cancellati. Questo non avviene per il +bit \acr{sgid} nel caso in cui esso sia usato (in assenza del corrispondente +permesso di esecuzione) per indicare che per il file è attivo il +\textit{mandatory locking}. \subsection{Un quadro d'insieme sui permessi} @@ -2455,14 +2465,16 @@ ha alcun effetto qualora il processo possieda i privilegi di amministratore. \label{tab:file_fileperm_bits} \end{table} -Per compattezza, nella tabella si sono specificati i bit di \acr{suid}, -\acr{sgid} e \acr{sticky} con la notazione illustrata anche in -fig.~\ref{fig:file_perm_bit}. +Per compattezza, nella tabella si sono specificati i bit di \itindex{suid~bit} +\textit{suid}, \itindex{sgid~bit} \textit{sgid} e \textit{sticky} +\itindex{sticky~bit} con la notazione illustrata anche in +fig.~\ref{fig:file_perm_bit}. In tab.~\ref{tab:file_dirperm_bits} si sono invece riassunti gli effetti dei vari bit dei permessi per una directory; anche in questo caso si sono -specificati i bit di \acr{suid}, \acr{sgid} e \acr{sticky} con la notazione -compatta illustrata in fig.~\ref{fig:file_perm_bit}. +specificati i bit di \itindex{suid~bit} \textit{suid}, \itindex{sgid~bit} +\textit{sgid} e \textit{sticky} \itindex{sticky~bit} con la notazione compatta +illustrata in fig.~\ref{fig:file_perm_bit}. \begin{table}[!htb] \centering diff --git a/fileintro.tex b/fileintro.tex index 3ac9475..6fea57d 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -43,7 +43,6 @@ Questo viene fatto strutturando l'informazione sul disco attraverso quello che si chiama un \textit{filesystem} (vedi sez.~\ref{sec:file_arch_func}), essa poi viene resa disponibile ai processi attraverso quello che viene chiamato il \textsl{montaggio} del \textit{filesystem}. -% (approfondiremo tutto ciò in sez.~\ref{sec:file_arch_func}). In questa sezione faremo una panoramica generica su come il sistema presenta i file ai processi, trattando l'organizzazione di file e directory, i tipi di @@ -302,12 +301,6 @@ portabilit \section{L'architettura della gestione dei file} \label{sec:file_arch_func} -%% Per capire fino in fondo le proprietà di file e directory in un sistema -%% unix-like ed il comportamento delle relative funzioni di manipolazione, -%% occorre una breve introduzione al funzionamento della gestione dei file da -%% parte del kernel e sugli oggetti su cui è basato un filesystem. In particolare -%% occorre tenere presente dov'è che si situa la divisione fondamentale fra -%% kernel space e user space che tracciavamo al cap.~\ref{cha:intro_unix}. In questa sezione esamineremo come viene implementato l'accesso ai file in Linux, come il kernel può gestire diversi tipi di filesystem, descrivendo @@ -315,21 +308,10 @@ 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}. -% in particolare si riprenderà, approfondendolo sul piano dell'uso nelle -% funzioni di libreria, il concetto di \textit{inode} di cui abbiamo brevemente -% accennato le caratteristiche (dal lato dell'implementazione nel kernel) in -% sez.~\ref{sec:file_vfs}. - \subsection{Il \textit{Virtual File System} di Linux} \label{sec:file_vfs} -% Questa sezione riporta informazioni sui dettagli di come il kernel gestisce i -% file. L'argomento è abbastanza ``esoterico'' e questa sezione può essere -% saltata ad una prima lettura; è bene però tenere presente che vengono -% introdotti qui alcuni termini che potranno comparire in seguito, come -% \textit{inode}, \textit{dentry}, \textit{dcache}. - \itindbeg{Virtual~File~System} In Linux il concetto di \textit{everything is a file} è stato implementato attraverso il \textit{Virtual File System} (da qui in avanti VFS) che è uno diff --git a/filestd.tex b/filestd.tex index ba27efa..3fde1d7 100644 --- a/filestd.tex +++ b/filestd.tex @@ -72,18 +72,19 @@ sez.~\ref{sec:file_access_control} per il controllo di accesso. \index{file!stream|)} -\subsection{Gli oggetti \ctyp{FILE}} +\subsection{Gli oggetti \type{FILE}} \label{sec:file_FILE} + Per ragioni storiche la struttura di dati che rappresenta uno stream è stata -chiamata \ctyp{FILE}, questi oggetti sono creati dalle funzioni di libreria e +chiamata \type{FILE}, questi oggetti sono creati dalle funzioni di libreria e contengono tutte le informazioni necessarie a gestire le operazioni sugli stream, come la posizione corrente, lo stato del buffer e degli indicatori di stato e di fine del file. Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare queste strutture (che sono dei \textsl{tipi opachi}\index{tipo!opaco}) ma -usare sempre puntatori del tipo \ctyp{FILE *} ottenuti dalla libreria stessa +usare sempre puntatori del tipo \texttt{FILE *} ottenuti dalla libreria stessa (tanto che in certi casi il termine di puntatore a file è diventato sinonimo di stream). Tutte le funzioni della libreria che operano sui file accettano come argomenti solo variabili di questo tipo, che diventa accessibile @@ -113,14 +114,13 @@ definiti nell'header \file{stdio.h} che sono: sullo schermo. \end{basedescript} -Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono -effettivamente tre variabili di tipo \ctyp{FILE *} che possono essere -usate come tutte le altre, ad esempio si può effettuare una redirezione -dell'output di un programma con il semplice codice: -\includecodesnip{listati/redir_stdout.c} -ma in altri sistemi queste variabili possono essere definite da macro, e -se si hanno problemi di portabilità e si vuole essere sicuri, diventa -opportuno usare la funzione \func{freopen}. +Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono effettivamente +tre variabili di tipo \type{FILE}\texttt{ *} che possono essere usate come +tutte le altre, ad esempio si può effettuare una redirezione dell'output di un +programma con il semplice codice: \includecodesnip{listati/redir_stdout.c} ma +in altri sistemi queste variabili possono essere definite da macro, e se si +hanno problemi di portabilità e si vuole essere sicuri, diventa opportuno +usare la funzione \func{freopen}. \subsection{Le modalità di bufferizzazione} @@ -422,7 +422,7 @@ funzionamento di \var{errno}). Per questo motivo tutte le implementazioni delle librerie standard mantengono per ogni stream almeno due flag all'interno dell'oggetto -\ctyp{FILE}, il flag di \textit{end-of-file}, che segnala che si è +\type{FILE}, il flag di \textit{end-of-file}, che segnala che si è raggiunta la fine del file in lettura, e quello di errore, che segnala la presenza di un qualche errore nelle operazioni di input/output; questi due flag possono essere riletti dalle funzioni \funcd{feof} e @@ -750,14 +750,13 @@ stringa letta superi le dimensioni del buffer, si avr 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 una stringa sufficientemente lunga ed opportunamente -forgiata per sovrascrivere gli indirizzi di ritorno nello stack -(supposto che la \func{gets} sia stata chiamata da una subroutine), in -modo da far ripartire l'esecuzione nel codice inviato nella stringa -stessa (in genere uno \textit{shell code} cioè una sezione di programma -che lancia una shell). +Questa è una delle vulnerabilità più sfruttate per guadagnare accessi non +autorizzati al sistema (i cosiddetti \textit{exploit}), basta infatti inviare +una stringa sufficientemente lunga ed opportunamente forgiata per +sovrascrivere gli indirizzi di ritorno nello \itindex{stack} stack (supposto +che la \func{gets} sia stata chiamata da una subroutine), in modo da far +ripartire l'esecuzione nel codice inviato nella stringa stessa (in genere uno +\textit{shell code} cioè una sezione di programma che lancia una shell). La funzione \func{fgets} non ha i precedenti problemi di \func{gets} in quanto prende in input la dimensione del buffer \param{size}, che non verrà mai diff --git a/fileunix.tex b/fileunix.tex index e59fd06..2d297ec 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -54,16 +54,16 @@ valore come argomento alle varie funzioni dell'interfaccia. Per capire come funziona il meccanismo occorre spiegare a grandi linee come il kernel gestisce l'interazione fra processi e file. Il kernel mantiene sempre -un elenco dei processi attivi nella cosiddetta \textit{process table} ed un -elenco dei file aperti nella \textit{file table}. - -La \textit{process table} è una tabella che contiene una voce per ciascun -processo attivo nel sistema. In Linux ciascuna voce è costituita da una -struttura di tipo \struct{task\_struct} nella quale sono raccolte tutte le -informazioni relative al processo; fra queste informazioni c'è anche il -puntatore ad una ulteriore struttura di tipo \struct{files\_struct}, in cui -sono contenute le informazioni relative ai file che il processo ha aperto, ed -in particolare: +un elenco dei processi attivi nella cosiddetta \itindex{process~table} +\textit{process table} ed un elenco dei file aperti nella \textit{file table}. + +La \itindex{process~table} \textit{process table} è una tabella che contiene +una voce per ciascun processo attivo nel sistema. In Linux ciascuna voce è +costituita da una struttura di tipo \struct{task\_struct} nella quale sono +raccolte tutte le informazioni relative al processo; fra queste informazioni +c'è anche il puntatore ad una ulteriore struttura di tipo +\struct{files\_struct}, in cui sono contenute le informazioni relative ai file +che il processo ha aperto, ed in particolare: \begin{itemize*} \item i flag relativi ai file descriptor. \item il numero di file aperti. @@ -199,9 +199,9 @@ un file descriptor, il suo prototipo \param{flags}, e, nel caso il file sia creato, con gli eventuali permessi specificati da \param{mode}. - \bodydesc{La funzione ritorna il file descriptor in caso di successo e -1 in - caso di errore. In questo caso la variabile \var{errno} assumerà uno dei - valori: + \bodydesc{La funzione ritorna il file descriptor in caso di successo e $-1$ + in caso di errore. In questo caso la variabile \var{errno} assumerà uno + dei valori: \begin{errlist} \item[\errcode{EEXIST}] \param{pathname} esiste e si è specificato \const{O\_CREAT} e \const{O\_EXCL}. @@ -226,10 +226,23 @@ un file descriptor, il suo prototipo \errval{EMFILE} e \errval{ENFILE}.} \end{functions} -La funzione apre il file, usando il primo file descriptor libero, e crea -l'opportuna voce (cioè la struttura \struct{file}) nella \textit{file table}. -Viene sempre restituito come valore di ritorno il file descriptor con il -valore più basso disponibile. + +La funzione apre il file usando il primo file descriptor libero, e crea +l'opportuna voce, cioè la struttura \struct{file}, nella \textit{file table} +del processo. Viene sempre restituito come valore di ritorno il file +descriptor con il valore più basso disponibile. + +\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 + 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.} \begin{table}[!htb] \centering @@ -239,122 +252,109 @@ valore pi \textbf{Flag} & \textbf{Descrizione} \\ \hline \hline % modalità di accesso al file - \const{O\_RDONLY} & apre il file in sola lettura, le \acr{glibc} - definiscono anche \const{O\_READ} come sinonimo. \\ - \const{O\_WRONLY} & apre il file in sola scrittura, le \acr{glibc} - definiscono anche \const{O\_WRITE} come sinonimo. \\ - \const{O\_RDWR} & apre il file sia in lettura che in scrittura. \\ + \const{O\_RDONLY} & Apre il file in sola lettura, le \acr{glibc} + definiscono anche \const{O\_READ} come sinonimo. \\ + \const{O\_WRONLY} & Apre il file in sola scrittura, le \acr{glibc} + definiscono anche \const{O\_WRITE} come sinonimo. \\ + \const{O\_RDWR} & Apre il file sia in lettura che in scrittura. \\ \hline % modalità di apertura del file \hline - \const{O\_CREAT} & se il file non esiste verrà creato, con le regole di - titolarità del file viste in - sez.~\ref{sec:file_ownership}. Con questa opzione - l'argomento \param{mode} deve essere specificato. \\ - \const{O\_EXCL} & usato in congiunzione con \const{O\_CREAT} fa sì che - la precedente esistenza del file diventi un - errore\protect\footnotemark\ che fa fallire - \func{open} con \errcode{EEXIST}. \\ - \const{O\_NONBLOCK}& apre il file in modalità non bloccante. Questo - valore specifica anche una modalità di operazione (vedi - sotto), e comporta che \func{open} ritorni - immediatamente (l'opzione ha senso solo per le fifo, - torneremo questo in sez.~\ref{sec:ipc_named_pipe}). \\ - \const{O\_NOCTTY}& se \param{pathname} si riferisce ad un dispositivo di - terminale, questo non diventerà il terminale di - controllo, anche se il processo non ne ha ancora uno - (si veda sez.~\ref{sec:sess_ctrl_term}). \\ - \const{O\_SHLOCK} & opzione di BSD, acquisisce uno shared lock (vedi - sez.~\ref{sec:file_locking}) sul file. Non è - disponibile in Linux. \\ - \const{O\_EXLOCK} & opzione di BSD, acquisisce uno lock esclusivo (vedi - sez.~\ref{sec:file_locking}) sul file. Non è - disponibile in Linux. \\ - \const{O\_TRUNC} & se il file esiste ed è un file di dati e la modalità di - apertura consente la scrittura, allora la sua - lunghezza verrà troncata a zero. Se il file è un - terminale o una fifo il flag verrà ignorato, negli - altri casi il comportamento non è specificato. \\ - \const{O\_NOFOLLOW}&se \param{pathname} è un link simbolico la chiamata - fallisce. Questa è un'estensione BSD aggiunta in Linux - dal kernel 2.1.126. Nelle versioni precedenti i link - simbolici sono sempre seguiti, e questa opzione è - ignorata. \\ - \const{O\_DIRECTORY}& se \param{pathname} non è una directory la chiamata - fallisce. Questo flag è specifico di Linux ed è stato - introdotto con il kernel 2.1.126 per evitare dei - \textit{DoS}\index{DoS}\protect\footnotemark\ quando - \func{opendir} viene chiamata su una fifo o su un - device di unità a nastri, non deve essere utilizzato - al di fuori dell'implementazione di \func{opendir}. \\ - \const{O\_LARGEFILE}& nel caso di sistemi a 32 bit che supportano file di - grandi dimensioni consente di aprire file le cui - dimensioni non possono essere rappresentate da numeri - a 31 bit. \\ + \const{O\_CREAT} & Se il file non esiste verrà creato, con le regole di + titolarità del file viste in + sez.~\ref{sec:file_ownership}. Con questa opzione + l'argomento \param{mode} deve essere specificato. \\ + \const{O\_EXCL} & Usato in congiunzione con \const{O\_CREAT} fa sì che + la precedente esistenza del file diventi un + errore\protect\footnotemark\ che fa fallire + \func{open} con \errcode{EEXIST}. \\ + \const{O\_NONBLOCK}& Apre il file in modalità non bloccante, e + comporta che \func{open} ritorni immediatamente anche + quando dovrebbe bloccarsi (l'opzione ha senso solo per + le fifo, vedi sez.~\ref{sec:ipc_named_pipe}). \\ + \const{O\_NOCTTY} & Se \param{pathname} si riferisce ad un dispositivo di + terminale, questo non diventerà il terminale di + controllo, anche se il processo non ne ha ancora uno + (si veda sez.~\ref{sec:sess_ctrl_term}). \\ + \const{O\_SHLOCK} & Apre il file con uno shared lock (vedi + sez.~\ref{sec:file_locking}). Specifica di BSD, + assente in Linux. \\ + \const{O\_EXLOCK} & Apre il file con un lock esclusivo (vedi + sez.~\ref{sec:file_locking}). Specifica di BSD, + assente in Linux.\\ + \const{O\_TRUNC} & Se usato su un file di dati aperto in scrittura, + ne tronca la lunghezza a zero; con un terminale o una + fifo viene ignorato, negli altri casi il + comportamento non è specificato. \\ + \const{O\_NOFOLLOW}& Se \param{pathname} è un link simbolico la chiamata + fallisce. Questa è un'estensione BSD aggiunta in Linux + dal kernel 2.1.126. Nelle versioni precedenti i link + simbolici sono sempre seguiti, e questa opzione è + ignorata. \\ + \const{O\_DIRECTORY}&Se \param{pathname} non è una directory la chiamata + fallisce. Questo flag è specifico di Linux ed è stato + introdotto con il kernel 2.1.126 per evitare dei + \itindex{Denial~of~Service~(DoS)} + \textit{DoS}\protect\footnotemark\ quando + \func{opendir} viene chiamata su una fifo o su un + device di unità a nastri, non deve essere utilizzato + al di fuori dell'implementazione di \func{opendir}. \\ + \const{O\_LARGEFILE}&nel caso di sistemi a 32 bit che supportano file di + grandi dimensioni consente di aprire file le cui + dimensioni non possono essere rappresentate da numeri + a 31 bit. \\ \hline - \hline % modalità di operazione col file - \const{O\_APPEND} & il file viene aperto in append mode. Prima di ciascuna - scrittura la posizione corrente viene sempre impostata - alla fine del file. Con NFS si può avere una - corruzione del file se più di un processo scrive allo - stesso tempo.\footnotemark\\ - \const{O\_NONBLOCK}&il file viene aperto in modalità non bloccante per - le operazioni di I/O (che tratteremo in - sez.~\ref{sec:file_noblocking}): questo significa il - fallimento di \func{read} in assenza di dati da - leggere e quello di \func{write} in caso di - impossibilità di scrivere immediatamente. Questa - modalità ha senso solo per le fifo e per alcuni file - di dispositivo. \\ - \const{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di - \const{O\_NONBLOCK}.\\ - \const{O\_ASYNC} & apre il file per l'I/O in modalità asincrona (vedi - sez.~\ref{sec:file_asyncronous_io}). Quando è - impostato viene generato il segnale \const{SIGIO} - tutte le volte che sono disponibili dati in input - sul file. \\ - \const{O\_SYNC} & apre il file per l'input/output sincrono: ogni - \func{write} bloccherà fino al completamento della - scrittura di tutti i dati sull'hardware sottostante.\\ - \const{O\_FSYNC} & sinonimo di \const{O\_SYNC}, usato da BSD. \\ - \const{O\_DSYNC} & richiede una variante di I/O sincorno definita nello - standard POSIX; definita a partire dal kernel 2.1.130 - come sinonimo di \const{O\_SYNC}. \\ - \const{O\_RSYNC} & richiede una variante di I/O sincorno definita nello - standard POSIX; definita a partire dal kernel 2.1.130 - come sinonimo di \const{O\_SYNC}. \\ - \const{O\_NOATIME}& blocca l'aggiornamento dei tempi di accesso dei - file (vedi sez.~\ref{sec:file_file_times}). Per molti - filesystem questa funzionalità non è disponibile per - il singolo file ma come opzione generale da - specificare in fase di montaggio.\\ - \const{O\_DIRECT} & esegue l'I/O direttamente dai buffer in user space, ed - in maniera sincrona, in modo da scavalcare i - meccanismi di caching del kernel. In gebere questo - peggiora le prestazioni tranne per casi speciali in - cui sono le applicazioni\footnotemark a gestire il - caching. Per i kernel della serie 2.4 si deve - garantire che i buffer in user space siano allineati - alle dimensioni dei blocchi del filesystem; per il - kernel 2.6 basta che siano allineati a multipli di 512 - byte.\\ + \hline % modalità di operazione coi file + \const{O\_APPEND} & Il file viene aperto in append mode. Prima di ciascuna + scrittura la posizione corrente viene sempre impostata + alla fine del file. Con NFS si può avere una + corruzione del file se più di un processo scrive allo + stesso tempo.\footnotemark\\ + \const{O\_NONBLOCK}& Il file viene aperto in modalità non bloccante per + le operazioni di I/O (che tratteremo in + sez.~\ref{sec:file_noblocking}): questo significa il + fallimento di \func{read} in assenza di dati da + leggere e quello di \func{write} in caso di + impossibilità di scrivere immediatamente. Questa + modalità ha senso solo per le fifo e per alcuni file + di dispositivo. \\ + \const{O\_NDELAY} & In Linux\footnotemark\ è sinonimo di + \const{O\_NONBLOCK}.\\ + \const{O\_ASYNC} & Apre il file per l'I/O in modalità asincrona (vedi + sez.~\ref{sec:file_asyncronous_io}). Quando è + impostato viene generato il segnale \const{SIGIO} + tutte le volte che sono disponibili dati in input + sul file. \\ + \const{O\_SYNC} & Apre il file per l'input/output sincrono: ogni + \func{write} bloccherà fino al completamento della + scrittura di tutti i dati sull'hardware + sottostante.\\ + \const{O\_FSYNC} & sinonimo di \const{O\_SYNC}, usato da BSD. \\ + \const{O\_DSYNC} & Variante di I/O sincrono definita da POSIX; presente + dal kernel 2.1.130 come sinonimo di + \const{O\_SYNC}. \\ + \const{O\_RSYNC} & Variante analoga alla precedente, trattata allo stesso + modo. \\ + \const{O\_NOATIME} & Blocca l'aggiornamento dei tempi di accesso dei + file (vedi sez.~\ref{sec:file_file_times}). Per molti + filesystem questa funzionalità non è disponibile per + il singolo file ma come opzione generale da + specificare in fase di montaggio.\\ + \const{O\_DIRECT} & Esegue l'I/O direttamente dai buffer in user space + in maniera sincrona, in modo da scavalcare i + meccanismi di caching del kernel. In genere questo + peggiora le prestazioni tranne quando le + applicazioni\footnotemark ottimizzano il proprio + caching. Per i kernel della serie 2.4 si deve + garantire che i buffer in user space siano allineati + alle dimensioni dei blocchi del filesystem; per il + kernel 2.6 basta che siano allineati a multipli di 512 + byte.\\ \hline \end{tabular} \caption{Valori e significato dei vari bit del \textit{file status flag}.} \label{tab:file_open_flags} \end{table} -\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 - alternativa di usare un file con un nome univoco e la funzione \func{link} - per verificarne l'esistenza (vedi sez.~\ref{sec:ipc_file_lock}).} - -\footnotetext[3]{\textit{Denial of Service}\index{DoS}, si chiamano così - attacchi miranti ad impedire un servizio causando una qualche forma di - carico eccessivo per il sistema, che resta bloccato nelle risposte - all'attacco.} - \footnotetext[4]{il problema è che NFS non supporta la scrittura in append, ed il kernel deve simularla, ma questo comporta la possibilità di una race condition, vedi sez.~\ref{sec:file_atomic}.} @@ -446,8 +446,8 @@ descriptor ritorna disponibile; il suo prototipo \begin{prototype}{unistd.h}{int close(int fd)} Chiude il descrittore \param{fd}. - \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore, - con \var{errno} che assume i valori: + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, con \var{errno} che assume i valori: \begin{errlist} \item[\errcode{EBADF}] \param{fd} non è un descrittore valido. \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. @@ -503,8 +503,8 @@ ad un valore qualsiasi con la funzione \funcd{lseek}, il cui prototipo Imposta la posizione attuale nel file. \bodydesc{La funzione ritorna il valore della posizione corrente in caso di - successo e -1 in caso di errore nel qual caso \var{errno} assumerà uno dei - valori: + successo e $-1$ in caso di errore nel qual caso \var{errno} assumerà uno + dei valori: \begin{errlist} \item[\errcode{ESPIPE}] \param{fd} è una pipe, un socket\index{socket} o una fifo. @@ -570,7 +570,7 @@ prototipo \param{buf}. \bodydesc{La funzione ritorna il numero di byte letti in caso di successo e - -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di aver potuto leggere qualsiasi dato. @@ -644,9 +644,9 @@ definizione di un'altra funzione di lettura, \funcd{pread}, il cui prototipo Cerca di leggere \param{count} byte dal file \param{fd}, a partire dalla posizione \param{offset}, nel buffer \param{buf}. -\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e -1 - in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per - \func{read} e \func{lseek}.} +\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e + $-1$ in caso di errore, nel qual caso \var{errno} assumerà i valori già + visti per \func{read} e \func{lseek}.} \end{prototype} La funzione prende esattamente gli stessi argomenti di \func{read} con lo @@ -683,7 +683,8 @@ scrivere su di esso utilizzando la funzione \funcd{write}, il cui prototipo Scrive \param{count} byte dal buffer \param{buf} sul file \param{fd}. \bodydesc{La funzione ritorna il numero di byte scritti in caso di successo - e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei + valori: \begin{errlist} \item[\errcode{EINVAL}] \param{fd} è connesso ad un oggetto che non consente la scrittura. @@ -727,9 +728,9 @@ nel file, il suo prototipo Cerca di scrivere sul file \param{fd}, a partire dalla posizione \param{offset}, \param{count} byte dal buffer \param{buf}. -\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e -1 - in caso di errore, nel qual caso \var{errno} assumerà i valori già visti per - \func{write} e \func{lseek}.} +\bodydesc{La funzione ritorna il numero di byte letti in caso di successo e + $-1$ in caso di errore, nel qual caso \var{errno} assumerà i valori già + visti per \func{write} e \func{lseek}.} \end{prototype} \noindent e per essa valgono le stesse considerazioni fatte per \func{pread}. @@ -924,8 +925,8 @@ usare le due funzioni \funcd{fsync} e \funcd{fdatasync}, i cui prototipi sono: \funcdecl{int fdatasync(int fd)} Sincronizza i dati del file \param{fd}. - \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore, - nel qual caso \var{errno} assume i valori: + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assume i valori: \begin{errlist} \item[\errcode{EINVAL}] \param{fd} è un file speciale che non supporta la sincronizzazione. @@ -960,7 +961,7 @@ prototipo Crea una copia del file descriptor \param{oldfd}. \bodydesc{La funzione ritorna il nuovo file descriptor in caso di successo e - -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei + $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EBADF}] \param{oldfd} non è un file aperto. @@ -1014,7 +1015,7 @@ prototipo Rende \param{newfd} una copia del file descriptor \param{oldfd}. \bodydesc{La funzione ritorna il nuovo file descriptor in caso di successo e - -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EBADF}] \param{oldfd} non è un file aperto o \param{newfd} ha un valore fuori dall'intervallo consentito per i file descriptor. @@ -1066,8 +1067,8 @@ il cui prototipo sul file \param{fd}. \bodydesc{La funzione ha valori di ritorno diversi a seconda - dell'operazione. In caso di errore il valore di ritorno è sempre -1 ed il - codice dell'errore è restituito nella variabile \var{errno}; i codici + dell'operazione. In caso di errore il valore di ritorno è sempre $-1$ ed + il codice dell'errore è restituito nella variabile \var{errno}; i codici possibili dipendono dal tipo di operazione, l'unico valido in generale è: \begin{errlist} \item[\errcode{EBADF}] \param{fd} non è un file aperto. @@ -1086,73 +1087,75 @@ per \var{cmd} \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{F\_DUPFD}] trova il primo file descriptor disponibile di valore maggiore o uguale ad \param{arg} e ne fa una copia di \param{fd}. Ritorna il - nuovo file descriptor in caso di successo e -1 in caso di errore. Gli errori - possibili sono \errcode{EINVAL} se \param{arg} è negativo o maggiore del - massimo consentito o \errcode{EMFILE} se il processo ha già raggiunto il + nuovo file descriptor in caso di successo e $-1$ in caso di errore. Gli + errori possibili sono \errcode{EINVAL} se \param{arg} è negativo o maggiore + del massimo consentito o \errcode{EMFILE} se il processo ha già raggiunto il 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 \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. + valore nullo in caso di successo e $-1$ in caso di errore. \item[\const{F\_GETFD}] ritorna il valore del \textit{file descriptor flag} di - \param{fd} o -1 in caso di errore; se \const{FD\_CLOEXEC} è impostato i file - descriptor aperti vengono chiusi attraverso una \func{exec} altrimenti (il - comportamento predefinito) restano aperti. + \param{fd} o $-1$ in caso di errore; se \const{FD\_CLOEXEC} è impostato i + file descriptor aperti vengono chiusi attraverso una \func{exec} altrimenti + (il comportamento predefinito) restano aperti. \item[\const{F\_GETFL}] ritorna il valore del \textit{file status flag} in - caso di successo o -1 in caso di errore; permette cioè di rileggere quei bit - impostati da \func{open} all'apertura del file che vengono memorizzati + caso di successo o $-1$ in caso di errore; permette cioè di rileggere quei + bit impostati da \func{open} all'apertura del file che vengono memorizzati (quelli riportati nella prima e terza sezione di tab.~\ref{tab:file_open_flags}). \item[\const{F\_SETFL}] imposta il \textit{file status flag} al valore - specificato da \param{arg}, ritorna un valore nullo in caso di successo o -1 - in caso di errore. Possono essere impostati solo i bit riportati nella terza - sezione di tab.~\ref{tab:file_open_flags}.\footnote{la pagina di manuale - riporta come impostabili solo \const{O\_APPEND}, \const{O\_NONBLOCK} e - \const{O\_ASYNC}.} + specificato da \param{arg}, ritorna un valore nullo in caso di successo o + $-1$ in caso di errore. Possono essere impostati solo i bit riportati nella + terza sezione di tab.~\ref{tab:file_open_flags}.\footnote{la pagina di + manuale riporta come impostabili solo \const{O\_APPEND}, + \const{O\_NONBLOCK} e \const{O\_ASYNC}.} \item[\const{F\_GETLK}] richiede un controllo sul file lock specificato da - \param{lock}, sovrascrivendo la struttura da esso puntata con il risultato, - ritorna un valore nullo in caso di successo o -1 in caso di errore. Questa + \param{lock}, sovrascrivendo la struttura da esso puntata con il risultato; + ritorna un valore nullo in caso di successo o $-1$ in caso di errore. Questa funzionalità è trattata in dettaglio in sez.~\ref{sec:file_posix_lock}. \item[\const{F\_SETLK}] richiede o rilascia un file lock a seconda di quanto specificato nella struttura puntata da \param{lock}. Se il lock è tenuto da - qualcun'altro ritorna immediatamente restituendo -1 e imposta \var{errno} a + qualcun altro ritorna immediatamente restituendo $-1$ e imposta \var{errno} a \errcode{EACCES} o \errcode{EAGAIN}, in caso di successo ritorna un valore nullo. Questa funzionalità è trattata in dettaglio in sez.~\ref{sec:file_posix_lock}. \item[\const{F\_SETLKW}] identica a \const{F\_SETLK} eccetto per il fatto che la funzione non ritorna subito ma attende che il blocco sia rilasciato. Se - l'attesa viene interrotta da un segnale la funzione restituisce -1 e imposta - \var{errno} a \errcode{EINTR}, in caso di successo ritorna un valore nullo. - Questa funzionalità è trattata in dettaglio in + l'attesa viene interrotta da un segnale la funzione restituisce $-1$ e + imposta \var{errno} a \errcode{EINTR}, in caso di successo ritorna un valore + nullo. Questa funzionalità è trattata in dettaglio in sez.~\ref{sec:file_posix_lock}. \item[\const{F\_GETOWN}] restituisce il \acr{pid} del processo o - l'identificatore del process group\footnote{i \texttt{process group} sono + l'identificatore del \itindex{process~group} \textit{process + group}\footnote{i \itindex{process~group} \textit{process group} sono (vedi sez.~\ref{sec:sess_proc_group}) raggruppamenti di processi usati nel controllo di sessione; a ciascuno di essi è associato un identificatore (un numero positivo analogo al \acr{pid}).} che è preposto alla ricezione dei segnali \const{SIGIO} e \const{SIGURG} per gli eventi associati al file - descriptor \param{fd}. Nel caso di un process group viene restituito un - valore negativo il cui valore assoluto corrisponde all'identificatore del - process group. In caso di errore viene restituito -1. + 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 + caso di errore viene restituito $-1$. \item[\const{F\_SETOWN}] imposta, con il valore dell'argomento \param{arg}, - l'identificatore del processo o del \textit{process group} che riceverà i - segnali \const{SIGIO} e \const{SIGURG} per gli eventi associati al file - descriptor \param{fd}, ritorna un valore nullo in caso di successo o -1 in - caso di errore. Come per \const{F\_GETOWN}, per impostare un - \textit{process group} si deve usare per \param{arg} un valore negativo, il - cui valore assoluto corrisponde all'identificatore del \textit{process - group}. + l'identificatore del processo o del \itindex{process~group} \textit{process + group} che riceverà i segnali \const{SIGIO} e \const{SIGURG} per gli + eventi associati al file descriptor \param{fd}, ritorna un valore nullo in + caso di successo o $-1$ in caso di errore. Come per \const{F\_GETOWN}, per + impostare un \itindex{process~group} \textit{process group} si deve usare + per \param{arg} un valore negativo, il cui valore assoluto corrisponde + all'identificatore del \itindex{process~group} \textit{process group}. \item[\const{F\_GETSIG}] restituisce il valore del segnale inviato quando ci sono dati disponibili in ingresso su un file descriptor aperto ed impostato per l'I/O asincrono (si veda sez.~\ref{sec:file_asyncronous_io}). Il valore 0 indica il valore predefinito (che è \const{SIGIO}), un valore diverso da zero indica il segnale richiesto, (che può essere anche lo stesso - \const{SIGIO}). In caso di errore ritorna -1. + \const{SIGIO}). In caso di errore ritorna $-1$. \item[\const{F\_SETSIG}] imposta il segnale da inviare quando diventa possibile effettuare I/O sul file descriptor in caso di I/O asincrono, - ritorna un valore nullo in caso di successo o -1 in caso di errore. Il + ritorna un valore nullo in caso di successo o $-1$ in caso di errore. Il valore zero indica di usare il segnale predefinito, \const{SIGIO}. Un altro valore diverso da zero (compreso lo stesso \const{SIGIO}) specifica il segnale voluto; l'uso di un valore diverso da zero permette inoltre, se si è @@ -1163,27 +1166,28 @@ per \var{cmd} (come vedremo in sez.~\ref{sec:file_asyncronous_io}).\footnote{i due comandi \const{F\_SETSIG} e \const{F\_GETSIG} sono una estensione specifica di Linux.} -\item[\const{F\_SETLEASE}] imposta o rimuove un \textit{file - lease}\footnote{questa è una nuova funzionalità, specifica di Linux, e - presente solo a partire dai kernel della serie 2.4.x, in cui il processo - che detiene un \textit{lease} su un file riceve una notifica qualora un - altro processo cerca di eseguire una \func{open} o una \func{truncate} su - di esso.} sul file descriptor \var{fd} a seconda del valore del terzo - argomento, che in questo caso è un \ctyp{int}, ritorna un valore nullo in - caso di successo o -1 in caso di errore. Questa funzionalità avanzata è - trattata in dettaglio in sez.~\ref{sec:file_asyncronous_operation}. -\item[\const{F\_GETLEASE}] restituisce il tipo di \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 +\item[\const{F\_SETLEASE}] imposta o rimuove un \index{file!lease} + \textit{file lease}\footnote{questa è una nuova funzionalità, specifica di + Linux, e presente solo a partire dai kernel della serie 2.4.x, in cui il + processo che detiene un \textit{lease} su un file riceve una notifica + qualora un altro processo cerca di eseguire una \func{open} o una + \func{truncate} su di esso.} sul file descriptor \var{fd} a seconda del + valore del terzo argomento, che in questo caso è un \ctyp{int}, ritorna un + valore nullo in caso di successo o $-1$ in caso di errore. Questa funzionalità avanzata è trattata in dettaglio in - sez.~\ref{sec:file_asyncronous_operation}. + 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\_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 direttamente sulla directory cui \var{fd} fa riferimento, o su uno dei file - in essa contenuti; ritorna un valore nullo in caso di successo o -1 in caso + in essa contenuti; ritorna un valore nullo in caso di successo o $-1$ in caso di errore. Questa funzionalità avanzata, disponibile dai kernel della serie - 2.4.x, è trattata in dettaglio in sez.~\ref{sec:file_asyncronous_operation}. + 2.4.x, è trattata in dettaglio in sez.~\ref{sec:file_asyncronous_lease}. \end{basedescript} La maggior parte delle funzionalità di \func{fcntl} sono troppo avanzate per @@ -1191,8 +1195,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_operation} mentre quelle relative al -\textit{file locking}\index{file!locking} saranno esaminate in +sez.~\ref{sec:file_asyncronous_access} mentre quelle relative al \textit{file + locking}\index{file!locking} saranno esaminate in sez.~\ref{sec:file_locking}). Si tenga presente infine che quando si usa la funzione per determinare le @@ -1233,7 +1237,7 @@ file descriptor. Il prototipo di questa funzione \bodydesc{La funzione nella maggior parte dei casi ritorna 0, alcune operazioni usano però il valore di ritorno per restituire informazioni. In - caso di errore viene sempre restituito -1 ed \var{errno} assumerà uno dei + caso di errore viene sempre restituito $-1$ ed \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{ENOTTY}] il file \param{fd} non è associato con un device, o @@ -1294,6 +1298,8 @@ file: \end{basedescript} relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}. +% TODO estendere la lista delle ioctl + %%% Local Variables: %%% mode: latex diff --git a/intro.tex b/intro.tex index 7cca8ce..0e24abd 100644 --- a/intro.tex +++ b/intro.tex @@ -716,7 +716,7 @@ includere i vari header file. %% \subsection{Gli standard di GNU/Linux} %% \label{sec:intro_linux_std} -%% Da fare (o cassare, a seconda del tempo e della voglia). +% TODO Da fare (o cassare, a seconda del tempo e della voglia). diff --git a/ipc.tex b/ipc.tex index 839f9da..135bed7 100644 --- a/ipc.tex +++ b/ipc.tex @@ -131,7 +131,7 @@ da altri processi. Per capire meglio il funzionamento delle pipe faremo un esempio di quello che è il loro uso più comune, analogo a quello effettuato della shell, e che consiste nell'inviare l'output di un processo (lo standard output) sull'input -di un'altro. Realizzeremo il programma di esempio nella forma di un +di un altro. Realizzeremo il programma di esempio nella forma di un \textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un programma che permette la creazione dinamica di un oggetto da inserire all'interno di una pagina HTML.} per Apache, che genera una immagine JPEG @@ -3046,7 +3046,7 @@ con una chiamata ad \func{unlink}. Un esempio dell'uso di questa funzione è mostrato dalle funzioni \func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock} -(sono contenute in \file{LockFile.c}, un'altro dei sorgenti allegati alla +(sono contenute in \file{LockFile.c}, un altro dei sorgenti allegati alla guida) che permettono rispettivamente di creare e rimuovere un \textsl{file di lock}. Come si può notare entrambe le funzioni sono elementari; la prima (\texttt{\small 4--10}) si limita ad aprire il file di lock (\texttt{\small @@ -3073,7 +3073,7 @@ caso si pu esistente; se il link esiste già e la funzione fallisce, significa che la risorsa è bloccata e potrà essere sbloccata solo con un \func{unlink}, altrimenti il link è creato ed il lock acquisito; il controllo e l'eventuale -acquisizione sono atomici; la soluzione funziona anche su NFS, ma ha un'altro +acquisizione sono atomici; la soluzione funziona anche su NFS, ma ha un altro difetto è che è quello di poterla usare solo se si opera all'interno di uno stesso filesystem. @@ -3155,7 +3155,7 @@ write lock sul file, che poi (\texttt{\small 21}) viene richiesto con \func{fcntl}, restituendo il valore di ritorno di quest'ultima. Se il file è libero il lock viene acquisito e la funzione ritorna immediatamente; altrimenti \func{fcntl} si bloccherà (si noti che la si è chiamata con -\func{F\_SETLKW}) fino al rilascio del lock. +\const{F\_SETLKW}) fino al rilascio del lock. La quarta funzione (\texttt{\small 24--34}) è \func{UnlockMutex} e serve a rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo @@ -3255,9 +3255,9 @@ tuttavia dei patch e una libreria aggiuntiva. La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso degli identificatori e delle chiavi visti nel SysV IPC, per passare ai -\textit{Posix IPC names}\itindex{Posix~IPC~names}, che sono sostanzialmente +\textit{POSIX IPC names}\itindex{POSIX~IPC~names}, che sono sostanzialmente equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC -Posix prendono come primo argomento una stringa che indica uno di questi nomi; +POSIX prendono come primo argomento una stringa che indica uno di questi nomi; lo standard è molto generico riguardo l'implementazione, ed i nomi stessi possono avere o meno una corrispondenza sul filesystem; tutto quello che è richiesto è che: @@ -3646,6 +3646,9 @@ differenza di quanto avveniva con le code di messaggi di SysV che permettono invece la selezione in base al valore del campo \var{mtype}. Qualora non interessi usare la priorità dei messaggi si +% TODO vericare questa interruzione di paragrafo +% TODO inserire i dati di /proc/sys/fs/mqueue + Qualora la coda sia vuota entrambe le funzioni si bloccano, a meno che non si sia selezionata la modalità non bloccante; in tal caso entrambe ritornano immediatamente con l'errore \errcode{EAGAIN}. Anche in questo caso la sola @@ -3771,6 +3774,7 @@ pi POSIX. L'interfaccia corrente è stata stabilizzata a partire dal kernel 2.5.40. +% TODO vedere se ci sono novità e trattare la cosa. @@ -3862,10 +3866,10 @@ segmento di memoria condiviso con le stesse modalit effetto.} viste in sez.~\ref{sec:file_open}; in particolare viene impostato il flag \const{FD\_CLOEXEC}. Chiamate effettuate da diversi processi usando lo stesso nome, restituiranno file descriptor associati allo stesso segmento -(così come, nel caso di file di dati, essi sono associati allo stesso inode). -In questo modo è possibile effettuare una chiamata ad \func{mmap} sul file -descriptor restituito da \func{shm\_open} ed i processi vedranno lo stesso -segmento di memoria condivisa. +(così come, nel caso di file di dati, essi sono associati allo stesso +\index{inode}inode). In questo modo è possibile effettuare una chiamata ad +\func{mmap} sul file descriptor restituito da \func{shm\_open} ed i processi +vedranno lo stesso segmento di memoria condivisa. Quando il nome non esiste il segmento può essere creato specificando \const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file) diff --git a/macro.tex b/macro.tex index 631220a..762ec69 100644 --- a/macro.tex +++ b/macro.tex @@ -164,7 +164,7 @@ \index{#1@{\textit{#1}}|)}% } \newcommand{\itindsub}[2]{% -\index{#1@{\textit{#1}}!#2}% +\index{#1@{\textit{#1}}!\textit{#2}}% } % Aggiunte di Mirko per la gestione delle tabelle complicate come immagini diff --git a/netlayer.tex b/netlayer.tex index 8926bfc..86bb052 100644 --- a/netlayer.tex +++ b/netlayer.tex @@ -499,8 +499,8 @@ differenze: pacchetti frammentati\\ \textit{flag} & 3 & \textsl{flag} bit di frammentazione, uno indica se un - pacchetto è frammentato, un'altro se ci sono ulteriori frammenti, e - un'altro se il pacchetto non può essere frammentato. \\ + pacchetto è frammentato, un altro se ci sono ulteriori frammenti, e + un altro se il pacchetto non può essere frammentato. \\ \textit{fragmentation offset} & 13 & \textsl{offset di frammento}, indica la posizione del frammento rispetto al pacchetto originale\\ \textit{time to live} & 16 & \textsl{tempo di vita}, diff --git a/network.tex b/network.tex index 273c8da..788d554 100644 --- a/network.tex +++ b/network.tex @@ -680,6 +680,7 @@ ricevere allo stesso tempo, il che comporta che quanto dicevamo a proposito del controllo di flusso e della gestione della sequenzialità dei dati viene effettuato per entrambe le direzioni di comunicazione. +% TODO mettere riferimento alla appendice su TCP quando ci sarà %% Una descrizione più accurata del protocollo è fornita in appendice %% sez.~\ref{sec:tcp_protocol}. @@ -784,12 +785,6 @@ delle intestazioni di IP e TCP, in Linux il default, mantenuto nella costante \const{TCP\_MSS} è 512. -%\subsection{Il passaggio dei dati in TCP} -%\label{sec:net_tcp_pass} - -%\subsection{Il passaggio dei dati in UDP} -%\label{sec:net_udp_pass} - %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" diff --git a/othersock.tex b/othersock.tex index 6915f99..3aa2bb9 100644 --- a/othersock.tex +++ b/othersock.tex @@ -131,11 +131,11 @@ la destinazione dei dati trasmessi o ottenere l'origine dei dati ricevuti. La prima di queste funzioni è \funcd{sendto} ed il suo prototipo\footnote{il prototipo illustrato è quello utilizzato dalle \acr{glibc}, che seguono le \textit{Single Unix Specification}, l'argomento \param{flags} era di tipo - \type{int} nei vari BSD4.*, mentre nelle \acr{libc4} e \acr{libc5} veniva - usato un \type{unsigned int}; l'argomento \param{len} era \type{int} nei + \texttt{int} nei vari BSD4.*, mentre nelle \acr{libc4} e \acr{libc5} veniva + usato un \texttt{unsigned int}; l'argomento \param{len} era \texttt{int} nei vari BSD4.* e nelle \acr{libc4}, ma \type{size\_t} nelle \acr{libc5}; infine - l'argomento \param{tolen} era \type{int} nei vari BSD4.* nelle \acr{libc4} e - nelle \acr{libc5}.} è: + l'argomento \param{tolen} era \texttt{int} nei vari BSD4.* nelle \acr{libc4} + e nelle \acr{libc5}.} è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/socket.h} @@ -220,9 +220,9 @@ La seconda funzione utilizzata nella comunicazione fra socket UDP \funcd{recvfrom}, che serve a ricevere i dati inviati da un altro socket; il suo prototipo\footnote{il prototipo è quello delle \acr{glibc} che seguono le \textit{Single Unix Specification}, i vari BSD4.*, le \acr{libc4} e le - \acr{libc5} usano un \type{int} come valore di ritorno; per gli argomenti + \acr{libc5} usano un \texttt{int} come valore di ritorno; per gli argomenti \param{flags} e \param{len} vale quanto detto a proposito di \func{sendto}; - infine l'argomento \param{fromlen} è \type{int} per i vari BSD4.*, le + infine l'argomento \param{fromlen} è \texttt{int} per i vari BSD4.*, le \acr{libc4} e le \acr{libc5}.} è: \begin{functions} \headdecl{sys/types.h} diff --git a/process.tex b/process.tex index b572ee3..a0024f5 100644 --- a/process.tex +++ b/process.tex @@ -351,20 +351,21 @@ processo pu seguenti segmenti: \begin{enumerate} -\item Il segmento di testo o \textit{text segment}. Contiene il codice del - programma, delle funzioni di librerie da esso utilizzate, e le costanti. - Normalmente viene condiviso fra tutti i processi che eseguono lo stesso - programma (e anche da processi che eseguono altri programmi nel caso delle - librerie). Viene marcato in sola lettura per evitare sovrascritture - accidentali (o maliziose) che ne modifichino le istruzioni. +\item Il \index{segmento!testo} segmento di testo o \textit{text segment}. + Contiene il codice del programma, delle funzioni di librerie da esso + utilizzate, e le costanti. Normalmente viene condiviso fra tutti i processi + che eseguono lo stesso programma (e anche da processi che eseguono altri + programmi nel caso delle librerie). Viene marcato in sola lettura per + evitare sovrascritture accidentali (o maliziose) che ne modifichino le + istruzioni. Viene allocato da \func{exec} all'avvio del programma e resta invariato per tutto il tempo dell'esecuzione. -\item Il segmento dei dati o \textit{data segment}. Contiene le variabili - globali (cioè quelle definite al di fuori di tutte le funzioni che - compongono il programma) e le variabili statiche (cioè quelle dichiarate con - l'attributo \ctyp{static}). Di norma è diviso in due parti. +\item Il \index{segmento!dati} segmento dei dati o \textit{data segment}. + Contiene le variabili globali (cioè quelle definite al di fuori di tutte le + funzioni che compongono il programma) e le variabili statiche (cioè quelle + dichiarate con l'attributo \ctyp{static}). Di norma è diviso in due parti. La prima parte è il segmento dei dati inizializzati, che contiene le variabili il cui valore è stato assegnato esplicitamente. Ad esempio @@ -386,26 +387,30 @@ seguenti segmenti: Storicamente questa seconda parte del segmento dati viene chiamata BSS (da \textit{Block Started by Symbol}). La sua dimensione è fissa. -\item Lo \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 funzioni (vedi - sez.~\ref{sec:proc_mem_alloc}), ma il suo limite inferiore (quello adiacente - al segmento dati) ha una posizione fissa. +\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 + funzioni (vedi sez.~\ref{sec:proc_mem_alloc}), ma il suo limite inferiore + (quello adiacente al segmento dati) ha una posizione fissa. -\item Il segmento di \textit{stack}, che contiene lo \textit{stack} del - programma. Tutte le volte che si effettua una chiamata ad una funzione è - qui che viene salvato l'indirizzo di ritorno e le informazioni dello stato - del chiamante (tipo il contenuto di alcuni registri della CPU). Poi la - funzione chiamata alloca qui lo spazio per le sue variabili locali: in - questo modo le funzioni possono essere chiamate ricorsivamente. Al ritorno - della funzione lo spazio è automaticamente rilasciato e - ``\textsl{ripulito}''. La pulizia in C e C++ viene fatta dal - chiamante.\footnote{a meno che non sia stato specificato l'utilizzo di una - calling convention diversa da quella standard.} - - La dimensione di questo segmento aumenta seguendo la crescita dello stack - del programma, ma non viene ridotta quando quest'ultimo si restringe. +\item Il segmento di \itindex{stack} \textit{stack}, che contiene quello che + viene chiamato \textit{stack} del programma. Tutte le volte che si effettua + una chiamata ad una funzione è qui che viene salvato l'indirizzo di ritorno + e le informazioni dello stato del chiamante (tipo il contenuto di alcuni + registri della CPU), poi la funzione chiamata alloca qui lo spazio per le + sue variabili locali. Tutti questi dati vengono \textit{impilati} (da questo + viene il nome \textit{stack}) in sequenza uno sull'altro; in questo modo le + funzioni possono essere chiamate ricorsivamente. Al ritorno della funzione + lo spazio è automaticamente rilasciato e ``\textsl{ripulito}''. La pulizia + in C e C++ viene fatta dal chiamante.\footnote{a meno che non sia stato + specificato l'utilizzo di una calling convention diversa da quella + standard.} +% TODO verificare le modalità di cambiamento della calling convention + + La dimensione di questo segmento aumenta seguendo la crescita dello + \textit{stack} del programma, ma non viene ridotta quando quest'ultimo si + restringe. \end{enumerate} \begin{figure}[htb] @@ -415,11 +420,12 @@ seguenti segmenti: \label{fig:proc_mem_layout} \end{figure} -Una disposizione tipica di questi segmenti è riportata in -fig.~\ref{fig:proc_mem_layout}. Usando il comando \cmd{size} su un programma se -ne può stampare le dimensioni dei segmenti di testo e di dati (inizializzati e -BSS); si tenga presente però che il BSS non è mai salvato sul file che -contiene l'eseguibile, dato che viene sempre inizializzato a zero al +Una disposizione tipica dei vari segmenti (testo, \itindex{heap} +\textit{heap}, \itindex{stack} \textit{stack}, ecc.) è riportata in +fig.~\ref{fig:proc_mem_layout}. Usando il comando \cmd{size} su un programma +se ne può stampare le dimensioni dei segmenti di testo e di dati +(inizializzati e BSS); si tenga presente però che il BSS non è mai salvato sul +file che contiene l'eseguibile, dato che viene sempre inizializzato a zero al caricamento del programma. @@ -433,15 +439,15 @@ l'\textsl{allocazione automatica}. L'\textsl{allocazione statica} è quella con cui sono memorizzate le variabili globali e le variabili statiche, cioè le variabili il cui valore deve essere mantenuto per tutta la durata del programma. Come accennato queste variabili -vengono allocate nel segmento dei dati all'avvio del programma (come parte -delle operazioni svolte da \func{exec}) e lo spazio da loro occupato non viene -liberato fino alla sua conclusione. +vengono allocate nel \index{segmento!dati} segmento dei dati all'avvio del +programma (come parte delle operazioni svolte da \func{exec}) e lo spazio da +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 stack quando viene eseguita la -funzione e liberato quando si esce dalla medesima. +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} della memoria, che non è prevista direttamente all'interno del linguaggio C, @@ -452,12 +458,13 @@ 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 heap). +l'allocazione dinamica di memoria (in genere nello \itindex{heap} heap). Le variabili il cui contenuto è allocato in questo modo non potranno essere -usate direttamente come le altre, ma l'accesso sarà possibile solo in maniera -indiretta, attraverso i puntatori alla memoria loro riservata che si sono -ottenuti dalle funzioni di allocazione. +usate direttamente come le altre (quelle nello \itindex{stack} stack), ma +l'accesso sarà possibile solo in maniera indiretta, attraverso i puntatori +alla memoria loro riservata che si sono ottenuti dalle funzioni di +allocazione. \subsection{Le funzioni \func{malloc}, \func{calloc}, \func{realloc} e @@ -586,6 +593,7 @@ programmazione ad oggetti, il problema dei \textit{memory 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 % nemmeno perché la gestione della memoria viene fatta totalmente in maniera % automatica, ovvero il programmatore non deve minimamente preoccuparsi di @@ -625,9 +633,10 @@ 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 heap usa -il segmento di stack della funzione corrente. La sintassi è identica a quella -di \func{malloc}, il suo prototipo è: +è 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. @@ -637,10 +646,10 @@ di \func{malloc}, il suo prototipo \end{prototype} La funzione alloca la quantità di memoria (non inizializzata) richiesta -dall'argomento \param{size} nel segmento di stack della funzione chiamante. -Con questa funzione non è più necessario liberare la memoria allocata (e -quindi non esiste un analogo della \func{free}) in quanto essa viene -rilasciata automaticamente al ritorno della funzione. +dall'argomento \param{size} nel segmento di \itindex{stack}stack della +funzione chiamante. Con questa funzione non è più necessario liberare 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}, @@ -691,15 +700,17 @@ prototipo \end{prototype} La funzione è un'interfaccia diretta all'omonima system call ed imposta -l'indirizzo finale del segmento dati di un processo all'indirizzo specificato -da \param{end\_data\_segment}. Quest'ultimo deve essere un valore ragionevole, -ed inoltre la dimensione totale del segmento non deve comunque eccedere un -eventuale limite (si veda sez.~\ref{sec:sys_resource_limit}) imposto sulle -dimensioni massime dello spazio dati del processo. - -La seconda funzione per la manipolazione delle dimensioni del segmento -dati\footnote{in questo caso si tratta soltanto di una funzione di libreria, e - non di una system call.} è \funcd{sbrk}, ed il suo prototipo è: +l'indirizzo finale del \index{segmento!dati}segmento dati di un processo +all'indirizzo specificato da \param{end\_data\_segment}. Quest'ultimo deve +essere un valore ragionevole, ed inoltre la dimensione totale del segmento non +deve comunque eccedere un eventuale limite (si veda +sez.~\ref{sec:sys_resource_limit}) imposto sulle dimensioni massime dello +spazio dati del processo. + +La seconda funzione per la manipolazione delle dimensioni +\index{segmento!dati} del segmento dati\footnote{in questo caso si tratta + soltanto di una funzione di libreria, e non di una system call.} è +\funcd{sbrk}, ed il suo prototipo è: \begin{prototype}{unistd.h}{void *sbrk(ptrdiff\_t increment)} Incrementa la dimensione dello spazio dati. @@ -710,7 +721,7 @@ dati\footnote{in questo caso si tratta soltanto di una funzione di libreria, e \noindent la funzione incrementa la dimensione lo spazio dati di un programma di \param{increment} byte, restituendo il nuovo indirizzo finale dello stesso. Un valore nullo permette di ottenere l'attuale posizione della fine del -segmento dati. +\index{segmento!dati} segmento dati. Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e per i programmi normali è sempre opportuno usare le funzioni di allocazione @@ -722,7 +733,6 @@ standard descritte in precedenza, che sono costruite su di esse. % TODO documentare \func{madvise} % TODO documentare \func{mincore} -% TODO documentare \func{mprotect} forse da mettere insieme a mmap \subsection{Il controllo della memoria virtuale} \label{sec:proc_mem_lock} @@ -791,7 +801,7 @@ 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{capability}\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. @@ -866,7 +876,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 la \itindex{capability}\textit{capability} + func{munlockall} senza la \itindex{capabilities}\textit{capability} \const{CAP\_IPC\_LOCK} genera un errore di \errcode{EPERM}.} \end{functions} @@ -881,11 +891,13 @@ costanti: \end{basedescript} Con \func{mlockall} si possono bloccare tutte le pagine mappate nello spazio -di indirizzi del processo, sia che comprendano il segmento di testo, di dati, -lo stack, lo 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. +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. In ogni caso un processo real-time che deve entrare in una sezione critica deve provvedere a riservare memoria sufficiente prima dell'ingresso, per @@ -899,9 +911,12 @@ esecuzione. In genere si ovvia a questa problematica chiamando una funzione che ha allocato una quantità sufficientemente ampia di variabili automatiche, in modo -che esse vengano mappate in RAM dallo stack, dopo di che, per essere sicuri -che esse siano state effettivamente portate in memoria, ci si scrive sopra. -\index{memoria~virtuale|)} +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. + +\index{memoria~virtuale|)} + \itindend{memory~locking} @@ -1258,10 +1273,10 @@ versione del vettore \var{environ} questo sar corrente sarà deallocata solo se anch'essa è risultante da un'allocazione 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 stack, (vedi -fig.~\ref{fig:proc_mem_layout}) e non nello heap e non può essere deallocato. -Inoltre la memoria associata alle variabili di ambiente eliminate non viene -liberata. +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 +ambiente eliminate non viene liberata. L'ultima funzione è \funcd{clearenv}, che viene usata per cancellare completamente tutto l'ambiente; il suo prototipo è: @@ -1384,9 +1399,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 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} 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}. @@ -1442,8 +1457,8 @@ 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 -stack all'indirizzo dove sono stati salvati gli argomenti, è assolutamente -normale pensare di poter effettuare questa operazione. +\itindex{stack} 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} @@ -1496,9 +1511,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 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} 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 @@ -1544,10 +1559,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 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 stack è \funcd{setjmp}, il cui prototipo è: +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 è: \begin{functions} \headdecl{setjmp.h} \funcdecl{int setjmp(jmp\_buf env)} @@ -1559,8 +1575,8 @@ salvare il contesto dello stack che usa il contesto salvato in precedenza.} \end{functions} -Quando si esegue la funzione il contesto corrente dello stack viene salvato -nell'argomento \param{env}, una variabile di tipo +Quando si esegue la funzione il contesto corrente dello \itindex{stack} 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 altri oggetti usati da una libreria, la cui struttura interna non deve @@ -1573,10 +1589,10 @@ 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 -stack effettuando il salto non-locale. Si tenga conto che il contesto salvato -in \param{env} viene invalidato se la routine 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. +\itindex{stack} stack effettuando il salto non-locale. Si tenga conto che il +contesto salvato in \param{env} viene invalidato se la routine 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. Come accennato per effettuare un salto non-locale ad un punto precedentemente stabilito con \func{setjmp} si usa la funzione @@ -1590,12 +1606,13 @@ un punto precedentemente stabilito con \func{setjmp} si usa la funzione \bodydesc{La funzione non ritorna.} \end{functions} -La funzione ripristina il contesto dello 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. +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 +\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. In sostanza un \func{longjmp} è analogo ad un \code{return}, solo che invece di ritornare alla riga successiva della funzione chiamante, il programma @@ -1604,10 +1621,11 @@ il ritorno pu annidate. L'implementazione di queste funzioni comporta alcune restrizioni dato che esse -interagiscono direttamente con la gestione dello 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} 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}); @@ -1641,17 +1659,18 @@ delle variabili automatiche (o di quelle dichiarate Quello che succede infatti è che i valori delle variabili che sono tenute in 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 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).}. +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 + \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).}. \index{salto~non-locale|)} diff --git a/prochand.tex b/prochand.tex index 569e06b..b2b2b0b 100644 --- a/prochand.tex +++ b/prochand.tex @@ -126,13 +126,13 @@ struttura, alla cui base c' processi. Il kernel mantiene una tabella dei processi attivi, la cosiddetta -\textit{process table}; per ciascun processo viene mantenuta una voce, -costituita da una struttura \struct{task\_struct}, nella tabella dei processi -che contiene tutte le informazioni rilevanti per quel processo. Tutte le -strutture usate a questo scopo sono dichiarate nell'header file -\file{linux/sched.h}, ed uno schema semplificato, che riporta la struttura -delle principali informazioni contenute nella \struct{task\_struct} (che in -seguito incontreremo a più riprese), è mostrato in +\itindex{process~table} \textit{process table}; per ciascun processo viene +mantenuta una voce, costituita da una struttura \struct{task\_struct}, nella +tabella dei processi che contiene tutte le informazioni rilevanti per quel +processo. Tutte le strutture usate a questo scopo sono dichiarate nell'header +file \file{linux/sched.h}, ed uno schema semplificato, che riporta la +struttura delle principali informazioni contenute nella \struct{task\_struct} +(che in seguito incontreremo a più riprese), è mostrato in fig.~\ref{fig:proc_task_struct}. \begin{figure}[htb] @@ -146,16 +146,18 @@ fig.~\ref{fig:proc_task_struct}. 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. NDT completare questa - parte.} (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 in \file{asm/param.h}, ed il cui valore è espresso in -Hertz.\footnote{Il valore usuale di questa costante è 100, per tutte le - architetture eccetto l'alpha, per la quale è 1000. Occorre fare attenzione a - non confondere questo valore con quello dei clock tick (vedi +interrupt,\footnote{più in una serie di altre occasioni.} +% TODO completare questa parte. +(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 +in \file{asm/param.h}, ed il cui valore è espresso in Hertz.\footnote{Fino al + kernel 2.4 l valore usuale di questa costante era 100, per tutte le + architetture eccetto l'alpha, per la quale era 1000. Occorre fare attenzione + a non confondere questo valore con quello dei clock tick (vedi sez.~\ref{sec:sys_unix_time}).} -%Si ha cioè un interrupt dal timer ogni centesimo di secondo. +% 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} effettua il calcolo delle priorità dei vari processi attivi (torneremo su @@ -317,22 +319,22 @@ 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, 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 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 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. 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 @@ -898,15 +900,17 @@ secondo lo specchietto riportato in tab.~\ref{tab:proc_waidpid_pid}. \textbf{Valore} & \textbf{Opzione} &\textbf{Significato}\\ \hline \hline - $<-1$& -- & attende per un figlio il cui \textit{process group} (vedi - sez.~\ref{sec:sess_proc_group}) è uguale al - valore assoluto di \param{pid}. \\ - $-1$ & \const{WAIT\_ANY} & attende per un figlio qualsiasi, usata in - questa maniera è equivalente a \func{wait}.\\ - $0$ & \const{WAIT\_MYPGRP} & attende per un figlio il cui \textit{process - group} è uguale a quello del processo chiamante. \\ - $>0$ & -- &attende per un figlio il cui \acr{pid} è uguale al - valore di \param{pid}.\\ + $<-1$& -- & attende per un figlio il cui + \itindex{process~group} \textit{process group} + (vedi sez.~\ref{sec:sess_proc_group}) è uguale + al valore assoluto di \param{pid}. \\ + $-1$& \const{WAIT\_ANY} & attende per un figlio qualsiasi, usata in + questa maniera è equivalente a \func{wait}.\\ + $0$ &\const{WAIT\_MYPGRP}&attende per un figlio il cui + \itindex{process~group} \textit{process group} è + uguale a quello del processo chiamante. \\ + $>0$& -- & attende per un figlio il cui \acr{pid} è uguale + al valore di \param{pid}.\\ \hline \end{tabular} \caption{Significato dei valori dell'argomento \param{pid} della funzione @@ -1058,9 +1062,9 @@ processi in Unix 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 stack, lo -heap, i dati ed il testo del processo corrente con un nuovo programma letto da -disco. +creato un nuovo processo, la funzione semplicemente rimpiazza lo +\itindex{stack} stack, lo \itindex{heap} heap, i dati ed il testo del processo +corrente con un nuovo programma letto da disco. Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata famiglia di funzioni) che possono essere usate per questo compito, in realtà @@ -1075,9 +1079,9 @@ famiglia di funzioni) che possono essere usate per questo compito, in realt \begin{errlist} \item[\errcode{EACCES}] il file non è eseguibile, oppure il filesystem è montato in \cmd{noexec}, oppure non è un file regolare o un interprete. - \item[\errcode{EPERM}] il file ha i bit \acr{suid} o \acr{sgid}, l'utente - non è root, il processo viene tracciato, o il filesystem è montato con - l'opzione \cmd{nosuid}. + \item[\errcode{EPERM}] il file ha i bit \itindex{suid~bit} \acr{suid} o + \itindex{sgid~bit} \acr{sgid}, l'utente non è root, il processo viene + tracciato, o il filesystem è montato con l'opzione \cmd{nosuid}. \item[\errcode{ENOEXEC}] il file è in un formato non eseguibile o non riconosciuto come tale, o compilato per un'altra architettura. \item[\errcode{ENOENT}] il file o una delle librerie dinamiche o l'interprete @@ -1213,8 +1217,8 @@ la lista completa (\acr{ppid}); \item l'\textsl{user-ID reale}, il \textit{group-ID reale} ed i \textsl{group-ID supplementari} (vedi sez.~\ref{sec:proc_access_id}); -\item il \textit{session id} (\acr{sid}) ed il \textit{process group-ID} - (\acr{pgid}), vedi sez.~\ref{sec:sess_proc_group}; +\item il \textit{session ID} (\acr{sid}) ed il \itindex{process~group} + \textit{process group ID} (\acr{pgid}), vedi sez.~\ref{sec:sess_proc_group}; \item il terminale di controllo (vedi sez.~\ref{sec:sess_ctrl_term}); \item il tempo restante ad un allarme (vedi sez.~\ref{sec:sig_alarm_abort}); \item la directory radice e la directory di lavoro corrente (vedi @@ -1254,10 +1258,11 @@ 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 \acr{suid} bit o lo \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 dettagli vedi sez.~\ref{sec:proc_perms}). +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 +dettagli vedi sez.~\ref{sec:proc_perms}). Se il file da eseguire è in formato \emph{a.out} e necessita di librerie condivise, viene lanciato il \textit{linker} dinamico \cmd{/lib/ld.so} prima @@ -1307,22 +1312,19 @@ problematiche connesse ad una gestione accorta dei privilegi. 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{capability}\textit{capabilities}, le ACL per i file o il - \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 + 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. -%Benché il sistema sia piuttosto semplice (è basato su un solo livello di -% separazione) il sistema permette una -%notevole flessibilità, - 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 identificare uno specifico utente o un gruppo di utenti, per poi poter @@ -1406,12 +1408,13 @@ sez.~\ref{sec:file_perm_overview}). Questi identificatori normalmente sono identici ai corrispondenti del gruppo \textit{real} tranne nel caso in cui, come accennato in -sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit -\acr{suid} o \acr{sgid} impostati (il significato di questi bit è affrontato -in dettaglio in sez.~\ref{sec:file_suid_sgid}). In questo caso essi saranno -impostati all'utente e al gruppo proprietari del file. Questo consente, per -programmi in cui ci sia necessità, di dare a qualunque utente normale -privilegi o permessi di un altro (o dell'amministratore). +sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i +bit \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid} impostati +(il significato di questi bit è affrontato in dettaglio in +sez.~\ref{sec:file_suid_sgid}). In questo caso essi saranno impostati +all'utente e al gruppo proprietari del file. Questo consente, per programmi in +cui ci sia necessità, di dare a qualunque utente normale privilegi o permessi +di un altro (o dell'amministratore). Come nel caso del \acr{pid} e del \acr{ppid}, anche tutti questi identificatori possono essere letti attraverso le rispettive funzioni: @@ -1455,9 +1458,10 @@ L'\textsl{user-ID salvato} ed il \textsl{group-ID salvato} sono copie 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 \acr{suid} o -\acr{sgid}. Essi quindi consentono di tenere traccia di quale fossero utente -e gruppo effettivi all'inizio dell'esecuzione di un nuovo programma. +dopo che questi sono stati impostati tenendo conto di eventuali +\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. L'\textsl{user-ID di filesystem} e il \textsl{group-ID di filesystem} sono un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS @@ -1508,10 +1512,11 @@ all'\textsl{user-ID salvato}. Negli altri casi viene segnalato un errore (con \errcode{EPERM}). Come accennato l'uso principale di queste funzioni è quello di poter -consentire ad un programma con i bit \acr{suid} o \acr{sgid} impostati (vedi -sez.~\ref{sec:file_suid_sgid}) di riportare l'\textsl{user-ID effettivo} a -quello dell'utente che ha lanciato il programma, effettuare il lavoro che non -necessita di privilegi aggiuntivi, ed eventualmente tornare indietro. +consentire ad un programma con i bit \itindex{suid~bit} \acr{suid} o +\itindex{sgid~bit} \acr{sgid} impostati (vedi sez.~\ref{sec:file_suid_sgid}) +di riportare l'\textsl{user-ID effettivo} a quello dell'utente che ha lanciato +il programma, effettuare il lavoro che non necessita di privilegi aggiuntivi, +ed eventualmente tornare indietro. Come esempio per chiarire l'uso di queste funzioni prendiamo quello con cui viene gestito l'accesso al file \file{/var/log/utmp}. In questo file viene @@ -1859,20 +1864,270 @@ compila con il flag \cmd{-ansi}, scrivere codice portabile. -\subsection{La gestione delle capabilities} +\subsection{La gestione delle \textit{capabilities}} \label{sec:proc_capabilities} -Da fare + +\itindbeg{capabilities} + +Come accennato in sez.~\ref{sec:proc_access_id} l'architettura classica della +gestione dei privilegi in un sistema unix-like ha il sostanziale problema di +fornire all'amministratore dei poteri troppo ampi, questo comporta che anche +quando di siamo predisposte delle protezioni per in essere in grado di +difendersi dagli effetti di una eventuale compromissione del sistema (come +montare un filesystem in sola lettura per impedirne modifiche), una volta che +questa sia stata effettuata e si siano ottenuti i privilegi di amministratore, +queste potranno essere comunque rimosse (nel caso dell'esempio si potrà sempre +rimontare il sistema in lettura-scrittura). + +Il problema consiste nel fatto che nell'architettura tradizionale di un +sistema unix-like i controlli di accesso sono basati su un solo livello di +separazione: per i processi normali essi sono posti in atto, mentre per i +processi con i privilegi di amministratore essi non vengono neppure eseguiti. +Dato che i privilegi sono sempre gli stessi, non esiste modo per evitare che +un processo con diritti di amministratore non possa eseguire certe operazioni. +Per ovviare a tutto ciò, a partire dai kernel della serie 2.2, è stato +introdotto un meccanismo, detto \textit{capabilities}, che consentisse di +suddividere i vari privilegi tradizionalmente associati all'amministratore in +un insieme di \textsl{capacità} distinte. + +Queste capacità possano essere abilitate e disabilitate in maniera +indipendente per ciascun processo, permettendo una granularità molto più fine +nella distribuzione dei privilegi. Il meccanismo completo delle +\textit{capabilities} prevederebbe anche la possibilità di associare le stesse +\textit{capabilities} anche ai singoli file +eseguibili,\footnote{l'implementazione di Linux si rifà ad una bozza per + quello che dovrebbe divenire lo standard POSIX.1e, che prevede questa + funzionalità.} in modo da poter stabilire quali capacità possono essere +utilizzate quando viene messo in esecuzione uno specifico programma; +attualmente\footnote{vale a dire almeno fino al kernel 2.6.13, e non è + disponibile al momento neanche nessuna realizzazione sperimentale.} questa +funzionalità non è implementata. + +Per gestire questo nuovo meccanismo ciascun processo porta con sé tre distinti +insiemi di \textit{capabilities}, che vengono denominati rispettivamente +\textit{effective}, \textit{permitted} ed \textit{inherited}. Questi insiemi +vengono mantenuti in forma di tre diverse maschere binarie,\footnote{il kernel + li mantiene, come i vari identificatori di sez.~\ref{sec:proc_setuid}, + all'interno della \struct{task\_struct} di ciascun processo (vedi + fig.~\ref{fig:proc_task_struct}), nei tre campi \texttt{cap\_effective}, + \texttt{cap\_inheritable}, \texttt{cap\_permitted} del tipo + \texttt{kernel\_cap\_t} (definito come intero a 32 bit), il che comporta un + massimo di 32 \textit{capabilities} distinte.} in cui ciascun bit +corrisponde ad una capacità diversa; se ne è riportato l'elenco,\footnote{si + tenga presente che l'elenco delle \textit{capabilities} presentato questa + tabella, ripreso dalla relativa pagina di manuale (accessibile con + \texttt{man capabilities}), è quello aggiornato al kernel 2.6.6.} con una +breve descrizione, ed il nome delle costanti che identificano i singoli bit, +in tab.~\ref{tab:proc_capabilities}. + + +\begin{table}[!hbt] + \centering + \footnotesize + \begin{tabular}{|l|p{12cm}|} + \hline + \textbf{Capacità}&\textbf{Descrizione}\\ + \hline + \hline + \const{CAP\_CHOWN} & la capacità di cambiare proprietario e gruppo + proprietario di un file (vedi + sez.~\ref{sec:file_chown}).\\ + \const{CAP\_DAC\_OVERRIDE}& la capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione dei + file, (vedi sez.~\ref{sec:file_access_control}) + caratteristici del modello classico del + controllo di accesso chiamato + \itindex{Discrectionary~Access~Control~(DAC)} + \textit{Discrectionary Access Control} (da cui + il nome DAC).\\ + \const{CAP\_DAC\_READ\_SEARCH}& la capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione per + le directory (vedi + sez.~\ref{sec:file_access_control}).\\ + \const{CAP\_FOWNER} & la capacità di evitare il controllo che + l'user-ID effettivo del processo (o meglio il + \textit{filesystem user-ID}, vedi + sez.~\ref{sec:proc_setuid}) coincida con + quello del proprietario di un file per tutte + le operazioni privilegiate non coperte dalle + precedenti \const{CAP\_DAC\_OVERRIDE} e + \const{CAP\_DAC\_READ\_SEARCH}. Queste + comprendono i cambiamenti dei permessi e dei + tempi del file (vedi sez.~\ref{sec:file_chmod} e + sez.~\ref{sec:file_utime}), le impostazioni degli + attributi estesi (con il comando \cmd{chattr}) e + delle ACL, poter ignorare lo + \itindex{sticky~bit} \textit{sticky bit} nella + cancellazione dei file (vedi + sez.~\ref{sec:file_sticky}), la possibilità di + impostare il flag di \const{O\_NOATIME} con + \func{open} e \func{fcntl} (vedi + sez.~\ref{sec:file_open} e + sez.~\ref{sec:file_fcntl}).\\ + \const{CAP\_FSETID} & la capacità di evitare la cancellazione + automatica dei bit \itindex{suid~bit} \acr{suid} + e \itindex{sgid~bit} \acr{sgid} quando un file + per i quali sono impostati viene modificato da + un processo senza questa capacità e la capacità + di impostare il bit \acr{sgid} su un file anche + quando questo è relativo ad un gruppo cui non si + appartiene (vedi sez.~\ref{sec:file_chmod}).\\ + \const{CAP\_IPC\_LOCK} & la capacità di effettuare il \textit{memory + locking} \itindex{memory~locking} con le + funzioni \func{mlock}, \func{mlockall}, + \func{shmctl}, \func{mmap} (vedi + sez.~\ref{sec:proc_mem_lock} e + sez.~\ref{sec:file_memory_map}). \\ + \const{CAP\_IPC\_OWNER} & la capacità di evitare il controllo dei permessi + per le operazioni sugli oggetti di + intercomunicazione fra processi (vedi + sez.~\ref{sec:ipc_sysv}).\\ + \const{CAP\_KILL} & la capacità di mandare segnali a qualunque + processo (vedi sez.~\ref{sec:sig_kill_raise}).\\ + \const{CAP\_LEASE} & la capacità di creare dei \textit{file lease} + \index{file!lease} su di un file (vedi + sez.~\ref{sec:file_asyncronous_lease}) + indipendentemente dalla proprietà dello + stesso.\footnotemark\\ + \const{CAP\_LINUX\_IMMUTABLE}& la capacità di impostare gli attributi + \textit{immutable} e \textit{append only} per i + file su un filesystem che supporta questi + attributi estesi.\\ + \const{CAP\_MKNOD} & la capacità di creare file di dispositivo con la + funzione \func{mknod} (vedi + sez.~\ref{sec:file_mknod}).\footnotemark\\ + \const{CAP\_NET\_ADMIN} & la capacità di eseguire alcune operazioni + privilegiate sulla rete (impostare le opzioni + privilegiate dei socket, abilitare il + multicasting, impostare interfacce di rete e + tabella di instradamento).\\ + \const{CAP\_NET\_BIND\_SERVICE}& la capacità di porre in ascolto server + su porte riservate (vedi + sez.~\ref{sec:TCP_func_bind}).\\ + \const{CAP\_NET\_BROADCAST}& la capacità di consentire l'uso di socket in + broadcast e multicast.\\ + \const{CAP\_NET\_RAW} & la capacità di usare socket \texttt{RAW} e + \texttt{PACKET} (quelli che permettono di creare + pacchetti nei protocolli di basso livello).\\ + \const{CAP\_SETGID} & la capacità di manipolare i group ID dei + processi, sia il principale che i supplementari, + (vedi sez.~\ref{sec:proc_setgroups} che quelli + trasmessi tramite i \index{socket} socket + \textit{unix domain} (vedi + sez.~\ref{sec:unix_socket}).\\ + \const{CAP\_SETPCAP} & la capacità di impostare o rimuovere una capacità + (limitatamente a quelle che il processo + chiamante ha nel suo insieme di capacità + permesse) da qualunque processo.\\ + \const{CAP\_SETUID} & la capacità di manipolare gli user ID del + processo (e trasmettere un valore arbitrario + tramite i socket unix domain).\\ + \const{CAP\_SYS\_ADMIN} & la capacità di eseguire una serie di compiti + amministrativi (come impostare le quote, + attivare e disattivare la swap, montare, + rimontare e smontare filesystem, ecc.). \\ + \const{CAP\_SYS\_BOOT} & la capacità di fare eseguire un reboot del + sistema.\\ + \const{CAP\_SYS\_CHROOT}& la capacità di eseguire la funzione + \func{chroot} (vedi + sez.~\ref{sec:file_chroot}).\\ + \const{CAP\_SYS\_MODULE}& la capacità di caricare e rimuovere moduli del + kernel. \\ + \const{CAP\_SYS\_NICE} & la capacità di modificare le priorità dei + processi (vedi sez.~\ref{sec:proc_priority}). \\ + \const{CAP\_SYS\_PACCT} & la capacità di usare le funzioni di + \textit{accounting} dei processi (vedi + sez.~\ref{sec:sys_bsd_accounting}).\\ + \const{CAP\_SYS\_RAWIO} & la capacità di eseguire operazioni sulle porte + di I/O con \func{ioperm} e \func{iopl} (vedi + sez.~\ref{sec:file_io_port}).\\ + \const{CAP\_SYS\_RESOURCE}& la capacità di superare le limitazioni sulle + risorse, aumentare le quote disco, usare lo + spazio disco riservato all'amministratore.\\ + \const{CAP\_SYS\_TIME} & la capacità di modificare il tempo di sistema + (vedi sez.~\ref{sec:sys_time}).\\ + \const{CAP\_SYS\_TTY\_CONFIG}& la capacità di simulare un \textit{hangup} + della console, con la funzione + \func{vhangup}.\\ + \const{CAP\_SYS\_PTRACE}& consente di tracciare qualunque processo con + \func{ptrace} (vedi + sez.~\ref{sec:xxx_ptrace}).\\ +% TODO documentatare ptrace + \hline + \end{tabular} + \caption{Le costanti che identificano le \textit{capabilities} presenti nel + kernel.} +\label{tab:proc_capabilities} +\end{table} + +\footnotetext{questa capacità è presente soltato a partire dai kernel della + serie 2.4.x.} + +\footnotetext{questa capacità è presente soltato a partire dai kernel della + serie 2.4.x.} + + +L'utilizzo di tre distinti insiemi serve a fornire una interfaccia flessibile +per l'uso delle \textit{capabilities}, con scopi analoghi a quelli per cui +sono mantenuti i diversi insiemi di identificatori di +sez.~\ref{sec:proc_setuid}; il loro significato è il seguente: +\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}} +\item[\textit{effective}] l'insieme delle \textit{capabilities} + ``\textsl{effettive}'', cioè quelle che vengono effettivamente usate dal + kernel per eseguire il controllo di accesso per le operazioni compiute dal + processo. +\item[\textit{permitted}] l'insieme delle \textit{capabilities} + ``\textsl{permesse}'', cioè l'insieme di quelle che un processo \textsl{può} + impostare come \textsl{effettive} se ha la capacità \const{CAP\_SETPCAP}. Se + un processo cancella una capacità da questo insieme non potrà più + riassumerla (almeno che non esegua un programma che è \acr{suid} di root). +\item[\textit{inherited}] l'insieme delle \textit{capabilities} + \textsl{ereditate}, cioè quelle che vengono trasmesse ad un nuovo programma + eseguito attraverso una chiamata ad \func{exec} (con l'eccezione del caso + che questo sia \acr{suid} di root). +\end{basedescript} + + +Oltre a questi tre insiemi relativi al singolo processo il kernel mantiene un +valore generale per tutto il sistema, chiamato +\index{capabilities~bounding~set} \textit{capabilities bounding set}. Questo +è un parametro di sistema, accessibile attraverso il contenuto del file +\file{/proc/sys/kernel/cap-bound}, che consente di impostare un limite +generale alle capacità che possono essere accordate ai vari processi. + +Il meccanismo prevede infatti che nell'esecuzione di una \func{exec} venga +utilizzato il valore mantenuto nell'insieme \textit{inherited} per +inizializzare tutti gli insiemi + + + +vengano +impostati come valori per le \textit{capabilities} (per tutti e tre gli +insiemi) del nuovo programma quelle + + + + + + + + + + + + +\itindend{capabilities} \section{La gestione della priorità di esecuzione} \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 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. +lo \textit{scheduler}\itindex{scheduler} assegna la CPU ai vari processi +attivi. In particolare prenderemo in esame i vari meccanismi con cui viene +gestita l'assegnazione del tempo di CPU, ed illustreremo le varie funzioni di +gestione. \subsection{I meccanismi di \textit{scheduling}} @@ -2105,9 +2360,10 @@ l'utente correnti. \param{which} & \param{who} & \textbf{Significato} \\ \hline \hline - \const{PRIO\_PROCESS} & \type{pid\_t} & processo \\ - \const{PRIO\_PRGR} & \type{pid\_t} & process group \\ - \const{PRIO\_USER} & \type{uid\_t} & utente \\ + \const{PRIO\_PROCESS} & \type{pid\_t} & processo \\ + \const{PRIO\_PRGR} & \type{pid\_t} & \itindex{process~group} + \textit{process group} \\ + \const{PRIO\_USER} & \type{uid\_t} & utente \\ \hline \end{tabular} \caption{Legenda del valore dell'argomento \param{which} e del tipo @@ -2719,10 +2975,11 @@ multi-thread, ma si hanno gli stessi problemi quando si vogliono chiamare delle funzioni all'interno dei gestori dei segnali. Fintanto che una funzione opera soltanto con le variabili locali è rientrante; -queste infatti vengono allocate nello stack, e un'altra invocazione non fa -altro che allocarne un'altra copia. Una funzione può non essere rientrante -quando opera su memoria che non è nello stack. Ad esempio una funzione non è -mai rientrante se usa una variabile globale o statica. +queste infatti vengono allocate nello \itindex{stack} stack, e un'altra +invocazione non fa altro che allocarne un'altra copia. Una funzione può non +essere rientrante quando opera su memoria che non è nello \itindex{stack} +stack. Ad esempio una funzione non è mai rientrante se usa una variabile +globale o statica. Nel caso invece la funzione operi su un oggetto allocato dinamicamente, la cosa viene a dipendere da come avvengono le operazioni: se l'oggetto è creato diff --git a/session.tex b/session.tex index 68fa465..c8f25ef 100644 --- a/session.tex +++ b/session.tex @@ -75,19 +75,21 @@ questo potr Per questo l'esecuzione di un comando può originare più di un processo; quindi nella gestione del job control non si può far riferimento ai singoli processi. Per questo il kernel prevede la possibilità di raggruppare più processi in un -\textit{process group} (detto anche \textsl{raggruppamento di processi}, vedi -sez.~\ref{sec:sess_proc_group}) e la shell farà sì che tutti i processi che -originano da una riga di comando appartengano allo stesso raggruppamento, in -modo che le varie funzioni di controllo, ed i segnali inviati dal terminale, -possano fare riferimento ad esso. +\itindex{process~group} \textit{process group} (detto anche +\textsl{raggruppamento di processi}, vedi sez.~\ref{sec:sess_proc_group}) e la +shell farà sì che tutti i processi che originano da una riga di comando +appartengano allo stesso raggruppamento, in modo che le varie funzioni di +controllo, ed i segnali inviati dal terminale, possano fare riferimento ad +esso. In generale allora all'interno di una sessione avremo un eventuale (può non -esserci) \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}). +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}). 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 @@ -110,8 +112,10 @@ sez.~\ref{sec:proc_wait}). \subsection{I \textit{process group} e le \textsl{sessioni}} \label{sec:sess_proc_group} +\itindbeg{process~group} + Come accennato in sez.~\ref{sec:sess_job_control_overview} nel job control i -processi vengono raggruppati in \textit{process group} e \textit{sessioni}; +processi vengono raggruppati in \textit{process group} e \textsl{sessioni}; per far questo vengono utilizzati due ulteriori identificatori (oltre quelli visti in sez.~\ref{sec:proc_pid}) che il kernel associa a ciascun processo:\footnote{in Linux questi identificatori sono mantenuti nei campi @@ -178,15 +182,15 @@ 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 \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 \funcd{setpgrp},\footnote{questa è la - definizione di POSIX.1, BSD definisce una funzione con lo stesso nome, che - però è identica a \func{setpgid}; nelle \acr{glibc} viene sempre usata - sempre questa definizione, a meno di non richiedere esplicitamente la - compatibilità all'indietro con BSD, definendo la macro - \macro{\_BSD\_SOURCE}.} il cui prototipo è: +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 +\funcd{setpgrp},\footnote{questa è la definizione di POSIX.1, BSD definisce + una funzione con lo stesso nome, che però è identica a \func{setpgid}; nelle + \acr{glibc} viene sempre usata sempre questa definizione, a meno di non + richiedere esplicitamente la compatibilità all'indietro con BSD, definendo + la macro \macro{\_BSD\_SOURCE}.} il cui prototipo è: \begin{prototype}{unistd.h}{int setpgrp(void)} Modifica il \acr{pgid} al valore del \acr{pid} del processo corrente. @@ -195,11 +199,11 @@ raggruppamento si crea con la funzione \funcd{setpgrp},\footnote{questa \end{prototype} La funzione, assegnando al \acr{pgid} il valore del \acr{pid} processo -corrente, rende questo \textit{group leader} di un nuovo raggruppamento, tutti -i successivi processi da esso creati apparterranno (a meno di non cambiare di -nuovo il \acr{pgid}) al nuovo raggruppamento. È possibile invece spostare un -processo da un raggruppamento ad un altro con la funzione \funcd{setpgid}, il -cui prototipo è: +corrente, rende questo \itindex{process~group~leader} \textit{group leader} di +un nuovo raggruppamento, tutti i successivi processi da esso creati +apparterranno (a meno di non cambiare di nuovo il \acr{pgid}) al nuovo +raggruppamento. È possibile invece spostare un processo da un raggruppamento +ad un altro con la funzione \funcd{setpgid}, il cui prototipo è: \begin{prototype}{unistd.h}{int setpgid(pid\_t pid, pid\_t pgid)} Assegna al \acr{pgid} del processo \param{pid} il valore \param{pgid}. @@ -228,13 +232,13 @@ processo selezionato; pertanto \func{setpgrp} 0)}. Di norma questa funzione viene usata dalla shell quando si usano delle -pipeline, per mettere nello stesso process group tutti i programmi lanciati su -ogni linea di comando; essa viene chiamata dopo una \func{fork} 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 +pipeline, per mettere nello stesso \textit{process group} tutti i programmi +lanciati su ogni linea di comando; essa viene chiamata dopo una \func{fork} +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}. Si noti come nessuna delle funzioni esaminate finora permetta di spostare un @@ -260,21 +264,22 @@ unico componente. Inoltre la funzione distacca il processo da ogni terminale di controllo (torneremo sull'argomento in sez.~\ref{sec:sess_ctrl_term}) cui fosse in precedenza associato. -La funzione ha successo soltanto se il processo non è già leader di un -\textit{process group}, per cui per usarla di norma si esegue una \func{fork} -e si esce, per poi chiamare \func{setsid} nel processo figlio, in modo che, -avendo questo lo stesso \acr{pgid} del padre ma un \acr{pid} diverso, non ci -siano possibilità di errore.\footnote{potrebbe sorgere il dubbio che, per il - riutilizzo dei valori dei \acr{pid} fatto nella creazione dei nuovi processi - (vedi sez.~\ref{sec:proc_pid}), il figlio venga ad assumere un valore - corrispondente ad un process group esistente; questo viene evitato dal - kernel che considera come disponibili per un nuovo \acr{pid} solo valori che - non corrispondono ad altri \acr{pid}, \acr{pgid} o \acr{sid} in uso nel +La funzione ha successo soltanto se il processo non è già +\itindex{process~group~leader} leader di un \textit{process group}, per cui +per usarla di norma si esegue una \func{fork} e si esce, per poi chiamare +\func{setsid} nel processo figlio, in modo che, avendo questo lo stesso +\acr{pgid} del padre ma un \acr{pid} diverso, non ci siano possibilità di +errore.\footnote{potrebbe sorgere il dubbio che, per il riutilizzo dei valori + dei \acr{pid} fatto nella creazione dei nuovi processi (vedi + sez.~\ref{sec:proc_pid}), il figlio venga ad assumere un valore + corrispondente ad un \textit{process group} esistente; questo viene evitato + dal kernel che considera come disponibili per un nuovo \acr{pid} solo valori + che non corrispondono ad altri \acr{pid}, \acr{pgid} o \acr{sid} in uso nel sistema.} Questa funzione viene usata di solito nel processo di login (per i dettagli vedi sez.~\ref{sec:sess_login}) per raggruppare in una sessione tutti i comandi eseguiti da un utente dalla sua shell. - +\itindend{process~group} \subsection{Il terminale di controllo e il controllo di sessione} \label{sec:sess_ctrl_term} @@ -344,19 +349,20 @@ funzione \funcd{tcsetpgrp}, il cui prototipo \noindent la funzione può essere eseguita con successo solo da un processo nella stessa sessione e con lo stesso terminale di controllo. -Come accennato in sez.~\ref{sec:sess_job_control_overview}, tutti i processi (e -relativi raggruppamenti) che non fanno parte del gruppo di \textit{foreground} -sono detti in \textit{background}; se uno si essi cerca di accedere al -terminale di controllo provocherà l'invio da parte del kernel di uno dei due -segnali \const{SIGTTIN} o \const{SIGTTOU} (a seconda che l'accesso sia stato -in lettura o scrittura) a tutto il suo \textit{process group}; dato che il -comportamento di default di questi segnali (si riveda quanto esposto in -sez.~\ref{sec:sig_job_control}) è di fermare il processo, di norma questo -comporta che tutti i membri del gruppo verranno fermati, ma non si avranno -condizioni di errore.\footnote{la shell in genere notifica comunque un - avvertimento, avvertendo la presenza di processi bloccati grazie all'uso di - \func{waitpid}.} Se però si bloccano o ignorano i due segnali citati, le -funzioni di lettura e scrittura falliranno con un errore di \errcode{EIO}. +Come accennato in sez.~\ref{sec:sess_job_control_overview}, tutti i processi +(e relativi raggruppamenti) che non fanno parte del gruppo di +\textit{foreground} sono detti in \textit{background}; se uno si essi cerca di +accedere al terminale di controllo provocherà l'invio da parte del kernel di +uno dei due segnali \const{SIGTTIN} o \const{SIGTTOU} (a seconda che l'accesso +sia stato in lettura o scrittura) a tutto il suo \itindex{process~group} +\textit{process group}; dato che il comportamento di default di questi segnali +(si riveda quanto esposto in sez.~\ref{sec:sig_job_control}) è di fermare il +processo, di norma questo comporta che tutti i membri del gruppo verranno +fermati, ma non si avranno condizioni di errore.\footnote{la shell in genere + notifica comunque un avvertimento, avvertendo la presenza di processi + bloccati grazie all'uso di \func{waitpid}.} Se però si bloccano o ignorano i +due segnali citati, le funzioni di lettura e scrittura falliranno con un +errore di \errcode{EIO}. Un processo può controllare qual è il gruppo di \textit{foreground} associato ad un terminale con la funzione \funcd{tcgetpgrp}, il cui prototipo è: @@ -428,26 +434,28 @@ terminale, in assenza di un processo che sia in grado di effettuare il controllo dello stesso. Questa è la situazione in cui si ha quello che viene chiamato un -\textit{orphaned process group}. Lo standard POSIX.1 lo definisce come un -\textit{process group} i cui processi hanno come padri esclusivamente o altri -processi nel raggruppamento, o processi fuori della sessione. Lo standard -prevede inoltre che se la terminazione di un processo fa sì che un -raggruppamento di processi diventi orfano e se i suoi membri sono bloccati, ad -essi vengano inviati in sequenza i segnali di \const{SIGHUP} e -\const{SIGCONT}. +\itindex{process~group~orphaned} \textit{orphaned process group}. Lo standard +POSIX.1 lo definisce come un \itindex{process~group} \textit{process group} i +cui processi hanno come padri esclusivamente o altri processi nel +raggruppamento, o processi fuori della sessione. Lo standard prevede inoltre +che se la terminazione di un processo fa sì che un raggruppamento di processi +diventi orfano e se i suoi membri sono bloccati, ad essi vengano inviati in +sequenza i segnali di \const{SIGHUP} e \const{SIGCONT}. La definizione può sembrare complicata, e a prima vista non è chiaro cosa tutto ciò abbia a che fare con il problema della terminazione del processo di controllo. Consideriamo allora cosa avviene di norma nel \textit{job control}: una sessione viene creata con \func{setsid} che crea anche un -nuovo process group: per definizione quest'ultimo è sempre \textsl{orfano}, -dato che il padre del leader di sessione è fuori dalla stessa e il nuovo -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}.} +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}.} 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 @@ -522,16 +530,17 @@ indicato dall'amministratore nel file di configurazione del programma, Quando viene lanciato da \cmd{init} il programma parte con i privilegi di amministratore e con un ambiente vuoto; \cmd{getty} si cura di chiamare -\func{setsid} per creare una nuova sessione ed un nuovo process group, e di -aprire il terminale (che così diventa il terminale di controllo della -sessione) in lettura sullo standard input ed in scrittura sullo standard -output e sullo standard error; inoltre effettuerà, qualora servano, ulteriori -settaggi.\footnote{ad esempio, come qualcuno si sarà accorto scrivendo un nome - di login in maiuscolo, può effettuare la conversione automatica dell'input - in minuscolo, ponendosi in una modalità speciale che non distingue fra i due - tipi di caratteri (a beneficio di alcuni vecchi terminali che non - supportavano le minuscole).} Alla fine il programma stamperà un messaggio di -benvenuto per poi porsi in attesa dell'immissione del nome di un utente. +\func{setsid} per creare una nuova sessione ed un nuovo +\itindex{process~group} \textit{process group}, e di aprire il terminale (che +così diventa il terminale di controllo della sessione) in lettura sullo +standard input ed in scrittura sullo standard output e sullo standard error; +inoltre effettuerà, qualora servano, ulteriori settaggi.\footnote{ad esempio, + come qualcuno si sarà accorto scrivendo un nome di login in maiuscolo, può + effettuare la conversione automatica dell'input in minuscolo, ponendosi in + una modalità speciale che non distingue fra i due tipi di caratteri (a + beneficio di alcuni vecchi terminali che non supportavano le minuscole).} +Alla fine il programma stamperà un messaggio di benvenuto per poi porsi in +attesa dell'immissione del nome di un utente. Una volta che si sia immesso il nome di login \cmd{getty} esegue direttamente il programma \cmd{login} con una \func{exevle}, passando come argomento la @@ -616,10 +625,10 @@ occorrer \begin{enumerate} \item Eseguire una \func{fork} e terminare immediatamente il processo padre proseguendo l'esecuzione nel figlio. In questo modo si ha la certezza che - il figlio non è un \textit{process group leader}, (avrà il \acr{pgid} del - padre, ma un \acr{pid} diverso) e si può chiamare \func{setsid} con - successo. Inoltre la shell considererà terminato il comando all'uscita del - padre. + il figlio non è un \itindex{process~group~leader} \textit{process group + leader}, (avrà il \acr{pgid} del padre, ma un \acr{pid} diverso) e si può + chiamare \func{setsid} con successo. Inoltre la shell considererà terminato + il comando all'uscita del padre. \item Eseguire \func{setsid} per creare una nuova sessione ed un nuovo raggruppamento di cui il processo diventa automaticamente il leader, che però non ha associato nessun terminale di controllo. @@ -1969,14 +1978,16 @@ distinti: \end{description} -% -% Qui c'è da mettere tutta la parte sui terminali virtuali, e la gestione -% degli stessi -% \section{La gestione dei terminali virtuali} \label{sec:sess_virtual_terminal} +% +% TODO terminali virtuali +% Qui c'è da mettere tutta la parte sui terminali virtuali, e la gestione +% degli stessi +% + Da fare. \subsection{I terminali virtuali} diff --git a/signal.tex b/signal.tex index 66485bb..aa47a4d 100644 --- a/signal.tex +++ b/signal.tex @@ -60,7 +60,7 @@ il seguente: \code{C-z};\footnote{indichiamo con \code{C-x} la pressione simultanea al tasto \code{x} del tasto control (ctrl in molte tastiere).} \item l'esecuzione di una \func{kill} o di una \func{raise} da parte del - processo stesso o di un'altro (solo nel caso della \func{kill}). + processo stesso o di un altro (solo nel caso della \func{kill}). \end{itemize*} Ciascuno di questi eventi (compresi gli ultimi due che pure sono controllati @@ -125,12 +125,12 @@ segnale, ma non di un segnale, pur mantenendo memoria del fatto che è avvenuto. Nella semantica \textsl{affidabile} (quella utilizzata da Linux e da ogni Unix -moderno) il gestore una volta installato resta attivo e non si hanno -tutti i problemi precedenti. In questa semantica i segnali vengono -\textsl{generati} dal kernel per un processo all'occorrenza dell'evento che -causa il segnale. In genere questo viene fatto dal kernel impostando l'apposito -campo della \struct{task\_struct} del processo nella process table (si veda -fig.~\ref{fig:proc_task_struct}). +moderno) il gestore una volta installato resta attivo e non si hanno tutti i +problemi precedenti. In questa semantica i segnali vengono \textsl{generati} +dal kernel per un processo all'occorrenza dell'evento che causa il segnale. In +genere questo viene fatto dal kernel impostando l'apposito campo della +\struct{task\_struct} del processo nella \itindex{process~table} +\textit{process table} (si veda fig.~\ref{fig:proc_task_struct}). Si dice che il segnale viene \textsl{consegnato} al processo (dall'inglese \textit{delivered}) quando viene eseguita l'azione per esso prevista, mentre @@ -261,10 +261,10 @@ 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 -in particolare della memoria e dello 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 vengono generati con una -\func{kill}. +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 +vengono generati con una \func{kill}. \section{La classificazione dei segnali} @@ -348,8 +348,8 @@ In alcuni casi alla terminazione del processo 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 -per esaminare lo stato dello stack e delle variabili al momento della -ricezione del segnale. +per esaminare lo stato dello \itindex{stack} stack e delle variabili al +momento della ricezione del segnale. \begin{table}[htb] \footnotesize @@ -448,6 +448,7 @@ programma al momento della terminazione. Questi segnali sono: % molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo % standard IEEE per le operazioni in virgola mobile definisce varie eccezioni % aritmetiche e richiede che esse siano notificate. +% TODO trovare altre info su SIGFPE e trattare la notifica delle eccezioni \item[\const{SIGILL}] Il nome deriva da \textit{illegal instruction}, significa che il programma sta cercando di eseguire una istruzione @@ -456,10 +457,10 @@ programma al momento della terminazione. Questi segnali sono: file eseguibile è corrotto o si stanno cercando di eseguire dei dati. Quest'ultimo caso può accadere quando si passa un puntatore sbagliato al posto di un puntatore a funzione, o si eccede la scrittura di un vettore di - una variabile locale, andando a corrompere lo stack. Lo stesso segnale viene - generato in caso di overflow dello stack o di problemi nell'esecuzione di un - gestore. Se il gestore ritorna il comportamento del processo è - indefinito. + una variabile locale, andando a corrompere lo \itindex{stack} stack. Lo + stesso segnale viene generato in caso di overflow dello \itindex{stack} + stack o di problemi nell'esecuzione di un gestore. Se il gestore ritorna il + comportamento del processo è indefinito. \item[\const{SIGSEGV}] Il nome deriva da \textit{segment violation}, e significa che il programma sta cercando di leggere o scrivere in una zona di memoria protetta al di fuori di quella che gli è stata riservata dal @@ -473,9 +474,9 @@ programma al momento della terminazione. Questi segnali sono: \const{SIGSEGV} questo è un segnale che viene generato di solito quando si dereferenzia un puntatore non inizializzato, la differenza è che \const{SIGSEGV} indica un accesso non permesso su un indirizzo esistente - (tipo fuori dallo heap o dallo stack), mentre \const{SIGBUS} indica - l'accesso ad un indirizzo non valido, come nel caso di un puntatore non - allineato. + (tipo fuori dallo heap o dallo \itindex{stack} stack), mentre \const{SIGBUS} + indica l'accesso ad un indirizzo non valido, come nel caso di un puntatore + non allineato. \item[\const{SIGABRT}] Il nome deriva da \textit{abort}. Il segnale indica che il programma stesso ha rilevato un errore che viene riportato chiamando la funzione \func{abort} che genera questo segnale. @@ -656,7 +657,7 @@ processo, questi segnali sono: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{SIGPIPE}] Sta per \textit{Broken pipe}. Se si usano delle pipe, (o delle FIFO o dei socket) è necessario, prima che un processo inizi a - scrivere su una di esse, che un'altro l'abbia aperta in lettura (si veda + scrivere su una di esse, che un altro l'abbia aperta in lettura (si veda sez.~\ref{sec:ipc_pipes}). Se il processo in lettura non è partito o è terminato inavvertitamente alla scrittura sulla pipe il kernel genera questo segnale. Se il segnale è bloccato, intercettato o ignorato la chiamata che @@ -950,7 +951,7 @@ suo prototipo \begin{prototype}{signal.h}{int raise(int sig)} Invia il segnale \param{sig} al processo corrente. - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore, il solo errore restituito è \errval{EINVAL} qualora si sia specificato un numero di segnale invalido.} \end{prototype} @@ -973,7 +974,7 @@ prototipo \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al processo specificato con \param{pid}. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di errore nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] Il segnale specificato non esiste. @@ -1007,12 +1008,14 @@ Una seconda funzione che pu \code{kill(-pidgrp, signal)}; il suo prototipo è: \begin{prototype}{signal.h}{int killpg(pid\_t pidgrp, int signal)} - Invia il segnale \param{signal} al process group \param{pidgrp}. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + Invia il segnale \param{signal} al \itindex{process~group} \textit{process + group} \param{pidgrp}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di errore, gli errori sono gli stessi di \func{kill}.} \end{prototype} -\noindent e permette di inviare un segnale a tutto un \textit{process group} -(vedi sez.~\ref{sec:sess_proc_group}). +\noindent e permette di inviare un segnale a tutto un \itindex{process~group} +\textit{process group} (vedi sez.~\ref{sec:sess_proc_group}). \begin{table}[htb] \footnotesize @@ -1023,11 +1026,11 @@ Una seconda funzione che pu \hline \hline $>0$ & il segnale è mandato al processo con il \acr{pid} indicato.\\ - 0 & il segnale è mandato ad ogni processo del \textit{process group} - del chiamante.\\ + 0 & il segnale è mandato ad ogni processo del \itindex{process~group} + \textit{process group} del chiamante.\\ $-1$ & il segnale è mandato ad ogni processo (eccetto \cmd{init}).\\ - $<-1$ & il segnale è mandato ad ogni processo del process group - $|\code{pid}|$.\\ + $<-1$ & il segnale è mandato ad ogni processo del \textit{process group} + \itindex{process~group} $|\code{pid}|$.\\ \hline \end{tabular} \caption{Valori dell'argomento \param{pid} per la funzione @@ -1117,7 +1120,7 @@ suo prototipo Predispone l'invio di un segnale di allarme alla scadenza dell'intervallo \param{value} sul timer specificato da \param{which}. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori \errval{EINVAL} o \errval{EFAULT}.} \end{prototype} @@ -1213,7 +1216,7 @@ valore corrente di un timer senza modificarlo, Legge in \param{value} il valore del timer specificato da \param{which}. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di errore e restituisce gli stessi errori di \func{getitimer}} \end{prototype} \noindent i cui argomenti hanno lo stesso significato e formato di quelli di @@ -1265,7 +1268,7 @@ segnale Pone il processo in stato di sleep fino al ritorno di un gestore. \bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed - il relativo gestore è ritornato, nel qual caso restituisce -1 e + il relativo gestore è ritornato, nel qual caso restituisce $-1$ e \var{errno} assumerà il valore \errval{EINTR}.} \end{prototype} @@ -1315,8 +1318,8 @@ seguono quella di SUSv2 che prevede il seguente prototipo: Pone il processo in stato di sleep per \param{usec} microsecondi. - \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in - caso di errore, nel qual caso \var{errno} assumerà il valore + \bodydesc{La funzione restituisce zero se l'attesa viene completata, o $-1$ + in caso di errore, nel qual caso \var{errno} assumerà il valore \errval{EINTR}.} \end{prototype} @@ -1331,8 +1334,8 @@ POSIX1.b, il cui prototipo Pone il processo in stato di sleep per il tempo specificato da \param{req}. In caso di interruzione restituisce il tempo restante in \param{rem}. - \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in - caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \bodydesc{La funzione restituisce zero se l'attesa viene completata, o $-1$ + in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] si è specificato un numero di secondi negativo o un numero di nanosecondi maggiore di 999.999.999. @@ -1620,7 +1623,7 @@ segnali: \funcd{sigemptyset}, \funcd{sigfillset}, \funcd{sigaddset}, \bodydesc{Le prime quattro funzioni ritornano 0 in caso di successo, mentre \func{sigismember} ritorna 1 se \param{signum} è in \param{set} e 0 - altrimenti. In caso di errore tutte ritornano -1, con \var{errno} + altrimenti. In caso di errore tutte ritornano $-1$, con \var{errno} impostata a \errval{EINVAL} (il solo errore possibile è che \param{signum} non sia un segnale valido).} \end{functions} @@ -1660,7 +1663,7 @@ da un processo. Il suo prototipo Installa una nuova azione per il segnale \param{signum}. - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} \item[\errcode{EINVAL}] Si è specificato un numero di segnale invalido o si è @@ -1750,8 +1753,8 @@ in tab.~\ref{tab:sig_sa_flag}. \const{SA\_SIGINFO} & Deve essere specificato quando si vuole usare un gestore in forma estesa usando \var{sa\_sigaction} al posto di \var{sa\_handler}.\\ - \const{SA\_ONSTACK} & Stabilisce l'uso di uno stack alternativo per - l'esecuzione del gestore (vedi + \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} stack + alternativo per l'esecuzione del gestore (vedi sez.~\ref{sec:sig_specific_features}).\\ \hline \end{tabular} @@ -1759,6 +1762,8 @@ in tab.~\ref{tab:sig_sa_flag}. \label{tab:sig_sa_flag} \end{table} +% TODO con il 2.6 sono stati aggiunti SA_NOCLDWAIT e altro, documentare + Come si può notare in fig.~\ref{fig:sig_sigaction} \func{sigaction} permette di utilizzare due forme diverse di gestore,\footnote{La possibilità è prevista dallo standard POSIX.1b, ed è stata aggiunta nei kernel della serie 2.1.x @@ -1860,11 +1865,11 @@ estremamente semplice, le funzioni piccole ed usate di frequente (in particolare nel kernel, dove in certi casi le ottimizzazioni dal compilatore, tarate per l'uso in user space, non sono sempre adatte). In tal caso infatti le istruzioni per creare - un nuovo frame nello stack per chiamare la funzione costituirebbero una - parte rilevante del codice, appesantendo inutilmente il programma. - Originariamente questo comportamento veniva ottenuto con delle macro, ma - queste hanno tutta una serie di problemi di sintassi nel passaggio degli - argomenti (si veda ad esempio \cite{PratC}) che in questo modo possono + un nuovo frame nello \itindex{stack} stack per chiamare la funzione + costituirebbero una parte rilevante del codice, appesantendo inutilmente il + programma. Originariamente questo comportamento veniva ottenuto con delle + macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio + degli argomenti (si veda ad esempio \cite{PratC}) che in questo modo possono essere evitati.} @@ -1902,7 +1907,7 @@ segnali; il suo prototipo Cambia la \textsl{maschera dei segnali} del processo corrente. - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} \item[\errcode{EINVAL}] Si è specificato un numero di segnale invalido. @@ -1965,7 +1970,7 @@ sospensione del processo lo standard POSIX ha previsto la funzione Imposta la \textit{signal mask} specificata, mettendo in attesa il processo. - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} \item[\errcode{EINVAL}] Si è specificato un numero di segnale invalido. @@ -2045,7 +2050,7 @@ standard POSIX.1; il suo prototipo Scrive in \param{set} l'insieme dei segnali pendenti. - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore.} \end{prototype} @@ -2058,11 +2063,11 @@ escluderne l'avvenuto invio al momento della chiamata non significa nulla rispetto a quanto potrebbe essere in un qualunque momento successivo. Una delle caratteristiche di BSD, disponibile anche in Linux, è la possibilità -di usare uno stack alternativo per i segnali; è cioè possibile fare usare al -sistema un altro stack (invece di quello relativo al processo, vedi -sez.~\ref{sec:proc_mem_layout}) solo durante l'esecuzione di un -gestore. L'uso di uno stack alternativo è del tutto trasparente ai -gestori, occorre però seguire una certa procedura: +di usare uno \itindex{stack} stack alternativo per i segnali; è cioè possibile +fare usare al sistema un altro \itindex{stack} stack (invece di quello +relativo al processo, vedi sez.~\ref{sec:proc_mem_layout}) solo durante +l'esecuzione di un gestore. L'uso di uno stack alternativo è del tutto +trasparente ai gestori, occorre però seguire una certa procedura: \begin{enumerate} \item Allocare un'area di memoria di dimensione sufficiente da usare come stack alternativo; @@ -2078,24 +2083,24 @@ In genere il primo passo viene effettuato allocando un'opportuna area di memoria con \code{malloc}; in \file{signal.h} sono definite due costanti, \const{SIGSTKSZ} e \const{MINSIGSTKSZ}, che possono essere utilizzate per allocare una quantità di spazio opportuna, in modo da evitare overflow. La -prima delle due è la dimensione canonica per uno stack di segnali e di norma è -sufficiente per tutti gli usi normali. +prima delle due è la dimensione canonica per uno \itindex{stack} stack di +segnali e di norma è sufficiente per tutti gli usi normali. La seconda è lo spazio che occorre al sistema per essere in grado di lanciare il gestore e la dimensione di uno stack alternativo deve essere sempre maggiore di questo valore. Quando si conosce esattamente quanto è lo spazio necessario al gestore gli si può aggiungere questo valore per allocare uno -stack di dimensione sufficiente. +\itindex{stack} stack di dimensione sufficiente. -Come accennato, per poter essere usato, lo stack per i segnali deve essere -indicato al sistema attraverso la funzione \funcd{sigaltstack}; il suo -prototipo è: +Come accennato, per poter essere usato, lo \itindex{stack} stack per i segnali +deve essere indicato al sistema attraverso la funzione \funcd{sigaltstack}; il +suo prototipo è: \begin{prototype}{signal.h} {int sigaltstack(const stack\_t *ss, stack\_t *oss)} Installa un nuovo stack per i segnali. - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} @@ -2110,10 +2115,10 @@ Installa un nuovo stack per i segnali. \end{prototype} La funzione prende come argomenti puntatori ad una struttura di tipo -\var{stack\_t}, definita in fig.~\ref{fig:sig_stack_t}. I due valori \param{ss} -e \param{oss}, se non nulli, indicano rispettivamente il nuovo stack da -installare e quello corrente (che viene restituito dalla funzione per un -successivo ripristino). +\var{stack\_t}, definita in fig.~\ref{fig:sig_stack_t}. I due valori +\param{ss} e \param{oss}, se non nulli, indicano rispettivamente il nuovo +\itindex{stack} stack da installare e quello corrente (che viene restituito +dalla funzione per un successivo ripristino). \begin{figure}[!htb] \footnotesize \centering @@ -2125,33 +2130,34 @@ successivo ripristino). \label{fig:sig_stack_t} \end{figure} -Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello stack, -mentre \var{ss\_size} ne indica la dimensione; il campo \var{ss\_flags} invece -indica lo stato dello stack. Nell'indicare un nuovo stack occorre -inizializzare \var{ss\_sp} e \var{ss\_size} rispettivamente al puntatore e -alla dimensione della memoria allocata, mentre \var{ss\_flags} deve essere -nullo. Se invece si vuole disabilitare uno stack occorre indicare +Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello +\itindex{stack} stack, mentre \var{ss\_size} ne indica la dimensione; il campo +\var{ss\_flags} invece indica lo stato dello stack. Nell'indicare un nuovo +stack occorre inizializzare \var{ss\_sp} e \var{ss\_size} rispettivamente al +puntatore e alla dimensione della memoria allocata, mentre \var{ss\_flags} +deve essere nullo. Se invece si vuole disabilitare uno stack occorre indicare \const{SS\_DISABLE} come valore di \var{ss\_flags} e gli altri valori saranno ignorati. Se \param{oss} non è nullo verrà restituito dalla funzione indirizzo e -dimensione dello stack corrente nei relativi campi, mentre \var{ss\_flags} -potrà assumere il valore \const{SS\_ONSTACK} se il processo è in esecuzione -sullo stack alternativo (nel qual caso non è possibile cambiarlo) e -\const{SS\_DISABLE} se questo non è abilitato. - -In genere si installa uno stack alternativo per i segnali quando si teme di -avere problemi di esaurimento dello stack standard o di superamento di un -limite imposto con chiamate del tipo \code{setrlimit(RLIMIT\_STACK, \&rlim)}. -In tal caso infatti si avrebbe un segnale di \const{SIGSEGV}, che potrebbe -essere gestito soltanto avendo abilitato uno stack alternativo. +dimensione dello \itindex{stack} stack corrente nei relativi campi, mentre +\var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il processo è +in esecuzione sullo stack alternativo (nel qual caso non è possibile +cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato. + +In genere si installa uno \itindex{stack} stack alternativo per i segnali +quando si teme di avere problemi di esaurimento dello stack standard o di +superamento di un limite (vedi sez.~\ref{sec:sys_resource_limit}) imposto con +chiamate del tipo \code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso +infatti si avrebbe un segnale di \const{SIGSEGV}, che potrebbe essere gestito +soltanto avendo abilitato uno \itindex{stack} stack alternativo. Si tenga presente che le funzioni chiamate durante l'esecuzione sullo stack alternativo continueranno ad usare quest'ultimo, che, al contrario di quanto -avviene per lo stack ordinario dei processi, non si accresce automaticamente -(ed infatti eccederne le dimensioni può portare a conseguenze imprevedibili). -Si ricordi infine che una chiamata ad una funzione della famiglia -\func{exec} cancella ogni stack alternativo. +avviene per lo \itindex{stack} stack ordinario dei processi, non si accresce +automaticamente (ed infatti eccederne le dimensioni può portare a conseguenze +imprevedibili). Si ricordi infine che una chiamata ad una funzione della +famiglia \func{exec} cancella ogni stack alternativo. Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare \func{longjmp} per uscire da un gestore rientrando direttamente nel corpo @@ -2188,7 +2194,7 @@ due comportamenti il programma deve assumere; i loro prototipi sono: \end{functions} Le due funzioni prendono come primo argomento la variabile su cui viene -salvato il contesto dello stack per permettere il +salvato il contesto dello \itindex{stack} stack per permettere il \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 @@ -2314,7 +2320,7 @@ funzione, \funcd{sigqueue}, il cui prototipo Invia il segnale \param{signo} al processo \param{pid}, restituendo al gestore il valore \param{value}. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EAGAIN}] La coda è esaurita, ci sono già \const{SIGQUEUE\_MAX} @@ -2359,7 +2365,7 @@ meccanismi di comunicazione elementare; la prima di queste funzioni Attende che uno dei segnali specificati in \param{set} sia pendente. - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINTR}] La funzione è stata interrotta. @@ -2404,7 +2410,7 @@ relativi prototipi sono: timeout in \param{timeout}. - \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di + \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori già visti per \func{sigwait}, ai quali si aggiunge, per \func{sigtimedwait}: \begin{errlist} diff --git a/sockctrl.tex b/sockctrl.tex index 13384f3..585e371 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -882,17 +882,18 @@ usare la funzione \funcd{gethostbyaddr}, il cui prototipo In questo caso l'argomento \param{addr} dovrà essere il puntatore ad una appropriata struttura contenente il valore dell'indirizzo IP (o IPv6) che si -vuole risolvere. L'uso del tipo \type{char *} per questo argomento è storico, -il dato dovrà essere fornito in una struttura \struct{in\_addr}\footnote{si - ricordi che, come illustrato in fig.~\ref{fig:sock_sa_ipv4_struct}, questo - in realtà corrisponde ad un numero intero, da esprimere comunque in - \textit{network order}, non altrettanto avviene però per \var{in6\_addr}, - pertanto è sempre opportuno inizializzare questi indirizzi con - \func{inet\_pton} (vedi sez.~\ref{sec:sock_conv_func_gen}).} per un -indirizzo IPv4 ed una struttura \struct{in6\_addr} per un indirizzo IPv6, -mentre in \param{len} se ne dovrà specificare la dimensione (rispettivamente 4 -o 16), infine l'argomento \param{type} indica il tipo di indirizzo e dovrà -essere o \const{AF\_INET} o \const{AF\_INET6}. +vuole risolvere. L'uso del tipo \texttt{char *} per questo argomento è +storico, il dato dovrà essere fornito in una struttura +\struct{in\_addr}\footnote{si ricordi che, come illustrato in + fig.~\ref{fig:sock_sa_ipv4_struct}, questo in realtà corrisponde ad un + numero intero, da esprimere comunque in \textit{network order}, non + altrettanto avviene però per \struct{in6\_addr}, pertanto è sempre opportuno + inizializzare questi indirizzi con \func{inet\_pton} (vedi + sez.~\ref{sec:sock_conv_func_gen}).} per un indirizzo IPv4 ed una struttura +\struct{in6\_addr} per un indirizzo IPv6, mentre in \param{len} se ne dovrà +specificare la dimensione (rispettivamente 4 o 16), infine l'argomento +\param{type} indica il tipo di indirizzo e dovrà essere o \const{AF\_INET} o +\const{AF\_INET6}. La funzione restituisce, in caso di successo, un puntatore ad una struttura \struct{hostent}, solo che in questo caso la ricerca viene eseguita @@ -1172,9 +1173,9 @@ rimandando alle rispettive pagine di manuale. \textbf{Informazione}&\multicolumn{3}{|c|}{\textbf{Funzioni}}\\ \hline \hline - indirizzo&\func{sethostent}&\func{gethostent}&\func{endhostent} \\ - servizio &cd te\func{setservent}&\func{getservent}&\func{endservent}\\ - rete &\func{setnetent}&\func{getnetent}&\func{endnetent}\\ + indirizzo &\func{sethostent} &\func{gethostent} &\func{endhostent} \\ + servizio &\func{setservent} &\func{getservent} &\func{endservent}\\ + rete &\func{setnetent} &\func{getnetent} &\func{endnetent}\\ protocollo&\func{setprotoent}&\func{getprotoent}&\func{endprotoent}\\ \hline \end{tabular} @@ -1414,7 +1415,7 @@ corrispondente \const{EAI\_SYSTEM} & c'è stato un errore di sistema, si può controllare \var{errno} per i dettagli. \\ % \hline -% estensioni GNU, trovarne la documentazione +% TODO estensioni GNU, trovarne la documentazione % \const{EAI\_INPROGRESS}& richiesta in corso. \\ % \const{EAI\_CANCELED}& la richiesta è stata cancellata.\\ % \const{EAI\_NOTCANCELED}& la richiesta non è stata cancellata. \\ @@ -2136,7 +2137,7 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni: consente però di impostare il timout per l'uso di \func{connect}, per avere il quale si può ricorrere a questa opzione. -% verificare con un programma di test +% TODO verificare il timeout con un programma di test \item[\const{SO\_SNDTIMEO}] l'opzione permette di impostare un tempo massimo sulle operazioni di scrittura su un socket, ed usa gli stessi valori di @@ -2184,21 +2185,21 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni: \item[\const{SO\_DEBUG}] questa opzione abilita il debugging delle operazioni dei socket; l'opzione utilizza per \param{optval} un intero usato come valore logico, e può essere utilizzata solo da un processo con i privilegi - di amministratore (in particolare con la \textit{capability} - \const{CAP\_NET\_ADMIN}). L'opzione necessita inoltre dell'opportuno - supporto nel kernel;\footnote{deve cioè essere definita la macro di - preprocessore \macro{SOCK\_DEBUGGING} nel file \file{include/net/sock.h} - dei sorgenti del kernel, questo è sempre vero nei kernel delle serie - superiori alla 2.3, per i kernel delle serie precedenti invece è - necessario aggiungere a mano detta definizione; è inoltre possibile - abilitare anche il tracciamento degli stati del TCP definendo la macro - \macro{STATE\_TRACE} in \file{include/net/tcp.h}.} quando viene - abilitata una serie di messaggi con le informazioni di debug vengono inviati - direttamente al sistema del kernel log.\footnote{si tenga presente che il - comportamento è diverso da quanto avviene con BSD, dove l'opzione opera - solo sui socket TCP, causando la scrittura di tutti i pacchetti inviati - sulla rete su un buffer circolare che viene letto da un apposito - programma, \cmd{trpt}.} + di amministratore (in particolare con la \itindex{capabilities} + \textit{capability} \const{CAP\_NET\_ADMIN}). L'opzione necessita inoltre + dell'opportuno supporto nel kernel;\footnote{deve cioè essere definita la + macro di preprocessore \macro{SOCK\_DEBUGGING} nel file + \file{include/net/sock.h} dei sorgenti del kernel, questo è sempre vero + nei kernel delle serie superiori alla 2.3, per i kernel delle serie + precedenti invece è necessario aggiungere a mano detta definizione; è + inoltre possibile abilitare anche il tracciamento degli stati del TCP + definendo la macro \macro{STATE\_TRACE} in \file{include/net/tcp.h}.} + quando viene abilitata una serie di messaggi con le informazioni di debug + vengono inviati direttamente al sistema del kernel log.\footnote{si tenga + presente che il comportamento è diverso da quanto avviene con BSD, dove + l'opzione opera solo sui socket TCP, causando la scrittura di tutti i + pacchetti inviati sulla rete su un buffer circolare che viene letto da un + apposito programma, \cmd{trpt}.} \item[\const{SO\_REUSEADDR}] questa opzione permette di eseguire la funzione \func{bind} su indirizzi locali che siano già in uso da altri socket; @@ -2264,7 +2265,8 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni: valori del campo \textit{type of service} (noto come TOS, vedi sez.~\ref{sec:IP_header}) per i pacchetti uscenti. Per impostare una priorità al di fuori dell'intervallo di valori fra 0 e 6 sono richiesti i - privilegi di amministratore con la capability \const{CAP\_NET\_ADMIN}. + privilegi di amministratore con la \itindex{capabilities} capability + \const{CAP\_NET\_ADMIN}. \item[\const{SO\_ERROR}] questa opzione riceve un errore presente sul socket; può essere utilizzata soltanto con \func{getsockopt} e prende per @@ -2283,7 +2285,7 @@ programmazione dei socket. Per questo motivo faremo in questa sezione un approfondimento sul significato delle opzioni generiche più importanti. -\index{costante!{\tt SO\_KEEPALIVE}|(} +\index{costante!{SO\_KEEPALIVE}@{{\tt {SO\_KEEPALIVE}}}|(} \subsubsection{L'opzione \const{SO\_KEEPALIVE}} La prima opzione da approfondire è \const{SO\_KEEPALIVE} che permette di @@ -2365,8 +2367,7 @@ presente per necessariamente ad una reale conclusione della connessione, il problema potrebbe anche essere dovuto ad un problema di routing che perduri per un tempo maggiore di quello impiegato nei vari tentativi di ritrasmissione del -\textit{keep-alive} (anche se questa non è una una condizione molto -probabile). +\textit{keep-alive} (anche se questa non è una condizione molto probabile). Come esempio dell'utilizzo di questa opzione introduciamo all'interno del nostro server per il servizio \textit{echo} la nuova opzione \texttt{-k} che @@ -2385,10 +2386,11 @@ tutte le volte che un processo figlio viene eseguito in risposta ad una connessione verrà pertanto eseguita o meno la sezione (\texttt{\small 14--17}) che esegue l'impostazione di \const{SO\_KEEPALIVE} sul socket connesso, attivando il relativo comportamento. -\index{costante!{\tt SO\_KEEPALIVE}|)} +\index{costante!{SO\_KEEPALIVE}@{{\tt {SO\_KEEPALIVE}}}|)} -\index{costante!{\tt SO\_REUSEADDR}|(} + +\index{costante!{SO\_REUSEADDR}@{{\tt {SO\_REUSEADDR}}}|(} \subsubsection{L'opzione \const{SO\_REUSEADDR}} La seconda opzione da approfondire è \const{SO\_REUSEADDR}, che consente di @@ -2560,9 +2562,9 @@ questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto primo programma a consentirlo, avendo usato fin dall'inizio \const{SO\_REUSEADDR}.} -\index{costante!{\tt SO\_REUSEADDR}|)} +\index{costante!{SO\_REUSEADDR}@{{\tt {SO\_REUSEADDR}}}|)} -\index{costante!{\tt SO\_LINGER}|(} +\index{costante!{SO\_LINGER}@{{\tt {SO\_LINGER}}}|(} \subsubsection{L'opzione \const{SO\_LINGER}} La terza opzione da approfondire è \const{SO\_LINGER}; essa, come il nome @@ -2648,7 +2650,7 @@ secondi\footnote{questa completamento della trasmissione dei dati sul buffer.} pari al valore specificato in \var{l\_linger}. -\index{costante!{\tt SO\_LINGER}|)} +\index{costante!{SO\_LINGER}@{{\tt {SO\_LINGER}}}|)} diff --git a/socket.tex b/socket.tex index 92a7564..138ebe2 100644 --- a/socket.tex +++ b/socket.tex @@ -240,7 +240,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{capability}\textit{capability} \const{CAP\_NET\_RAW}. +\itindex{capabilities}\textit{capability} \const{CAP\_NET\_RAW}. \subsection{Il tipo, o stile} @@ -439,8 +439,8 @@ fig.~\ref{fig:sock_sa_ipv4_struct}, conforme allo standard POSIX.1g. \begin{minipage}[c]{15cm} \includestruct{listati/sockaddr_in.h} \end{minipage} - \caption{La struttura degli indirizzi dei socket internet (IPv4) - \structd{sockaddr\_in}.} + \caption{La struttura \structd{sockaddr\_in} degli indirizzi dei socket + internet (IPv4) e la struttura \structd{in\_addr} degli indirizzi IPv4.} \label{fig:sock_sa_ipv4_struct} \end{figure} @@ -457,7 +457,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{capability}\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. @@ -490,8 +490,8 @@ in fig.~\ref{fig:sock_sa_ipv6_struct}. \begin{minipage}[c]{15cm} \includestruct{listati/sockaddr_in6.h} \end{minipage} - \caption{La struttura degli indirizzi dei socket IPv6 - \structd{sockaddr\_in6}.} + \caption{La struttura \structd{sockaddr\_in6} degli indirizzi dei socket + IPv6 e la struttura \structd{in6\_addr} degli indirizzi IPv6.} \label{fig:sock_sa_ipv6_struct} \end{figure} @@ -531,8 +531,8 @@ fig.~\ref{fig:sock_sa_local_struct}. \begin{minipage}[c]{15cm} \includestruct{listati/sockaddr_un.h} \end{minipage} - \caption{La struttura degli indirizzi dei socket locali (detti anche - \textit{unix domain}) \structd{sockaddr\_un} definita in \file{sys/un.h}.} + \caption{La struttura \structd{sockaddr\_un} degli indirizzi dei socket + locali (detti anche \textit{unix domain}) definita in \file{sys/un.h}.} \label{fig:sock_sa_local_struct} \end{figure} @@ -574,8 +574,8 @@ il file \file{netatalk/at.h}. \begin{minipage}[c]{15cm} \includestruct{listati/sockaddr_atalk.h} \end{minipage} - \caption{La struttura degli indirizzi dei socket AppleTalk - \structd{sockaddr\_atalk}.} + \caption{La struttura \structd{sockaddr\_atalk} degli indirizzi dei socket + AppleTalk, e la struttura \structd{at\_addr} degli indirizzi AppleTalk.} \label{fig:sock_sa_atalk_struct} \end{figure} @@ -583,7 +583,7 @@ Il campo \var{sat\_family} deve essere sempre \const{AF\_APPLETALK}, mentre il campo \var{sat\_port} specifica la porta che identifica i vari servizi. Valori inferiori a 129 sono usati per le \textsl{porte riservate}, e possono essere usati solo da processi con i privilegi di amministratore o con la -\itindex{capability}\textit{capability} \const{CAP\_NET\_BIND\_SERVICE}. +\itindex{capabilities}\textit{capability} \const{CAP\_NET\_BIND\_SERVICE}. L'indirizzo remoto è specificato nella struttura \var{sat\_addr}, e deve essere in \textit{network order} (vedi sez.~\ref{sec:sock_endianess}); esso è composto da un parte di rete data dal campo \var{s\_net}, che può assumere il @@ -634,7 +634,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{capability}\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 @@ -951,15 +951,6 @@ questo caso le lettere \texttt{n} e \texttt{p} sono degli mnemonici per ricordare il tipo di conversione effettuata e stanno per \textit{presentation} e \textit{numeric}. -% \begin{figure}[htb] -% \centering - -% \caption{Schema della rappresentazioni utilizzate dalle funzioni di -% conversione \func{inet\_pton} e \func{inet\_ntop} } -% \label{fig:sock_inet_conv_func} - -% \end{figure} - Entrambe le funzioni accettano l'argomento \param{af} che indica il tipo di indirizzo, e che può essere soltanto \const{AF\_INET} o \const{AF\_INET6}. La prima funzione, \funcd{inet\_pton}, serve a convertire una stringa in un diff --git a/sources/AcctCtrl.c b/sources/AcctCtrl.c new file mode 100644 index 0000000..c60f958 --- /dev/null +++ b/sources/AcctCtrl.c @@ -0,0 +1,98 @@ +/* AcctCtrl.c + * + * Copyright (C) 2005 Simone Piccardi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include /* directory */ +#include /* C standard library */ +#include +#include + +/* + * Program AcctCtrl + * + * Enable and disable BSD accounting + */ +/* Help printing routine */ +void usage(void); + +int main(int argc, char *argv[]) +{ + int i; + int enable = 0; + /* + * Input section: decode command line parameters + * Use getopt function + */ + opterr = 0; /* don't want writing to stderr */ + while ( (i = getopt(argc, argv, "hed")) != -1) { + switch (i) { + /* + * Handling options + */ + case 'h': /* help option */ + printf("Wrong -h option use\n"); + usage(); + return -1; + break; + case 'e': /* enable option */ + enable = 1; + break; + case 'd': /* disable option */ + enable = 0; + break; + case '?': /* unrecognized options */ + printf("Unrecognized options -%c\n",optopt); + usage(); + default: /* should not reached */ + usage(); + } + } + /* *********************************************************** + * + * Options processing completed + * + * Main code beginning + * + * ***********************************************************/ + if ((argc - optind) != 1) { /* There must be remaing parameters */ + printf("Wrong number of arguments %d\n", argc - optind); + usage(); + } + if (enable) { + i = acct(argv[optind]); + } else { + i = acct(NULL); + } + if (i) + perror("Operazione Fallita"); + + exit(0); +} +/* + * routine to print usage info and exit + */ +void usage(void) { + printf("Program AcctCtrl: enable/disable BSD accounting \n"); + printf("Usage:\n"); + printf(" acctctrl [-hed] filename \n"); + printf(" -h print this help\n"); + printf(" -e enable BSD accounting\n"); + printf(" -d disable BSD accounting\n"); + exit(1); +} diff --git a/sources/Makefile b/sources/Makefile index edd6119..7832b6d 100644 --- a/sources/Makefile +++ b/sources/Makefile @@ -112,7 +112,8 @@ readshm: ReadShm.c wwwd: wwwd.c $(CC) $(CFLAGJ) $(CFLAGS) $^ -o $@ - +acctctrl: AcctCtrl.c + $(CC) $(CFLAGS) $^ -o $@ # Macro per la generazione della tarball dei sorgenti diff --git a/system.tex b/system.tex index 1efb2b9..446c0f6 100644 --- a/system.tex +++ b/system.tex @@ -316,40 +316,52 @@ relative spiegazioni, si pu \textbf{Parametro}&\textbf{Macro sostituita} &\textbf{Significato}\\ \hline \hline - \texttt{\_SC\_ARG\_MAX} &\const{ARG\_MAX}& - La dimensione massima degli argomenti passati ad una funzione - della famiglia \func{exec}.\\ - \texttt{\_SC\_CHILD\_MAX}&\const{\_CHILD\_MAX}& - Il numero massimo di processi contemporanei che un utente può - eseguire.\\ - \texttt{\_SC\_OPEN\_MAX}&\const{\_OPEN\_MAX}& - Il numero massimo di file che un processo può mantenere aperti in - contemporanea.\\ + \texttt{\_SC\_ARG\_MAX} & \const{ARG\_MAX}& + La dimensione massima degli argomenti passati + ad una funzione della famiglia \func{exec}.\\ + \texttt{\_SC\_CHILD\_MAX} & \const{\_CHILD\_MAX}& + Il numero massimo di processi contemporanei + che un utente può eseguire.\\ + \texttt{\_SC\_OPEN\_MAX} & \const{\_OPEN\_MAX}& + Il numero massimo di file che un processo può + mantenere aperti in contemporanea.\\ \texttt{\_SC\_STREAM\_MAX}& \const{STREAM\_MAX}& - Il massimo numero di stream che un processo può mantenere aperti in - contemporanea. Questo limite previsto anche dallo standard ANSI C, che - specifica la macro {FOPEN\_MAX}.\\ - \texttt{\_SC\_TZNAME\_MAX}&\const{TZNAME\_MAX}& - La dimensione massima di un nome di una \texttt{timezone} (vedi - sez.~\ref{sec:sys_date}).\\ + Il massimo numero di stream che un processo + può mantenere aperti in contemporanea. Questo + limite previsto anche dallo standard ANSI C, + che specifica la macro {FOPEN\_MAX}.\\ + \texttt{\_SC\_TZNAME\_MAX}& \const{TZNAME\_MAX}& + La dimensione massima di un nome di una + \texttt{timezone} (vedi + sez.~\ref{sec:sys_date}).\\ \texttt{\_SC\_NGROUPS\_MAX}&\const{NGROUP\_MAX}& - Massimo numero di gruppi supplementari che può avere un processo (vedi - sez.~\ref{sec:proc_access_id}).\\ - \texttt{\_SC\_SSIZE\_MAX}&\const{SSIZE\_MAX}& - valore massimo del tipo di dato \type{ssize\_t}.\\ - \texttt{\_SC\_CLK\_TCK}& \const{CLK\_TCK} & - Il numero di \textit{clock tick} al secondo, cioè l'unità di misura del - \textit{process time} (vedi sez.~\ref{sec:sys_unix_time}).\\ + Massimo numero di gruppi supplementari che + può avere un processo (vedi + sez.~\ref{sec:proc_access_id}).\\ + \texttt{\_SC\_SSIZE\_MAX} & \const{SSIZE\_MAX}& + Valore massimo del tipo di dato + \type{ssize\_t}.\\ + \texttt{\_SC\_CLK\_TCK} & \const{CLK\_TCK} & + Il numero di \textit{clock tick} al secondo, + cioè l'unità di misura del + \itindex{process~time} \textit{process + time} (vedi + sez.~\ref{sec:sys_unix_time}).\\ \texttt{\_SC\_JOB\_CONTROL}&\macro{\_POSIX\_JOB\_CONTROL}& - Indica se è supportato il \textit{job control} (vedi - sez.~\ref{sec:sess_job_control}) in stile POSIX.\\ - \texttt{\_SC\_SAVED\_IDS}&\macro{\_POSIX\_SAVED\_IDS}& - Indica se il sistema supporta i \textit{saved id} (vedi - sez.~\ref{sec:proc_access_id}).\\ - \texttt{\_SC\_VERSION}& \const{\_POSIX\_VERSION} & - Indica il mese e l'anno di approvazione della revisione dello standard - POSIX.1 a cui il sistema fa riferimento, nel formato YYYYMML, la - revisione più recente è 199009L, che indica il Settembre 1990.\\ + Indica se è supportato il \textit{job + control} (vedi + sez.~\ref{sec:sess_job_control}) in stile + POSIX.\\ + \texttt{\_SC\_SAVED\_IDS} & \macro{\_POSIX\_SAVED\_IDS}& + Indica se il sistema supporta i + \textit{saved id} (vedi + sez.~\ref{sec:proc_access_id}).\\ + \texttt{\_SC\_VERSION} & \const{\_POSIX\_VERSION} & + Indica il mese e l'anno di approvazione + della revisione dello standard POSIX.1 a cui + il sistema fa riferimento, nel formato + YYYYMML, la revisione più recente è 199009L, + che indica il Settembre 1990.\\ \hline \end{tabular} \caption{Parametri del sistema leggibili dalla funzione \func{sysconf}.} @@ -754,7 +766,8 @@ valori riportati in tab.~\ref{tab:sys_mount_flags}. \hline \hline \const{MS\_RDONLY} & 1 & monta in sola lettura\\ - \const{MS\_NOSUID} & 2 & ignora i bit \acr{suid} e \acr{sgid}\\ + \const{MS\_NOSUID} & 2 & ignora i bit \itindex{suid~bit} \acr{suid} e + \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 \\ @@ -897,6 +910,7 @@ semplice invocare direttamente il programma \cmd{mount}, per cui ne tralasceremo la trattazione, rimandando al manuale delle \acr{glibc} \cite{glibc} per la documentazione completa. +% TODO scrivere relativamente alle varie funzioni (getfsent e getmntent &C) \subsection{La gestione delle informazioni su utenti e gruppi} \label{sec:sys_user_group} @@ -1319,7 +1333,7 @@ argomenti \param{line}, \param{name} e \param{host} per costruire la voce che poi aggiunge chiamando \func{updwtmp}. -\section{Limitazione ed uso delle risorse} +\section{Il controllo dell'uso delle risorse} \label{sec:sys_res_limits} @@ -1352,15 +1366,16 @@ di tipo \struct{rusage}, la cui definizione (che si trova in \end{figure} La definizione della struttura in fig.~\ref{fig:sys_rusage_struct} è ripresa -da BSD 4.3,\footnote{questo non ha a nulla a che fare con il \textit{BSD - accounting} che si trova nelle opzioni di compilazione del kernel (e di - norma è disabilitato) che serve per mantenere una contabilità delle risorse - usate da ciascun processo in maniera molto più dettagliata.} ma attualmente -(con i kernel della serie 2.4.x e 2.6.x) i soli campi che sono mantenuti sono: -\var{ru\_utime}, \var{ru\_stime}, \var{ru\_minflt}, \var{ru\_majflt}, e -\var{ru\_nswap}. I primi due indicano rispettivamente il tempo impiegato dal -processo nell'eseguire le istruzioni in user space, e quello impiegato dal -kernel nelle system call eseguite per conto del processo. +da BSD 4.3,\footnote{questo non ha a nulla a che fare con il cosiddetto + \textit{BSD accounting} (vedi sez. \ref{sec:sys_bsd_accounting}) che si trova + nelle opzioni di compilazione del kernel (e di norma è disabilitato) che + serve per mantenere una contabilità delle risorse usate da ciascun processo + in maniera molto più dettagliata.} ma attualmente (con i kernel della serie +2.4.x e 2.6.x) i soli campi che sono mantenuti sono: \var{ru\_utime}, +\var{ru\_stime}, \var{ru\_minflt}, \var{ru\_majflt}, e \var{ru\_nswap}. I +primi due indicano rispettivamente il tempo impiegato dal processo +nell'eseguire le istruzioni in user space, e quello impiegato dal kernel nelle +system call eseguite per conto del processo. Gli altri tre campi servono a quantificare l'uso della memoria virtuale\index{memoria~virtuale} e corrispondono rispettivamente al numero di @@ -1435,8 +1450,9 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard come \func{brk}, \func{mremap} o \func{mmap} esse falliranno con un errore di \errcode{ENOMEM}, mentre se il superamento viene - causato dalla crescita dello stack il processo - riceverà un segnale di \const{SIGSEGV}. \\ + causato dalla crescita dello \itindex{stack} + 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 sez.~\ref{sec:sig_prog_error}) creato nella @@ -1453,7 +1469,8 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard il processo. Il superamento del limite massimo comporta l'emissione di un segnale di \const{SIGKILL}.\footnotemark\\ - \const{RLIMIT\_DATA} & La massima dimensione del segmento dati di un + \const{RLIMIT\_DATA} & La massima dimensione del ndex{segmento!dati} + segmento dati di un processo (vedi sez.~\ref{sec:proc_mem_layout}). Il tentativo di allocare più memoria di quanto indicato dal limite corrente causa il fallimento @@ -1468,7 +1485,7 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard un errore di \errcode{EFBIG}.\\ \const{RLIMIT\_LOCKS}& È un limite presente solo nelle prime versioni del kernel 2.4 sul numero massimo di - \index{file!lock}\texttt{file lock} (vedi + \index{file!locking}\textit{file lock} (vedi sez.~\ref{sec:file_locking}) che un processo poteva effettuare.\\ \const{RLIMIT\_MEMLOCK}& L'ammontare massimo di memoria che può essere @@ -1495,14 +1512,16 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard attivo solo per \func{sigqueue}, con \func{kill} si potrà sempre inviare un segnale che non sia già presente su una coda.\footnotemark\\ - \const{RLIMIT\_STACK} & La massima dimensione dello stack del + \const{RLIMIT\_STACK} & La massima dimensione dello \itindex{stack} + stack del processo. Se il processo esegue operazioni che estendano lo stack oltre questa dimensione riceverà un segnale di \const{SIGSEGV}.\\ \const{RLIMIT\_RSS} & L'ammontare massimo di pagine di memoria dato al - testo del processo. Il limite è solo una - indicazione per il kernel, qualora ci fosse un - surplus di memoria questa verrebbe assegnata.\\ + \index{segmento!testo} testo del processo. Il + limite è solo una indicazione per il kernel, + qualora ci fosse un surplus di memoria questa + verrebbe assegnata.\\ % TODO integrare con la roba di madvise \hline \end{tabular} @@ -1582,8 +1601,8 @@ 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{capability}\textit{capability} \const{CAP\_SYS\_RESOURCE}.} può -innalzare un limite al di sopra del valore corrente del limite massimo ed + 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} (vedi sez.~\ref{sec:proc_fork}) e mantenuti per gli altri programmi eseguiti @@ -1614,9 +1633,10 @@ scelta di dimensioni, Dato che si tratta di una caratteristica generale del sistema, questa dimensione può essere ottenuta come tutte le altre attraverso una chiamata a -\func{sysconf} (nel caso \code{sysconf(\_SC\_PAGESIZE)}, ma in BSD 4.2 è stata -introdotta una apposita funzione, \funcd{getpagesize}, che restituisce la -dimensione delle pagine di memoria; il suo prototipo è: +\func{sysconf}, \footnote{nel caso specifico si dovrebbe utilizzare il + parametro \const{\_SC\_PAGESIZE}.} ma in BSD 4.2 è stata introdotta una +apposita funzione, \funcd{getpagesize}, che restituisce la dimensione delle +pagine di memoria; il suo prototipo è: \begin{prototype}{unistd.h}{int getpagesize(void)} Legge le dimensioni delle pagine di memoria. @@ -1628,15 +1648,15 @@ La funzione standard la etichetta come obsoleta, mentre lo standard POSIX 1003.1-2001 la ha eliminata. In Linux è implementata come una system call nelle architetture in cui essa è necessaria, ed in genere restituisce il valore del simbolo -\const{PAGE\_SIZE} del kernel, anche se le versioni delle librerie del C -precedenti le \acr{glibc} 2.1 implementavano questa funzione restituendo -sempre un valore statico. +\const{PAGE\_SIZE} del kernel, che dipende dalla architettura hardware, anche +se le versioni delle librerie del C precedenti le \acr{glibc} 2.1 +implementavano questa funzione restituendo sempre un valore statico. % TODO verificare meglio la faccenda di const{PAGE\_SIZE} -Le \acr{glibc} forniscono, come specifica estensione GNU, altre due funzioni, -\funcd{get\_phys\_pages} e \funcd{get\_avphys\_pages} che permettono di -ottenere informazioni riguardo la memoria; i loro prototipi sono: +Le \textsl{glibc} forniscono, come specifica estensione GNU, altre due +funzioni, \funcd{get\_phys\_pages} e \funcd{get\_avphys\_pages} che permettono +di ottenere informazioni riguardo la memoria; i loro prototipi sono: \begin{functions} \headdecl{sys/sysinfo.h} @@ -1682,6 +1702,66 @@ 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. +\subsection{La contabilità in stile BSD} +\label{sec:sys_bsd_accounting} + +Una ultima modalità per monitorare l'uso delle risorse è quella, se si è +compilato il kernel con il relativo supporto,\footnote{se cioè si è abilitata + l'opzione di compilazione \texttt{CONFIG\_BSD\_PROCESS\_ACCT}.} di attivare +il cosiddetto \textit{BSD accounting}, che consente di registrare su file una +serie di informazioni\footnote{contenute nella struttura \texttt{acct} + definita nel file \texttt{include/linux/acct.h} dei sorgenti del kernel.} +riguardo alla \textsl{contabilità} delle risorse utilizzate da ogni processo +che viene terminato. + +Linux consente di salvare la contabilità delle informazioni relative alle +risorse utilizzate dai processi grazie alla funzione \funcd{acct}, il cui +prototipo è: +\begin{prototype}{unistd.h}{int acct(const char *filename)} + Abilita il \textit{BSD accounting}. + + \bodydesc{La funzione ritorna 0 in caso di successo o $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCESS}] non si hanno i permessi per accedere a + \param{pathname}. + \item[\errcode{EPERM}] Il processo non ha privilegi sufficienti ad + abilitare il \textit{BSD accounting}. + \item[\errcode{ENOSYS}] il kernel non supporta il \textit{BSD accounting}. + \item[\errcode{EUSER}] non sono disponibili nel kernel strutture per il + file o si è finita la memoria. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{EIO}, \errval{ELOOP}, + \errval{ENAMETOOLONG}, \errval{ENFILE}, \errval{ENOENT}, \errval{ENOMEM}, + \errval{ENOTDIR}, \errval{EROFS}.} +\end{prototype} + +La funzione attiva il salvataggio dei dati sul file indicato dal pathname +contenuti nella stringa puntata da \param{filename}; la funzione richiede che +il processo abbia i privilegi di amministratore (è necessaria la +\itindex{capabilities} capability \const{CAP\_SYS\_PACCT}, vedi +sez.~\ref{sec:proc_capabilities}). Se si specifica il valore \const{NULL} per +\param{filename} il \textit{BSD accounting} viene invece disabilitato. + +Quando si attiva la contabilità il file che si indica deve esistere; esso +verrà aperto in sola scrittura;\footnote{si applicano al pathname indicato da + \param{filename} tutte le restrizioni viste in cap.~\ref{cha:file_intro}.} +le informazioni verranno registrate in \textit{append} in coda al file tutte +le volte che un processo termina. Le informazioni vengono salvate in formato +binario, e corrispondono al contenuto della apposita struttura dati definita +all'interno del kernel. + +Il funzionamento di \func{acct} viene inoltre modificato da uno specifico +parametro di sistema, modificabile attraverso \file{/proc/sys/kernel/acct} (o +tramite la corrispondente \func{sysctl}). Esso contiene tre valori interi, il +primo indica la percentuale di spazio disco libero sopra il quale viene +ripresa una registrazione che era stata sospesa per essere scesi sotto il +minimo indicato dal secondo valore (sempre in percentuale di spazio disco +libero). Infine l'ultimo valore indica la frequenza in secondi con cui deve +essere controllata detta percentuale. + + + \section{La gestione dei tempi del sistema} \label{sec:sys_time} @@ -1699,25 +1779,25 @@ gestione di data e ora. Storicamente i sistemi unix-like hanno sempre mantenuto due distinti tipi di dati per la misure dei tempi all'interno del sistema: essi sono -rispettivamente chiamati \textit{calendar time} e \textit{process time}, -secondo le definizioni: +rispettivamente chiamati \itindend{calendar~time} \textit{calendar time} e +\itindex{process~time} \textit{process time}, secondo le definizioni: \begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}} -\item[\textit{calendar time}] detto anche \textsl{tempo di calendario}. È il - numero di secondi dalla mezzanotte del primo gennaio 1970, in tempo - universale coordinato (o UTC), data che viene usualmente indicata con - 00:00:00 Jan, 1 1970 (UTC) e chiamata \textit{the Epoch}. Questo tempo viene - anche chiamato anche GMT (Greenwich Mean Time) dato che l'UTC corrisponde - all'ora locale di Greenwich. È il tempo su cui viene mantenuto l'orologio - del kernel, e viene usato ad esempio per indicare le date di modifica dei - file o quelle di avvio dei processi. Per memorizzare questo tempo è stato - riservato il tipo primitivo \type{time\_t}. -\item[\textit{process time}] detto talvolta \textsl{tempo di processore}. - Viene misurato in \textit{clock tick}. Un tempo questo corrispondeva al - numero di interruzioni effettuate dal timer di sistema, adesso lo standard - POSIX richiede che esso sia pari al valore della costante - \const{CLOCKS\_PER\_SEC}, che deve essere definita come 1000000, qualunque - sia la risoluzione reale dell'orologio di sistema e la frequenza delle - interruzioni del timer.\footnote{quest'ultima, come accennato in +\item[\textit{calendar time}] \itindend{calendar~time} detto anche + \textsl{tempo di calendario}. È il numero di secondi dalla mezzanotte del + primo gennaio 1970, in tempo universale coordinato (o UTC), data che viene + usualmente indicata con 00:00:00 Jan, 1 1970 (UTC) e chiamata \textit{the + Epoch}. Questo tempo viene anche chiamato anche GMT (Greenwich Mean Time) + dato che l'UTC corrisponde all'ora locale di Greenwich. È il tempo su cui + viene mantenuto l'orologio del kernel, e viene usato ad esempio per indicare + le date di modifica dei file o quelle di avvio dei processi. Per memorizzare + questo tempo è stato riservato il tipo primitivo \type{time\_t}. +\item[\textit{process time}] \itindex{process~time} detto talvolta + \textsl{tempo di processore}. Viene misurato in \textit{clock tick}. Un + tempo questo corrispondeva al numero di interruzioni effettuate dal timer di + sistema, adesso lo standard POSIX richiede che esso sia pari al valore della + costante \const{CLOCKS\_PER\_SEC}, che deve essere definita come 1000000, + qualunque sia la risoluzione reale dell'orologio di sistema e la frequenza + delle interruzioni del timer.\footnote{quest'ultima, come accennato in sez.~\ref{sec:proc_hierarchy}, è invece data dalla costante \const{HZ}.} Il dato primitivo usato per questo tempo è \type{clock\_t}, che ha quindi una risoluzione del microsecondo. Il numero di tick al secondo può essere @@ -1726,10 +1806,10 @@ secondo le definizioni: considerato obsoleto. \end{basedescript} -In genere si usa il \textit{calendar time} per esprimere le date dei file e le -informazioni analoghe che riguardano i cosiddetti \textsl{tempi di orologio}, -che vengono usati ad esempio per i demoni che compiono lavori amministrativi -ad ore definite, come \cmd{cron}. +In genere si usa il \itindend{calendar~time} \textit{calendar time} per +esprimere le date dei file e le informazioni analoghe che riguardano i +cosiddetti \textsl{tempi di orologio}, che vengono usati ad esempio per i +demoni che compiono lavori amministrativi ad ore definite, come \cmd{cron}. Di solito questo tempo viene convertito automaticamente dal valore in UTC al tempo locale, utilizzando le opportune informazioni di localizzazione @@ -1737,11 +1817,11 @@ tempo locale, utilizzando le opportune informazioni di localizzazione mantenuto dal sistema e non è detto che corrisponda al tempo tenuto dall'orologio hardware del calcolatore. -Anche il \textit{process time} di solito si esprime in secondi, ma provvede -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: +Anche il \itindex{process~time} \textit{process time} di solito si esprime in +secondi, ma provvede 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: \begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}} \item[\textit{clock time}] il tempo \textsl{reale} (viene chiamato anche \textit{wall clock time} o \textit{elapsed time}) passato dall'avvio del @@ -1771,13 +1851,15 @@ del comando \cmd{time}. \subsection{La gestione del \textit{process time}} \label{sec:sys_cpu_times} +\itindbeg{process~time} + Di norma tutte le operazioni del sistema fanno sempre riferimento al -\textit{calendar time}, l'uso del \textit{process time} è riservato a quei -casi in cui serve conoscere i tempi di esecuzione di un processo (ad esempio -per valutarne l'efficienza). In tal caso infatti fare ricorso al -\textit{calendar time} è inutile in quanto il tempo può essere trascorso mentre -un altro processo era in esecuzione o in attesa del risultato di una -operazione di I/O. +\itindend{calendar~time} \textit{calendar time}, l'uso del \textit{process + time} è riservato a quei casi in cui serve conoscere i tempi di esecuzione +di un processo (ad esempio per valutarne l'efficienza). In tal caso infatti +fare ricorso al \textit{calendar time} è inutile in quanto il tempo può essere +trascorso mentre un altro processo era in esecuzione o in attesa del risultato +di una operazione di I/O. La funzione più semplice per leggere il \textit{process time} di un processo è \funcd{clock}, che da una valutazione approssimativa del tempo di CPU @@ -1809,10 +1891,10 @@ possono essere letti attraverso la funzione \funcd{times}, il cui prototipo in caso di successo e -1 in caso di errore.} \end{prototype} -La funzione restituisce i valori di process time del processo corrente in una -struttura di tipo \struct{tms}, la cui definizione è riportata in -fig.~\ref{fig:sys_tms_struct}. La struttura prevede quattro campi; i primi due, -\var{tms\_utime} e \var{tms\_stime}, sono l'\textit{user time} ed il +La funzione restituisce i valori di \textit{process time} del processo +corrente in una struttura di tipo \struct{tms}, la cui definizione è riportata +in fig.~\ref{fig:sys_tms_struct}. La struttura prevede quattro campi; i primi +due, \var{tms\_utime} e \var{tms\_stime}, sono l'\textit{user time} ed il \textit{system time} del processo, così come definiti in sez.~\ref{sec:sys_unix_time}. @@ -1840,10 +1922,14 @@ ritornata. Per questo motivo se un processo figlio termina prima di ricevere lo stato di terminazione di tutti i suoi figli, questi processi ``nipoti'' non verranno considerati nel calcolo di questi tempi. +\itindend{process~time} + \subsection{Le funzioni per il \textit{calendar time}} \label{sec:sys_time_base} +\itindbeg{calendar~time} + Come anticipato in sez.~\ref{sec:sys_unix_time} il \textit{calendar time} è mantenuto dal kernel in una variabile di tipo \type{time\_t}, che usualmente corrisponde ad un tipo elementare (in Linux è definito come \ctyp{long int}, @@ -2007,22 +2093,22 @@ a descrivere in tab.~\ref{tab:sys_timex_mode} i principali valori utilizzabili per il campo \var{mode}, un elenco più dettagliato del significato dei vari campi della struttura \struct{timex} può essere ritrovato in \cite{glibc}. -\begin{table}[htb] +\begin{table}[!htb] \footnotesize \centering - \begin{tabular}[c]{|l|c|p{7cm}|} + \begin{tabular}[c]{|l|c|p{8.5cm}|} \hline \textbf{Nome} & \textbf{Valore} & \textbf{Significato}\\ \hline \hline \const{ADJ\_OFFSET} & 0x0001 & Imposta la differenza fra il tempo - reale e l'orologio di sistema, che + reale e l'orologio di sistema: deve essere indicata in microsecondi nel campo \var{offset} di \struct{timex}.\\ \const{ADJ\_FREQUENCY} & 0x0002 & Imposta la differenze in frequenza fra il tempo reale e l'orologio di - sistema, che deve essere indicata + sistema: deve essere indicata in parti per milione nel campo \var{frequency} di \struct{timex}.\\ \const{ADJ\_MAXERROR} & 0x0004 & Imposta il valore massimo @@ -2090,6 +2176,7 @@ un errore; al solito se si cercher amministratore si otterrà un errore di \errcode{EPERM}. + \subsection{La gestione delle date.} \label{sec:sys_date} @@ -2292,6 +2379,7 @@ viene utilizzato come modificatore; alcuni\footnote{per la precisione quelli in tab.~\ref{tab:sys_strftime_format}. La funzione tiene conto anche della presenza di una localizzazione per stampare in maniera adeguata i vari nomi. +\itindend{calendar~time} \section{La gestione degli errori} @@ -2386,7 +2474,7 @@ La funzione utilizza una stringa statica che non deve essere modificata dal programma; essa è utilizzabile solo fino ad una chiamata successiva a \func{strerror} o \func{perror}, nessun'altra funzione di libreria tocca questa stringa. In ogni caso l'uso di una stringa statica rende la funzione -non rientrante, per cui nel caso nel caso si usino i thread le librerie +non rientrante, per cui nel caso si usino i thread le librerie forniscono\footnote{questa funzione è la versione prevista dalle \acr{glibc}, ed effettivamente definita in \file{string.h}, ne esiste una analoga nello standard SUSv3 (quella riportata dalla pagina di manuale), che restituisce diff --git a/tcpsock.tex b/tcpsock.tex index 583ec3d..14c664b 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -137,7 +137,8 @@ regolare la connessione. Normalmente vengono usate le seguenti opzioni: connessione corrente. È possibile leggere e scrivere questo valore attraverso l'opzione del socket \const{TCP\_MAXSEG}. -\item \textit{window scale option}, %come spiegato in sez.~\ref{sec:tcp_protocol} +\item \textit{window scale + option}, %come spiegato in sez.~\ref{sec:tcp_protocol} il protocollo TCP implementa il controllo di flusso attraverso una \textsl{finestra annunciata} (\textit{advertized window}) con la quale ciascun capo della comunicazione dichiara quanto spazio disponibile ha in @@ -393,7 +394,7 @@ una connessione fra due router si interrompa. In questo caso i protocolli di instradamento dei pacchetti possono impiegare diverso tempo (anche dell'ordine dei minuti) prima di trovare e stabilire un percorso alternativo per i pacchetti. Nel frattempo possono accadere casi in cui un router manda i -pacchetti verso un'altro e quest'ultimo li rispedisce indietro, o li manda ad +pacchetti verso un altro e quest'ultimo li rispedisce indietro, o li manda ad un terzo router che li rispedisce al primo, si creano cioè dei circoli (i cosiddetti \textit{routing loop}) in cui restano intrappolati i pacchetti. @@ -621,17 +622,17 @@ tcp 0 0 195.110.112.152:22 192.84.146.100:21100 ESTABLISHED tcp 0 0 195.110.112.152:22 192.84.146.100:21101 ESTABLISHED \end{verbatim} cioè il client effettuerà la connessione usando un'altra porta effimera: con -questa sarà aperta la connessione, ed il server creerà un'altro processo +questa sarà aperta la connessione, ed il server creerà un altro processo figlio per gestirla. Tutto ciò mostra come il TCP, per poter gestire le connessioni con un server concorrente, non può suddividere i pacchetti solo sulla base della porta di destinazione, ma deve usare tutta l'informazione contenuta nella socket pair, compresa la porta dell'indirizzo remoto. E se andassimo a vedere quali sono i -processi\footnote{ad esempio con il comando \cmd{fuser}, o con \cmd{lsof}.} a -cui fanno riferimento i vari socket vedremmo che i pacchetti che arrivano -dalla porta remota 21100 vanno al primo figlio e quelli che arrivano alla -porta 21101 al secondo. +processi\footnote{ad esempio con il comando \cmd{fuser}, o con \cmd{lsof}, o + usando l'opzione \texttt{-p}.} a cui fanno riferimento i vari socket +vedremmo che i pacchetti che arrivano dalla porta remota 21100 vanno al primo +figlio e quelli che arrivano alla porta 21101 al secondo. \section{Le funzioni di base per la gestione dei socket} @@ -747,10 +748,10 @@ con una struttura, perch costante come operando a destra in una assegnazione. Per questo motivo nell'header \file{netinet/in.h} è definita una variabile -\const{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal +\macro{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal sistema al valore \const{IN6ADRR\_ANY\_INIT}) che permette di effettuare una assegnazione del tipo: \includecodesnip{listati/serv_addr_sin6_addr.c} in -maniera analoga si può utilizzare la variabile \const{in6addr\_loopback} per +maniera analoga si può utilizzare la variabile \macro{in6addr\_loopback} per indicare l'indirizzo di \textit{loopback}, che a sua volta viene inizializzata staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}. @@ -818,7 +819,7 @@ 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 chiamata - di \func{connect}, un'altro dopo 6 secondi, un terzo dopo 24 secondi, se + di \func{connect}, un altro dopo 6 secondi, un terzo dopo 24 secondi, se dopo 75 secondi non ha ricevuto risposta viene ritornato l'errore. Linux invece ripete l'emissione del SYN ad intervalli di 30 secondi per un numero di volte che può essere stabilito dall'utente sia con una opportuna @@ -826,10 +827,7 @@ o problemi nella chiamata della funzione sono le seguenti: voluto in \file{/proc/sys/net/ipv4/tcp\_syn\_retries}. Il valore predefinito per la ripetizione dell'invio è di 5 volte, che comporta un timeout dopo circa 180 secondi. -% -% Le informazioni su tutte le opzioni impostabili via /proc stanno in -% Linux/Documentation/networking/ip-sysctl.txt -% + \item Il client riceve come risposta al SYN un RST significa che non c'è nessun programma in ascolto per la connessione sulla porta specificata (il che vuol dire probabilmente che o si è sbagliato il numero della porta o che @@ -1793,7 +1791,7 @@ processo ad un gruppo senza privilegi,\footnote{si 27--30}) l'operazione usando \func{setuid} per cambiare anche l'utente.\footnote{si tenga presente che l'ordine in cui si eseguono queste due operazioni è importante, infatti solo avendo i privilegi di - amministratore si può cambiare il gruppo di un processo ad un'altro di cui + amministratore si può cambiare il gruppo di un processo ad un altro di cui non si fa parte, per cui chiamare prima \func{setuid} farebbe fallire una successiva chiamata a \func{setgid}. Inoltre si ricordi (si riveda quanto esposto in sez.~\ref{sec:proc_perms}) che usando queste due funzioni il