di I/O, che prevede anche l'introduzione di un nuovo layer per l'I/O
asincrono (effettuato a partire dal 2.5.32).} esiste una sola versione
stabile di questa interfaccia, quella delle \acr{glibc}, che è realizzata
-completamente in user space. Esistono comunque vari progetti sperimentali
-(come il KAIO della SGI, o i patch di Benjamin La Haise) che prevedono un
-supporto diretto da parte del kernel.
+completamente in user space, ed accessibile linkando i programmi con la
+libreria \file{librt}. Esistono comunque vari progetti sperimentali (come il
+KAIO della SGI, o i patch di Benjamin La Haise) che prevedono un supporto
+diretto da parte del kernel.
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
filesystem che non supportano i link diretti, a delle directory, ed anche a
file che non esistono ancora.
-Il sistema funziona in quanto i link simbolici sono contrassegnati come tali
-al kernel (analogamente a quanto avviene per le directory) per cui per alcune
-funzioni di libreria (come \func{open} o \func{stat}) dare come parametro un
-link simbolico comporta l'applicazione della funzione al file da esso
-specificato. La funzione che permette di creare un nuovo link simbolico è
-\funcd{symlink}; il suo prototipo è:
+Il sistema funziona in quanto i link simbolici sono riconosciuti come tali dal
+kernel\footnote{è uno dei diversi tipi di file visti in
+ \tabref{tab:file_file_types}, contrassegnato come tale nell'inode, e
+ riconoscibile dal valore del campo \var{st\_mode} della struttura
+ \struct{stat} (vedi \secref{sec:file_stat}).} per cui alcune funzioni di
+libreria (come \func{open} o \func{stat}) quando ricevono come argomento un
+link simbolico vengono automaticamente applicate al file da esso specificato.
+La funzione che permette di creare un nuovo link simbolico è \funcd{symlink},
+ed il suo prototipo è:
\begin{prototype}{unistd.h}
{int symlink(const char *oldpath, const char *newpath)}
Crea un nuovo link simbolico di nome \param{newpath} il cui contenuto è
\label{sec:file_work_dir}
A ciascun processo è associata una directory nel filesystem che è chiamata
-directory corrente o directory di lavoro (\textit{current working directory})
-che è quella a cui si fa riferimento quando un pathname è espresso in forma
-relativa, dove il ``\textsl{relativa}'' fa riferimento appunto a questa
-directory.
+\textsl{directory corrente} o \textsl{directory di lavoro} (in inglese
+\textit{current working directory}) che è quella a cui si fa riferimento
+quando un pathname è espresso in forma relativa, dove il ``\textsl{relativa}''
+fa riferimento appunto a questa directory.
Quando un utente effettua il login, questa directory viene impostata alla
\textit{home directory} del suo account. Il comando \cmd{cd} della shell
directory corrente di qualunque comando da essa lanciato.
In genere il kernel tiene traccia per ciascun processo dell'inode\index{inode}
-della directory di lavoro corrente, per ottenere il pathname occorre usare una
-apposita funzione di libreria, \funcd{getcwd}, il cui prototipo è:
+della directory di lavoro, per ottenere il pathname occorre usare una apposita
+funzione di libreria, \funcd{getcwd}, il cui prototipo è:
\begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)}
Legge il pathname della directory di lavoro corrente.
\end{errlist}}
\end{prototype}
-La funzione restituisce il pathname completo della directory di lavoro
-corrente nella stringa puntata da \param{buffer}, che deve essere
-precedentemente allocata, per una dimensione massima di \param{size}. Il
-buffer deve essere sufficientemente lungo da poter contenere il pathname
-completo più lo zero di terminazione della stringa. Qualora esso ecceda le
-dimensioni specificate con \param{size} la funzione restituisce un errore.
+La funzione restituisce il pathname completo della directory di lavoro nella
+stringa puntata da \param{buffer}, che deve essere precedentemente allocata,
+per una dimensione massima di \param{size}. Il buffer deve essere
+sufficientemente lungo da poter contenere il pathname completo più lo zero di
+terminazione della stringa. Qualora esso ecceda le dimensioni specificate con
+\param{size} la funzione restituisce un errore.
Si può anche specificare un puntatore nullo come
\param{buffer},\footnote{questa è un'estensione allo standard POSIX.1,
risalendo all'indietro l'albero della directory, si perderebbe traccia di ogni
passaggio attraverso eventuali link simbolici.
-Per cambiare la directory di lavoro corrente si può usare la funzione
-\funcd{chdir} (equivalente del comando di shell \cmd{cd}) il cui nome sta
-appunto per \textit{change directory}, il suo prototipo è:
+Per cambiare la directory di lavoro si può usare la funzione \funcd{chdir}
+(equivalente del comando di shell \cmd{cd}) il cui nome sta appunto per
+\textit{change directory}, il suo prototipo è:
\begin{prototype}{unistd.h}{int chdir(const char *pathname)}
- Cambia la directory di lavoro corrente in \param{pathname}.
+ Cambia la directory di lavoro in \param{pathname}.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore,
nel qual caso \var{errno} assumerà i valori:
funzione non si può usare una stringa costante. Tutte le avvertenze riguardo
alle possibili \textit{race condition}\index{race condition} date per
\func{tmpnam} continuano a valere; inoltre in alcune vecchie implementazioni
-il valore di usato per sostituire le \code{XXXXXX} viene formato con il
-\acr{pid} del processo più una lettera, il che mette a disposizione solo 26
-possibilità diverse per il nome del file, e rende il nome temporaneo facile da
-indovinare. Per tutti questi motivi la funzione è deprecata e non dovrebbe mai
-essere usata.
+il valore usato per sostituire le \code{XXXXXX} viene formato con il \acr{pid}
+del processo più una lettera, il che mette a disposizione solo 26 possibilità
+diverse per il nome del file, e rende il nome temporaneo facile da indovinare.
+Per tutti questi motivi la funzione è deprecata e non dovrebbe mai essere
+usata.
La seconda funzione, \funcd{mkstemp} è sostanzialmente equivalente a
\func{tmpfile}, ma restituisce un file descriptor invece di uno stream; il suo
\funcdecl{int lstat(const char *file\_name, struct stat *buf)} Identica a
\func{stat} eccetto che se il \param{file\_name} è un link simbolico vengono
- lette le informazioni relativa ad esso e non al file a cui fa riferimento.
+ lette le informazioni relativae ad esso e non al file a cui fa riferimento.
\funcdecl{int fstat(int filedes, struct stat *buf)} Identica a \func{stat}
eccetto che si usa con un file aperto, specificato tramite il suo file
Come riportato in \tabref{tab:file_file_types} in Linux oltre ai file e alle
directory esistono altri oggetti che possono stare su un filesystem. Il tipo
di file è ritornato dalla \func{stat} come maschera binaria nel campo
-\var{st\_mode} (che che contiene anche le informazioni relative ai permessi).
+\var{st\_mode} (che contiene anche le informazioni relative ai permessi).
Dato che il valore numerico può variare a seconda delle implementazioni, lo
standard POSIX definisce un insieme di macro per verificare il tipo di file,
programma il comportamento normale del kernel è quello di impostare gli
identificatori del gruppo \textit{effective} del nuovo processo al valore dei
corrispondenti del gruppo \textit{real} del processo corrente, che normalmente
-corrispondono dell'utente con cui si è entrati nel sistema.
+corrispondono a quelli dell'utente con cui si è entrati nel sistema.
Se però il file del programma (che ovviamente deve essere
eseguibile\footnote{per motivi di sicurezza il kernel ignora i bit \acr{suid}
processo.
I bit \acr{suid} e \acr{sgid} vengono usati per permettere agli utenti normali
-di usare programmi che abbisognano di privilegi speciali; l'esempio classico è
-il comando \cmd{passwd} che ha la necessità di modificare il file delle
-password, quest'ultimo ovviamente può essere scritto solo dall'amministratore,
-ma non è necessario chiamare l'amministratore per cambiare la propria
-password. Infatti il comando \cmd{passwd} appartiene a root ma ha il bit
-\acr{suid} impostato per cui quando viene lanciato da un utente normale parte
-con i privilegi di root.
+di usare programmi che richiedono privilegi speciali; l'esempio classico è il
+comando \cmd{passwd} che ha la necessità di modificare il file delle password,
+quest'ultimo ovviamente può essere scritto solo dall'amministratore, ma non è
+necessario chiamare l'amministratore per cambiare la propria password. Infatti
+il comando \cmd{passwd} appartiene a root ma ha il bit \acr{suid} impostato
+per cui quando viene lanciato da un utente normale parte con i privilegi di
+root.
Chiaramente avere un processo che ha privilegi superiori a quelli che avrebbe
normalmente l'utente che lo ha lanciato comporta vari rischi, e questo tipo di
Vedremo in \secref{sec:file_base_func} con quali funzioni si possono creare
nuovi file, in tale occasione vedremo che è possibile specificare in sede di
creazione quali permessi applicare ad un file, però non si può indicare a
-quale utente e gruppo esso deve appartenere. Lo stesso problema di presenta
+quale utente e gruppo esso deve appartenere. Lo stesso problema si presenta
per la creazione di nuove directory (procedimento descritto in
\secref{sec:file_dir_creat_rem}).
\subsection{La funzione \func{umask}}
\label{sec:file_umask}
-Oltre che dai valori indicati in sede di creazione, i permessi assegnati ai
-nuovi file sono controllati anche da una maschera di bit impostata con la
-funzione \funcd{umask}, il cui prototipo è:
+Le funzioni \func{chmod} e \func{fchmod} ci permettono di modificare i
+permessi di un file, resta però il problema di quali sono i permessi assegnati
+quando il file viene creato. Le funzioni dell'interfaccia nativa di Unix, come
+vedremo in \secref{sec:file_open}, permettono di indicare esplicitamente i
+permessi di creazione di un file, ma questo non è possibile per le funzioni
+dell'interfaccia standard ANSI C che non prevede l'esistenza di utenti e
+gruppi, ed inoltre il problema si pone anche per l'interfaccia nativa quando i
+permessi non vengono indicati esplicitamente.
+
+In tutti questi casi l'unico riferimento possibile è quello della modalità di
+apertura del nuovo file (lettura/scrittura o sola lettura), che però può
+fornire un valore che è lo stesso per tutti e tre i permessi di
+\secref{sec:file_perm_overview} (cioè $666$ nel primo caso e $222$ nel
+secondo). Per questo motivo il sistema associa ad ogni processo\footnote{è
+ infatti contenuta nel campo \var{umask} della struttura \struct{fs\_struct},
+ vedi \figref{fig:proc_task_struct}.} una maschera di bit, la cosiddetta
+\textit{umask}, che viene utilizzata per impedire che alcuni permessi possano
+essere assegnati ai nuovi file in sede di creazione. I bit indicati nella
+maschera vengono infatti cancellati dai permessi quando un nuovo file viene
+creato.
+
+La funzione che permette di impostare il valore di questa maschera di
+controllo è \funcd{umask}, ed il suo prototipo è:
\begin{prototype}{stat.h}
{mode\_t umask(mode\_t mask)}
delle poche funzioni che non restituisce codici di errore.}
\end{prototype}
-Questa maschera è una caratteristica di ogni processo\footnote{è infatti
- contenuta nel campo \param{umask} di \struct{fs\_struct}, vedi
- \figref{fig:proc_task_struct}.} e viene utilizzata per impedire che alcuni
-permessi possano essere assegnati ai nuovi file in sede di creazione. I bit
-indicati nella maschera vengono infatti esclusi quando un nuovo file viene
-creato.
-
-In genere questa maschera serve per impostare un valore predefinito dei
-permessi che ne escluda alcuni (usualmente quello di scrittura per il gruppo e
-gli altri, corrispondente ad un valore di $022$). Essa è utile perché le
-routine dell'interfaccia ANSI C degli stream non prevedono l'esistenza dei
-permessi, e pertanto tutti i nuovi file vengono sempre creati con un valore di
-$666$ (cioè permessi di lettura e scrittura per tutti, si veda
-\tabref{tab:file_permission_const} per un confronto); in questo modo è
-possibile cancellare automaticamente i permessi non voluti, senza doverlo fare
-esplicitamente.
-
-In genere il valore di \func{umask} viene stabilito una volta per tutte al
-login a $022$, e di norma gli utenti non hanno motivi per modificarlo. Se però
-si vuole che un processo possa creare un file che chiunque possa leggere
-allora occorrerà cambiare il valore di \func{umask}.
+In genere si usa questa maschera per impostare un valore predefinito che
+escluda preventivamente alcuni permessi (usualmente quello di scrittura per il
+gruppo e gli altri, corrispondente ad un valore per \param{mask} pari a
+$022$). In questo modo è possibile cancellare automaticamente i permessi non
+voluti. Di norma questo valore viene impostato una volta per tutte al login a
+$022$, e gli utenti non hanno motivi per modificarlo.
\subsection{Le funzioni \func{chown}, \func{fchown} e \func{lchown}}
In \tabref{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{stiky} con la notazione
+specificati i bit di \acr{suid}, \acr{sgid} e \acr{sticky} con la notazione
compatta illustrata in \figref{fig:file_perm_bit}.
\begin{table}[!htb]
questa sezione.
Come accennato in \secref{sec:proc_fork} ogni processo oltre ad una directory
-di lavoro corrente, ha anche una directory radice,\footnote{entrambe sono
- contenute in due campi di \struct{fs\_struct}, vedi
- \figref{fig:proc_task_struct}.} che è la directory che per il processo
-costituisce la radice dell'albero dei file e rispetto alla quale vengono
-risolti i pathname assoluti (si ricordi quanto detto in
-\secref{sec:file_organization}). La radice viene ereditata dal padre per ogni
-processo figlio, e quindi di norma coincide con la \file{/} del sistema.
-
-In certe situazioni però per motivi di sicurezza non si vuole che un processo
-possa accedere a tutto il filesystem; per questo si può cambiare la directory
-radice con la funzione \funcd{chroot}, il cui prototipo è:
+di lavoro, ha anche una directory \textsl{radice}\footnote{entrambe sono
+ contenute in due campi (rispettivamente \var{pwd} e \var{root}) di
+ \struct{fs\_struct}; vedi \figref{fig:proc_task_struct}.} che, pur essendo
+di norma corrispondente alla radice dell'albero di file e directory come visto
+dal kernel (ed illustrato in \secref{sec:file_organization}), ha per il
+processo il significato specifico di directory rispetto alla quale vengono
+risolti i pathname assoluti.\footnote{cioè quando un processo chiede la
+ risoluzione di un pathname, il kernel usa sempre questa directory come punto
+ di partenza.} Il fatto che questo valore sia specificato per ogni processo
+apre allora la possibilità di modificare le modalità di risoluzione dei
+pathname assoluti da parte di un processo cambiando questa directory, così
+come si fa coi pathname relativi cambiando la directory di lavoro.
+
+Normalmente la directory radice di un processo coincide anche con la radice
+del filesystem usata dal kernel, e dato che il suo valore viene ereditato dal
+padre da ogni processo figlio, in generale i processi risolvono i pathname
+assoluti a partire sempre dalla stessa directory, che corrisponde alla
+\file{/} del sistema.
+
+In certe situazioni però, per motivi di sicurezza, è utile poter impedire che
+un processo possa accedere a tutto il filesystem; per far questo si può
+cambiare la sua directory radice con la funzione \funcd{chroot}, il cui
+prototipo è:
\begin{prototype}{unistd.h}{int chroot(const char *path)}
Cambia la directory radice del processo a quella specificata da
\param{path}.
\errval{EROFS} e \errval{EIO}.}
\end{prototype}
\noindent in questo modo la directory radice del processo diventerà
-\param{path} (che ovviamente deve esistere) ed ogni pathname assoluto sarà
-risolto a partire da essa, rendendo impossibile accedere alla parte di albero
-sovrastante; si ha cioè quella che viene chiamata una \textit{chroot jail}.
-
-Solo l'amministratore può usare questa funzione, e la nuova radice, per quanto
-detto in \secref{sec:proc_fork}, sarà ereditata da tutti i processi figli. Si
-tenga presente che la funzione non cambia la directory di lavoro corrente, che
-potrebbe restare fuori dalla \textit{chroot jail}.
+\param{path} (che ovviamente deve esistere) ed ogni pathname assoluto usato
+dalle funzioni chiamate nel processo sarà risolto a partire da essa, rendendo
+impossibile accedere alla parte di albero sovrastante. Si ha così quella che
+viene chiamata una \textit{chroot jail}, in quanto il processo non può più
+accedere a file al di fuori della sezione di albero in cui è stato
+\textsl{imprigionato}.
+
+Solo un processo con i privilegi di amministratore può usare questa funzione,
+e la nuova radice, per quanto detto in \secref{sec:proc_fork}, sarà ereditata
+da tutti i suoi processi figli. Si tenga presente però che la funzione non
+cambia la directory di lavoro, che potrebbe restare fuori dalla \textit{chroot
+ jail}.
Questo è il motivo per cui la funzione è efficace solo se dopo averla eseguita
-si cedono i privilegi di root. Infatti se in qualche modo il processo ha una
-directory di lavoro corrente fuori dalla \textit{chroot jail}, potrà comunque
-accedere a tutto il filesystem usando pathname relativi.
-
-Ma quando ad un processo restano i privilegi di root esso potrà sempre portare
-la directory di lavoro corrente fuori dalla \textit{chroot jail} creando una
-sotto-directory ed eseguendo una \func{chroot} su di essa. Per questo motivo
-l'uso di questa funzione non ha molto senso quando un processo necessita dei
-privilegi di root per le sue normali operazioni.
+si cedono i privilegi di root. Infatti se per un qualche motivo il processo
+resta con la directory di lavoro fuori dalla \textit{chroot jail}, potrà
+comunque accedere a tutto il resto del filesystem usando pathname relativi, i
+quali, partendo dalla directory di lavoro che è fuori della \textit{chroot
+ jail}, potranno (con l'uso di \texttt{..}) risalire fino alla radice
+effettiva del filesystem.
+
+Ma se ad un processo restano i privilegi di amministratore esso potrà comunque
+portare la sua directory di lavoro fuori dalla \textit{chroot jail} in cui si
+trova. Basta infatti creare una nuova \textit{chroot jail} con l'uso di
+\func{chroot} su una qualunque directory contenuta nell'attuale directory di
+lavoro. Per questo motivo l'uso di questa funzione non ha molto senso quando
+un processo necessita dei privilegi di root per le sue normali operazioni.
Un caso tipico di uso di \func{chroot} è quello di un server FTP anonimo, in
questo caso infatti si vuole che il server veda solo i file che deve
\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 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 \capref{cha:intro_unix}.
+%% 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 \capref{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
utilizzare l'opportuna routine dichiarata in \struct{f\_ops} appropriata al
tipo di file in questione.
-Pertanto è possibile scrivere allo stesso modo sulla porta seriale come su
-normale un file di dati; ovviamente certe operazioni (nel caso della seriale
-ad esempio la \code{seek}) non saranno disponibili, però con questo sistema
+Pertanto è possibile scrivere allo stesso modo sulla porta seriale come su un
+normale file di dati; ovviamente certe operazioni (nel caso della seriale ad
+esempio la \code{seek}) non saranno disponibili, però con questo sistema
l'utilizzo di diversi filesystem (come quelli usati da Windows o MacOs) è
immediato e (relativamente) trasparente per l'utente ed il programmatore.
Il filesystem standard usato da Linux è il cosiddetto \textit{second extended
filesystem}, identificato dalla sigla \acr{ext2}. Esso supporta tutte le
caratteristiche di un filesystem standard Unix, è in grado di gestire nomi di
-file lunghi (256 caratteri, estendibili a 1012) con una dimensione massima di
+file lunghi (256 caratteri, estensibili a 1012) con una dimensione massima di
4~Tb.
Oltre alle caratteristiche standard, \acr{ext2} fornisce alcune estensioni che
int WriteStruct(FILE *stream, struct histogram *histo)
{
- if ( fwrite(vec, sizeof(*histo), 1, stream) !=1) {
+ if ( fwrite(histo, sizeof(*histo), 1, stream) !=1) {
perror("Write error");
}
return nread;
\cmd{\%X} &\ctyp{unsigned int}& Stampano un intero in formato esadecimale,
rispettivamente con lettere minuscole e
maiuscole. \\
- \cmd{\%f} &\ctyp{unsigned int}& Stampa un numero in virgola mobile con la
+ \cmd{\%f} &\ctyp{double} & Stampa un numero in virgola mobile con la
notazione a virgola fissa \\
\cmd{\%e},
\cmd{\%E} &\ctyp{double} & Stampano un numero in virgola mobile con la
La sostituzione di tutte le funzioni di I/O con le relative versioni
\code{\_unlocked} in un programma che non usa i thread è però un lavoro
-abbastanza noioso; per questo motivo le \acr{glibc} provvedono al
+abbastanza noioso; per questo motivo le \acr{glibc} forniscono al
programmatore pigro un'altra via\footnote{anche questa mutuata da estensioni
introdotte in Solaris.} da poter utilizzare per disabilitare in blocco il
locking degli stream: l'uso della funzione \funcd{\_\_fsetlocking}, il cui
tutte le ulteriori operazioni saranno compiute specificando questo stesso
valore come argomento alle varie funzioni dell'interfaccia.
-Per capire come funziona il meccanismo occorre spiegare a grandi linee come è
-che 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}.
+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
\func{write} bloccherà fino al completamento della scrittura di tutti dati
sul sull'hardware sottostante.\\
\const{O\_FSYNC} & sinonimo di \const{O\_SYNC}. \\
- \const{O\_NOATIME} & blocca l'aggiornamento dei tempi dei di accesso dei
+ \const{O\_NOATIME} & blocca l'aggiornamento dei tempi di accesso dei
file (vedi \secref{sec:file_file_times}). In Linux questa opzione non è
disponibile per il singolo file ma come opzione per il filesystem in fase
di montaggio.\\
\funcdecl{off\_t lseek(int fd, off\_t offset, int whence)}
Imposta la posizione attuale nel file.
- \bodydesc{La funzione ritorna valore della posizione corrente in caso di
+ \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:
\begin{errlist}
\label{sec:file_read}
-Una volta che un file è stato aperto (con il permesso in lettura) su possono
+Una volta che un file è stato aperto (con il permesso in lettura) si possono
leggere i dati che contiene utilizzando la funzione \funcd{read}, il cui
prototipo è:
\begin{prototype}{unistd.h}{ssize\_t read(int fd, void * buf, size\_t count)}
\label{fig:file_mult_acc}
\end{figure}
-Il primo caso è quello in cui due processi diversi che aprono lo stesso file
+Il primo caso è quello in cui due processi diversi aprono lo stesso file
su disco; sulla base di quanto visto in \secref{sec:file_fd} avremo una
situazione come quella illustrata in \figref{fig:file_mult_acc}: ciascun
processo avrà una sua voce nella \textit{file table} referenziata da un
%% gapil.tex: file principale, gli altri vanno inclusi da questo.
%%
\documentclass[a4paper,11pt,twoside,italian]{book}
+%\usepackage{tex4ht}
\usepackage[latin1]{inputenc}
\usepackage[bookmarks=true]{hyperref}
\usepackage{makeidx}
Livello 4&\textit{Transport} &\textsl{Trasporto} \\
Livello 3&\textit{Network} &\textsl{Rete}\\
Livello 2&\textit{DataLink} &\textsl{Collegamento Dati} \\
- Livello 1&\textit{Connection} &\textsl{Connessione Fisica} \\
+ Livello 1&\textit{Physical} &\textsl{Connessione Fisica} \\
\hline
\end{tabular}
\caption{I sette livelli del protocollo ISO/OSI.}
\end{table}
Il modello ISO/OSI è stato sviluppato in corrispondenza alla definizione della
-serie di protocolli X.25 per la commutazione di pacchetto. Ma nonostante il
-lavoro dettagliato di standardizzazione il modello si è rivelato
-sostanzialmente troppo complesso e poco flessibile rispetto a quello
-precedente, il TCP/IP, su cui si basa internet, che è diventato uno standard
-de facto. Il modello di quest'ultimo viene chiamato anche modello DoD (sigla
-che sta per \textit{Department of Defense}), dato che fu sviluppato
-dall'agenzia ARPA per il Dipartimento della Difesa Americano.
+serie di protocolli X.25 per la commutazione di pacchetto; come si vede è un
+modello abbastanza complesso\footnote{infatti per memorizzarne i vari livelli
+ è stata creata la frase \texttt{All people seem to need data processing}, in
+ cui ciascuna parola corrisponde all'iniziale di uno dei livelli.}, tanto che
+usualmente si tende a suddividerlo in due parti, secondo lo schema mostrato in
+\figref{fig:net_osi_tcpip_comp}, con un \textit{upper layer} che riguarda solo
+le applicazioni, che viene realizzato in user space, ed un \textit{lower
+ layer} in cui si mescolano la gestione fatta dal kernel e le funzionalità
+fornite dall'hardware.
+
+Il modello ISO/OSI mira ad effettuare una classificazione completamente
+generale di ogni tipo di protocollo di rete; nel frattempo però era stato
+sviluppato anche un altro modello, relativo al protocollo TCP/IP, che è quello
+su cui è basata internet, che è diventato uno standard de facto. Questo
+modello viene talvolta chiamato anche modello \textit{DoD} (sigla che sta per
+\textit{Department of Defense}), dato che fu sviluppato dall'agenzia ARPA per
+il Dipartimento della Difesa Americano.
+\begin{figure}[!htb]
+ \centering
+ \includegraphics[width=13cm]{img/iso_tcp_comp}
+ \caption{Struttura a livelli dei protocolli OSI e TCP/IP, con la
+ relative corrispondenze e la divisione fra kernel e user space.}
+ \label{fig:net_osi_tcpip_comp}
+\end{figure}
+
+La scelta fra quale dei due modelli utilizzare dipende per lo più dai gusti
+personali. Come caratteristiche generali il modello ISO/OSI è più teorico e
+generico, basato separazioni funzionali, mentre il modello TCP/IP è più vicino
+alla separazione concreta dei vari strati del sistema operativo; useremo
+pertanto quest'ultimo, anche per la sua maggiore semplicità.\footnote{questa
+ semplicità ha un costo quando si fa riferimento agli strati più bassi, che
+ sono in effetti descritti meglio dal modello ISO/OSI, in quanto gran parte
+ dei protocolli di trasmissione hardware sono appunto strutturati sui due
+ livelli di \textit{Data Link} e \textit{Connection}.}
\subsection{Il modello TCP/IP (o DoD)}
\label{sec:net_tcpip_overview}
(riassunti in \tabref{tab:net_layers}); un confronto fra i due è riportato in
\figref{fig:net_osi_tcpip_comp} dove viene evidenziata anche la corrispondenza
fra i rispettivi livelli (che comunque è approssimativa) e su come essi vanno
-ad inserirsi all'interno di un sistema rispetto alla divisione fra user space
-e kernel space spiegata in \secref{sec:intro_unix_struct}.\footnote{in realtà
- è possibile accedere, attraverso una opportuna interfaccia (come vedremo in
- \secref{sec:sock_sa_packet}), anche ai livelli inferiori.}
+ad inserirsi all'interno del sistema rispetto alla divisione fra user space e
+kernel space spiegata in \secref{sec:intro_unix_struct}.\footnote{in realtà è
+ sempre possibile accedere dallo user space, attraverso una opportuna
+ interfaccia (come vedremo in \secref{sec:sock_sa_packet}), ai livelli
+ inferiori del protocollo.}
\begin{table}[htb]
\centering
l'invio e la ricezione dei pacchetti da e verso l'hardware.
\end{basedescript}
-\begin{figure}[!htb]
- \centering
- \includegraphics[width=13cm]{img/iso_tcp_comp}
- \caption{Struttura a livelli dei protocolli OSI e TCP/IP, con la
- relative corrispondenze e la divisione fra kernel e user space.}
- \label{fig:net_osi_tcpip_comp}
-\end{figure}
-
La comunicazione fra due stazioni remote avviene secondo le modalità
illustrate in \figref{fig:net_tcpip_data_flux}, dove si è riportato il flusso
dei dati reali e i protocolli usati per lo scambio di informazione su ciascun
se in realtà i protocolli di trasmissione usati possono essere molti altri.
\begin{figure}[!htb]
- \centering \includegraphics[width=12cm]{img/tcp_data_flux}
+ \centering \includegraphics[width=13cm]{img/tcp_data_flux}
\caption{Strutturazione del flusso dei dati nella comunicazione fra due
applicazioni attraverso i protocolli della suite TCP/IP.}
\label{fig:net_tcpip_data_flux}
\item I dati delle applicazioni vengono inviati al livello di trasporto usando
un'interfaccia opportuna (i \textit{socket}\index{socket}, che esamineremo
in dettaglio in \capref{cha:socket_intro}). Qui verranno spezzati in
- pacchetti di dimensione opportuna e incapsulati nel protocollo di trasporto,
+ pacchetti di dimensione opportuna e inseriti nel protocollo di trasporto,
aggiungendo ad ogni pacchetto le informazioni necessarie per la sua
gestione. Questo processo viene svolto direttamente nel kernel, ad esempio
dallo stack TCP, nel caso il protocollo di trasporto usato sia questo.
Benché si parli di TCP/IP questa famiglia di protocolli è composta anche da
molti membri. In \figref{fig:net_tcpip_overview} si è riportato uno schema che
-mostra un panorama sui vari protocolli della famiglia, e delle loro relazioni
-reciproche e con alcune dalle principali applicazioni che li usano.
+mostra un panorama sui principali protocolli della famiglia, e delle loro
+relazioni reciproche e con alcune dalle principali applicazioni che li usano.
\begin{figure}[!htbp]
\centering
\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
+\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
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 funzioni vengono salvati nel contesto nello stack)
+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
Il programma che un processo sta eseguendo si chiama immagine del processo (o
\textit{process image}), le funzioni della famiglia \func{exec} permettono di
-caricare un'altro programma da disco sostituendo quest'ultimo all'immagine
+caricare un altro programma da disco sostituendo quest'ultimo all'immagine
corrente; questo fa sì che l'immagine precedente venga completamente
cancellata. Questo significa che quando il nuovo programma termina, anche il
processo termina, e non si può tornare alla precedente immagine.
e direttamente in \file{fork.c}, con il kernel 2.5.x e la nuova interfaccia
per i thread creata da Ingo Molnar anche il meccanismo di allocazione dei
\acr{pid} è stato modificato.} che serve a riservare i \acr{pid} più bassi
-ai processi eseguiti dal direttamente dal kernel. Per questo motivo, come
-visto in \secref{sec:proc_hierarchy}, il processo di avvio (\cmd{init}) ha
-sempre il \acr{pid} uguale a uno.
+ai processi eseguiti direttamente dal kernel. Per questo motivo, come visto
+in \secref{sec:proc_hierarchy}, il processo di avvio (\cmd{init}) ha sempre il
+\acr{pid} uguale a uno.
Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui
sono stati creati, questo viene chiamato in genere \acr{ppid} (da
candidato per generare ulteriori indicatori associati al processo di cui
diventa possibile garantire l'unicità: ad esempio in alcune implementazioni la
funzione \func{tmpname} (si veda \secref{sec:file_temp_file}) usa il \acr{pid}
-per generare un pathname univoco, che non potrà essere replicato da un'altro
+per generare un pathname univoco, che non potrà essere replicato da un altro
processo che usi la stessa funzione.
Tutti i processi figli dello stesso processo padre sono detti
zero al figlio; ritorna -1 al padre (senza creare il figlio) in caso di
errore; \var{errno} può assumere i valori:
\begin{errlist}
- \item[\errcode{EAGAIN}] non ci sono risorse sufficienti per creare un'altro
+ \item[\errcode{EAGAIN}] non ci sono risorse sufficienti per creare un altro
processo (per allocare la tabella delle pagine e le strutture del task) o
si è esaurito il numero di processi disponibili.
\item[\errcode{ENOMEM}] non è stato possibile allocare la memoria per le
(fino alla conclusione) e poi il padre.
In generale l'ordine di esecuzione dipenderà, oltre che dall'algoritmo di
-scheduling usato dal kernel, dalla particolare situazione in si trova la
+scheduling usato dal kernel, dalla particolare situazione in cui si trova la
macchina al momento della chiamata, risultando del tutto impredicibile.
Eseguendo più volte il programma di prova e producendo un numero diverso di
figli, si sono ottenute situazioni completamente diverse, compreso il caso in
scritto prima della sua creazione. E alla fine del file (dato che in questo
caso il padre esce per ultimo) troveremo anche l'output completo del padre.
-L'esempio ci mostra un'altro aspetto fondamentale dell'interazione con i file,
+L'esempio ci mostra un altro aspetto fondamentale dell'interazione con i file,
valido anche per l'esempio precedente, ma meno evidente: il fatto cioè che non
solo processi diversi possono scrivere in contemporanea sullo stesso file
(l'argomento della condivisione dei file è trattato in dettaglio in
\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, e o il processo viene tracciato, o il filesystem è montato con
+ \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{ENOEXEC}] il file è in un formato non eseguibile o non
riconosciuto come tale, o compilato per un'altra architettura.
specifica il programma che si vuole eseguire. Con lo mnemonico \code{p} si
indicano le due funzioni che replicano il comportamento della shell nello
specificare il comando da eseguire; quando il parametro \param{file} non
-contiene una \file{/} esso viene considerato come un nome di programma, e
+contiene una ``\file{/}'' esso viene considerato come un nome di programma, e
viene eseguita automaticamente una ricerca fra i file presenti nella lista di
directory specificate dalla variabile di ambiente \var{PATH}. Il file che
viene posto in esecuzione è il primo che viene trovato. Se si ha un errore
\acr{libc5}, e \file{/lib/ld-linux.so.2} per programmi linkati con le
\acr{glibc}. Infine nel caso il file sia uno script esso deve iniziare con
una linea nella forma \cmd{\#!/path/to/interpreter} dove l'interprete indicato
-deve esse un valido programma (binario, non un altro script) che verrà
-chiamato come se si fosse eseguito il comando \cmd{interpreter [arg]
+deve esse un programma valido (binario, non un altro script) che verrà
+chiamato come se si fosse eseguito il comando \cmd{interpreter [argomenti]
filename}.
Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è
in dettaglio in \secref{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).
+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:
per i quali erano richiesti, e a poterli eventualmente recuperare in caso
servano di nuovo.
-Questo in Linux viene fatto usando altri gli altri due gruppi di
-identificatori, il \textit{saved} ed il \textit{filesystem}. Il primo gruppo è
-lo stesso usato in SVr4, e previsto dallo standard POSIX quando è definita la
-costante \macro{\_POSIX\_SAVED\_IDS},\footnote{in caso si abbia a cuore la
- portabilità del programma su altri Unix è buona norma controllare sempre la
+Questo in Linux viene fatto usando altri due gruppi di identificatori, il
+\textit{saved} ed il \textit{filesystem}. Il primo gruppo è lo stesso usato in
+SVr4, e previsto dallo standard POSIX quando è definita la costante
+\macro{\_POSIX\_SAVED\_IDS},\footnote{in caso si abbia a cuore la portabilità
+ del programma su altri Unix è buona norma controllare sempre la
disponibilità di queste funzioni controllando se questa costante è
definita.} il secondo gruppo è specifico di Linux e viene usato per
migliorare la sicurezza con NFS.
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 questo sono stati impostati tenendo conto di eventuali \acr{suid} o
+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.
consentendo l'accesso a \file{/var/log/utmp}.
Occorre però tenere conto che tutto questo non è possibile con un processo con
-i privilegi di root, in tal caso infatti l'esecuzione una \func{setuid}
-comporta il cambiamento di tutti gli identificatori associati al processo,
-rendendo impossibile riguadagnare i privilegi di amministratore. Questo
-comportamento è corretto per l'uso che ne fa \cmd{login} una volta che crea
-una nuova shell per l'utente; ma quando si vuole cambiare soltanto
+i privilegi di amministratore, in tal caso infatti l'esecuzione di una
+\func{setuid} comporta il cambiamento di tutti gli identificatori associati al
+processo, rendendo impossibile riguadagnare i privilegi di amministratore.
+Questo comportamento è corretto per l'uso che ne fa \cmd{login} una volta che
+crea una nuova shell per l'utente; ma quando si vuole cambiare soltanto
l'\textsl{user-ID effettivo} del processo per cedere i privilegi occorre
ricorrere ad altre funzioni (si veda ad esempio \secref{sec:proc_seteuid}).
-\subsection{Le funzioni \func{setreuid} e \func{setresuid}}
+\subsection{Le funzioni \func{setreuid} e \func{setregid}}
\label{sec:proc_setreuid}
-Queste due funzioni derivano da BSD che, non supportando\footnote{almeno fino
- alla versione 4.3+BSD TODO, FIXME verificare e aggiornare la nota.} gli
-identificatori del gruppo \textit{saved}, le usa per poter scambiare fra di
-loro \textit{effective} e \textit{real}. I loro prototipi sono:
+Le due funzioni \funcd{setreuid} e \funcd{setregid} derivano da BSD che, non
+supportando\footnote{almeno fino alla versione 4.3+BSD TODO, FIXME verificare
+ e aggiornare la nota.} gli identificatori del gruppo \textit{saved}, le usa
+per poter scambiare fra di loro \textit{effective} e \textit{real}. I
+rispettivi prototipi sono:
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
dell'user-ID effettivo.
-\subsection{Le funzioni \funcd{seteuid} e \funcd{setegid}}
+\subsection{Le funzioni \func{seteuid} e \func{setegid}}
\label{sec:proc_seteuid}
-Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
-supportate dalla maggior parte degli Unix) e vengono usate per cambiare gli
-identificatori del gruppo \textit{effective}; i loro prototipi sono:
+Le due funzioni \funcd{seteuid} e \funcd{setegid} sono un'estensione allo
+standard POSIX.1 (ma sono comunque supportate dalla maggior parte degli Unix)
+e vengono usate per cambiare gli identificatori del gruppo \textit{effective};
+i loro prototipi sono:
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
normale di \func{setuid} comporta l'impostazione di tutti gli identificatori.
-\subsection{Le funzioni \funcd{setresuid} e \funcd{setresgid}}
+\subsection{Le funzioni \func{setresuid} e \func{setresgid}}
\label{sec:proc_setresuid}
-Queste due funzioni sono un'estensione introdotta in Linux dal kernel 2.1.44,
-e permettono un completo controllo su tutti gli identificatori (\textit{real},
-\textit{effective} e \textit{saved}), i prototipi sono:
+Le due funzioni \funcd{setresuid} e \funcd{setresgid} sono un'estensione
+introdotta in Linux,\footnote{a partire dal kernel 2.1.44.} e permettono un
+completo controllo su tutti e tre i gruppi di identificatori (\textit{real},
+\textit{effective} e \textit{saved}), i loro prototipi sono:
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
Anche queste funzioni sono un'estensione specifica di Linux, e non richiedono
nessun privilegio. I valori sono restituiti negli argomenti, che vanno
-specificati come puntatori (è un'altro esempio di \textit{value result
+specificati come puntatori (è un altro esempio di \textit{value result
argument}). Si noti che queste funzioni sono le uniche in grado di leggere
gli identificatori del gruppo \textit{saved}.
\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
\label{sec:proc_setfsuid}
-Queste funzioni sono usate per impostare gli identificatori del gruppo
-\textit{filesystem} che usati da Linux per il controllo dell'accesso ai file.
-Come già accennato in \secref{sec:proc_access_id} Linux definisce questo
-ulteriore gruppo di identificatori, che di norma sono assolutamente
-equivalenti a quelli del gruppo \textit{effective}, dato che ogni cambiamento
-di questi ultimi viene immediatamente riportato su di essi.
+Queste funzioni servono per impostare gli identificatori del gruppo
+\textit{filesystem} che sono usati da Linux per il controllo dell'accesso ai
+file. Come già accennato in \secref{sec:proc_access_id} Linux definisce
+questo ulteriore gruppo di identificatori, che in circostanze normali sono
+assolutamente equivalenti a quelli del gruppo \textit{effective}, dato che
+ogni cambiamento di questi ultimi viene immediatamente riportato su di essi.
C'è un solo caso in cui si ha necessità di introdurre una differenza fra gli
identificatori dei gruppi \textit{effective} e \textit{filesystem}, ed è per
ovviare ad un problema di sicurezza che si presenta quando si deve
-implementare un server NFS. Il server NFS infatti deve poter cambiare
-l'identificatore con cui accede ai file per assumere l'identità del singolo
-utente remoto, ma se questo viene fatto cambiando l'user-ID effettivo o
-l'user-ID reale il server si espone alla ricezione di eventuali segnali ostili
-da parte dell'utente di cui ha temporaneamente assunto l'identità. Cambiando
-solo l'user-ID di filesystem si ottengono i privilegi necessari per accedere ai
-file, mantenendo quelli originari per quanto riguarda tutti gli altri
-controlli di accesso, così che l'utente non possa inviare segnali al server
-NFS.
+implementare un server NFS.
+
+Il server NFS infatti deve poter cambiare l'identificatore con cui accede ai
+file per assumere l'identità del singolo utente remoto, ma se questo viene
+fatto cambiando l'user-ID effettivo o l'user-ID reale il server si espone alla
+ricezione di eventuali segnali ostili da parte dell'utente di cui ha
+temporaneamente assunto l'identità. Cambiando solo l'user-ID di filesystem si
+ottengono i privilegi necessari per accedere ai file, mantenendo quelli
+originari per quanto riguarda tutti gli altri controlli di accesso, così che
+l'utente non possa inviare segnali al server NFS.
Le due funzioni usate per cambiare questi identificatori sono \funcd{setfsuid}
e \funcd{setfsgid}, ovviamente sono specifiche di Linux e non devono essere
modificato, ma si ottiene il numero di gruppi supplementari.
Una seconda funzione, \funcd{getgrouplist}, può invece essere usata per
-ottenere tutti i gruppi a cui appartiene un utente; il suo prototipo è:
+ottenere tutti i gruppi a cui appartiene un certo utente; il suo prototipo è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{grp.h}
restituisce 0 in caso di successo e -1 in caso di fallimento.}
\end{functions}
-La funzione legge i gruppi supplementari dell'utente \param{user} eseguendo
-una scansione del database dei gruppi (si veda \secref{sec:sys_user_group}) e
-ritorna in \param{groups} la lista di quelli a cui l'utente appartiene. Si
-noti che \param{ngroups} è passato come puntatore perché qualora il valore
-specificato sia troppo piccolo la funzione ritorna -1, passando indietro il
-numero dei gruppi trovati.
+La funzione legge i gruppi supplementari dell'utente specificato da
+\param{user}, eseguendo una scansione del database dei gruppi (si veda
+\secref{sec:sys_user_group}). Ritorna poi in \param{groups} la lista di quelli
+a cui l'utente appartiene. Si noti che \param{ngroups} è passato come
+puntatore perché, qualora il valore specificato sia troppo piccolo, la
+funzione ritorna -1, passando indietro il numero dei gruppi trovati.
Per impostare i gruppi supplementari di un processo ci sono due funzioni, che
possono essere usate solo se si hanno i privilegi di amministratore. La prima
\func{setgroups}. Si tenga presente che sia \func{setgroups} che
\func{initgroups} non sono definite nello standard POSIX.1 e che pertanto non
è possibile utilizzarle quando si definisce \macro{\_POSIX\_SOURCE} o si
-compila con il flag \cmd{-ansi}.
+compila con il flag \cmd{-ansi}, è pertanto meglio evitarle se si vuole
+scrivere codice portabile.
\section{La gestione della priorità di esecuzione}
\textbf{Runnable}& \texttt{R} & Il processo è in esecuzione o è pronto ad
essere eseguito (cioè è in attesa che gli
venga assegnata la CPU). \\
- \textbf{Sleep} & \texttt{S} & Il processo processo è in attesa di un
+ \textbf{Sleep} & \texttt{S} & Il processo è in attesa di un
risposta dal sistema, ma può essere
interrotto da un segnale. \\
\textbf{Uninterrutible Sleep}& \texttt{D} & Il processo è in
nell'esecuzione.
Il meccanismo usato da Linux è piuttosto semplice, ad ogni processo è
-assegnata una \textit{time-slice}, cioè in intervallo di tempo (letteralmente
+assegnata una \textit{time-slice}, cioè un intervallo di tempo (letteralmente
una fetta) per il quale esso deve essere eseguito. Il valore della
\textit{time-slice} è controllato dalla cosiddetta \textit{nice} (o
\textit{niceness}) del processo. Essa è contenuta nel campo \var{nice} di
La priorità di un processo è così controllata attraverso il valore di
\var{nice}, che stabilisce la durata della \textit{time-slice}; per il
-meccanismo appena descritto infatti un valore più lungo infatti assicura una
-maggiore attribuzione di CPU. L'origine del nome di questo parametro sta nel
-fatto che generalmente questo viene usato per diminuire la priorità di un
-processo, come misura di cortesia nei confronti degli altri. I processi
-infatti vengono creati dal sistema con lo stesso valore di \var{nice} (nullo)
-e nessuno è privilegiato rispetto agli altri; il valore può essere modificato
-solo attraverso la funzione \funcd{nice}, il cui prototipo è:
+meccanismo appena descritto infatti un valore più lungo assicura una maggiore
+attribuzione di CPU. L'origine del nome di questo parametro sta nel fatto che
+generalmente questo viene usato per diminuire la priorità di un processo, come
+misura di cortesia nei confronti degli altri. I processi infatti vengono
+creati dal sistema con lo stesso valore di \var{nice} (nullo) e nessuno è
+privilegiato rispetto agli altri; il valore può essere modificato solo
+attraverso la funzione \funcd{nice}, il cui prototipo è:
\begin{prototype}{unistd.h}
{int nice(int inc)}
Aumenta il valore di \var{nice} per il processo corrente.
metterà in esecuzione prima di ogni processo normale. In caso di più processi
sarà eseguito per primo quello con priorità assoluta più alta. Quando ci sono
più processi con la stessa priorità assoluta questi vengono tenuti in una coda
-tocca al kernel decidere quale deve essere eseguito.
+e tocca al kernel decidere quale deve essere eseguito.
Il meccanismo con cui vengono gestiti questi processi dipende dalla politica
di scheduling che si è scelto; lo standard ne prevede due:
\end{errlist}}
\end{prototype}
-La funzione restituisce il valore (secondo la quanto elencato in
+La funzione restituisce il valore (secondo quanto elencato in
\tabref{tab:proc_sched_policy}) della politica di scheduling per il processo
specificato; se \param{pid} è nullo viene restituito quello del processo
chiamante.
stati completati.
Dato che in un sistema multitasking ogni processo può essere interrotto in
-qualunque momento per farne subentrare un'altro in esecuzione, niente può
+qualunque momento per farne subentrare un altro in esecuzione, niente può
assicurare un preciso ordine di esecuzione fra processi diversi o che una
sezione di un programma possa essere eseguita senza interruzioni da parte di
altri. Queste situazioni comportano pertanto errori estremamente subdoli e
correzioni, i consigli sull'esposizione ed i contributi relativi alle
calling convention dei linguaggi e al confronto delle diverse tecniche di
gestione della memoria.
+\item[\textbf{Mirko Maischberger}] per la rilettura, le numerose correzioni,
+ la segnalazione dei passi poco chiari ed il grande lavoro svolto per
+ produrre una versione della guida in un HTML piacevole ed accurato.
\end{description}
Infine, ultimo, ma primo per importanza, voglio ringraziare il Firenze Linux
\subsection{Limiti e parametri di sistema}
\label{sec:sys_limits}
-Quando si devono determinare le le caratteristiche generali del sistema ci si
+Quando si devono determinare le caratteristiche generali del sistema ci si
trova di fronte a diverse possibilità; alcune di queste infatti possono
dipendere dall'architettura dell'hardware (come le dimensioni dei tipi
interi), o dal sistema operativo (come la presenza o meno del gruppo degli
\end{functions}
I parametri a cui la funzione permettere di accedere sono organizzati in
-maniera gerarchica all'interno un albero;\footnote{si tenga presente che
+maniera gerarchica all'interno di un albero;\footnote{si tenga presente che
includendo solo \file{unistd.h}, saranno definiti solo i parametri generici;
dato che ce ne sono molti specifici dell'implementazione, nel caso di Linux
occorrerà includere anche i file \file{linux/unistd.h} e
attraverso l'array \param{name}, di lunghezza \param{nlen}, che contiene la
sequenza dei vari nodi da attraversare. Ogni parametro ha un valore in un
formato specifico che può essere un intero, una stringa o anche una struttura
-complessa, per questo motivo il valori vengono passati come puntatori
+complessa, per questo motivo i valori vengono passati come puntatori
\ctyp{void}.
L'indirizzo a cui il valore corrente del parametro deve essere letto è
può modificarne il valore. Il valore di questi limiti è mantenuto in una
struttura \struct{rlimit}, la cui definizione è riportata in
\figref{fig:sys_rlimit_struct}, ed i cui campi corrispondono appunto a limite
-corrente e massimo.
+corrente e limite massimo.
\begin{figure}[!htb]
\footnotesize
verranno considerati nel calcolo di questi tempi.
-
\subsection{Le funzioni per il \textit{calendar time}}
\label{sec:sys_time_base}
corrisponde ad un tipo elementare (in Linux è definito come \ctyp{long int},
che di norma corrisponde a 32 bit). Il valore corrente del \textit{calendar
time}, che indicheremo come \textsl{tempo di sistema}, può essere ottenuto
-con la funzione \funcd{time} che lo restituisce in nel suddetto formato; il
-suo prototipo è:
+con la funzione \funcd{time} che lo restituisce nel suddetto formato; il suo
+prototipo è:
\begin{prototype}{time.h}{time\_t time(time\_t *t)}
Legge il valore corrente del \textit{calendar time}.