From 041fde8aba0e18bb746653a060619b32ea9240ce Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Wed, 9 Mar 2005 16:05:03 +0000 Subject: [PATCH] Correzioni ed aggiustamenti vari, passati dall'uso di caption2 a quello di caption. --- fileadv.tex | 56 +++++++++++++++++++++++++++++---------------------- ipc.tex | 57 ++++++++++++++++++++++++++-------------------------- session.tex | 2 +- signal.tex | 44 +++++++++++++++++++--------------------- sockctrl.tex | 2 +- socket.tex | 28 +++++++++++++------------- 6 files changed, 98 insertions(+), 91 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index 6d87e62..4e8e93f 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -982,29 +982,34 @@ rispetto a quella classica vista in cap.~\ref{cha:file_unix_interface}, cosiddetto \textit{memory-mapped I/O}, che, attraverso il meccanismo della \textsl{paginazione}\index{paginazione} usato dalla memoria virtuale (vedi sez.~\ref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un -file in una sezione dello spazio di indirizzi del processo. Il meccanismo è -illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del file viene -riportata direttamente nello spazio degli indirizzi del programma. Tutte le -operazioni su questa zona verranno riportate indietro sul file dal meccanismo -della memoria virtuale\index{memoria~virtuale} che trasferirà il contenuto di -quel segmento sul file invece che nella swap, per cui si può parlare tanto di -file mappato in memoria, quanto di memoria mappata su file. +file in una sezione dello spazio di indirizzi del processo. + +Il meccanismo è illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del +file viene \textsl{mappata} direttamente nello spazio degli indirizzi del +programma. Tutte le operazioni di lettura e scrittura su variabili contenute +in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto +del file attraverso il sistema della memoria virtuale\index{memoria~virtuale} +che in maniera analoga a quanto avviene per le pagine che vengono salvate e +rilette nella swap, si incaricherà di sincronizzare il contenuto di quel +segmento di memoria con quello del file mappato su di esso. Per questo motivo +si può parlare tanto di \textsl{file mappato in memoria}, quanto di +\textsl{memoria mappata su file}. \begin{figure}[htb] \centering - \includegraphics[width=7.cm]{img/mmap_layout} + \includegraphics[width=14cm]{img/mmap_layout} \caption{Disposizione della memoria di un processo quando si esegue la mappatura in memoria di un file.} \label{fig:file_mmap_layout} \end{figure} -Tutto questo comporta una notevole semplificazione delle operazioni di I/O, in -quanto non sarà più necessario utilizzare dei buffer intermedi su cui -appoggiare i dati da traferire, ma questi potranno essere acceduti -direttamente nella sezione di memoria mappata; inoltre questa interfaccia è -più efficiente delle usuali funzioni di I/O, in quanto permette di caricare in -memoria solo le parti del file che sono effettivamente usate ad un dato -istante. +L'uso del \textit{memory-mappung} comporta una notevole semplificazione delle +operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer +intermedi su cui appoggiare i dati da traferire, poiché questi potranno essere +acceduti direttamente nella sezione di memoria mappata; inoltre questa +interfaccia è più efficiente delle usuali funzioni di I/O, in quanto permette +di caricare in memoria solo le parti del file che sono effettivamente usate ad +un dato istante. Infatti, dato che l'accesso è fatto direttamente attraverso la memoria virtuale,\index{memoria~virtuale} la sezione di memoria mappata su cui si @@ -1012,15 +1017,18 @@ opera sar per le parti effettivamente usate, il tutto in maniera completamente trasparente al processo; l'accesso alle pagine non ancora caricate avverrà allo stesso modo con cui vengono caricate in memoria le pagine che sono state -salvate sullo swap. Infine in situazioni in cui la memoria è scarsa, le -pagine che mappano un file vengono salvate automaticamente, così come le -pagine dei programmi vengono scritte sulla swap; questo consente di accedere -ai file su dimensioni il cui solo limite è quello dello spazio di indirizzi -disponibile, e non della memoria su cui possono esserne lette delle porzioni. - -L'interfaccia prevede varie funzioni per la gestione del \textit{memory mapped - I/O}, la prima di queste è \funcd{mmap}, che serve ad eseguire la mappatura -in memoria di un file; il suo prototipo è: +salvate sullo swap. + +Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un file +vengono salvate automaticamente, così come le pagine dei programmi vengono +scritte sulla swap; questo consente di accedere ai file su dimensioni il cui +solo limite è quello dello spazio di indirizzi disponibile, e non della +memoria su cui possono esserne lette delle porzioni. + +L'interfaccia POSIX implementata da Linux prevede varie funzioni per la +gestione del \textit{memory mapped I/O}, la prima di queste, che serve ad +eseguire la mappatura in memoria di un file, è \funcd{mmap}; il suo prototipo +è: \begin{functions} \headdecl{unistd.h} diff --git a/ipc.tex b/ipc.tex index fa3f73c..e76fd7b 100644 --- a/ipc.tex +++ b/ipc.tex @@ -2179,7 +2179,7 @@ a queste strutture restano per compatibilit vecchie versioni delle librerie del C, come le libc5.} \begin{figure}[htb] - \centering \includegraphics[width=15cm]{img/semtruct} + \centering \includegraphics[width=13cm]{img/semtruct} \caption{Schema della struttura di un insieme di semafori.} \label{fig:ipc_sem_schema} \end{figure} @@ -2191,12 +2191,13 @@ possono avere successo; se una di esse comporta il blocco del processo il kernel crea una struttura \struct{sem\_queue} che viene aggiunta in fondo alla coda di attesa associata a ciascun insieme di semafori\footnote{che viene referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last} - di \struct{semid\_ds}.}. Nella struttura viene memorizzato il riferimento -alle operazioni richieste (nel campo \var{sops}, che è un puntatore ad una -struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper}) -poi quest'ultimo viene messo stato di attesa e viene invocato lo -scheduler\index{\textit{scheduler}} per passare all'esecuzione di un altro -processo. + di \struct{semid\_ds}.}. + +Nella struttura viene memorizzato il riferimento alle operazioni richieste +(nel campo \var{sops}, che è un puntatore ad una struttura \struct{sembuf}) e +al processo corrente (nel campo \var{sleeper}) poi quest'ultimo viene messo +stato di attesa e viene invocato lo scheduler\index{\textit{scheduler}} per +passare all'esecuzione di un altro processo. Se invece tutte le operazioni possono avere successo queste vengono eseguite immediatamente, dopo di che il kernel esegue una scansione della coda di @@ -2205,13 +2206,12 @@ operazioni sospese in precedenza pu struttura \struct{sem\_queue} viene rimossa e lo stato del processo associato all'operazione (\var{sleeper}) viene riportato a \textit{running}; il tutto viene ripetuto fin quando non ci sono più operazioni eseguibili o si è -svuotata la coda. - -Per gestire il meccanismo del ripristino tutte le volte che per un'operazione -si è specificato il flag \const{SEM\_UNDO} viene mantenuta per ciascun insieme -di semafori una apposita struttura \struct{sem\_undo} che contiene (nel vettore -puntato dal campo \var{semadj}) un valore di aggiustamento per ogni semaforo -cui viene sommato l'opposto del valore usato per l'operazione. +svuotata la coda. Per gestire il meccanismo del ripristino tutte le volte che +per un'operazione si è specificato il flag \const{SEM\_UNDO} viene mantenuta +per ciascun insieme di semafori una apposita struttura \struct{sem\_undo} che +contiene (nel vettore puntato dal campo \var{semadj}) un valore di +aggiustamento per ogni semaforo cui viene sommato l'opposto del valore usato +per l'operazione. Queste strutture sono mantenute in due liste,\footnote{rispettivamente attraverso i due campi \var{id\_next} e \var{proc\_next}.} una associata @@ -2221,20 +2221,21 @@ operazione con \func{semctl}; l'altra associata al processo che ha eseguito l'operazione;\footnote{attraverso il campo \var{semundo} di \struct{task\_struct}, come mostrato in \ref{fig:ipc_sem_schema}.} quando un processo termina, la lista ad esso associata viene scandita e le operazioni -applicate al semaforo. - -Siccome un processo può accumulare delle richieste di ripristino per semafori -differenti chiamate attraverso diverse chiamate a \func{semop}, si pone il -problema di come eseguire il ripristino dei semafori all'uscita del processo, -ed in particolare se questo può essere fatto atomicamente. Il punto è cosa -succede quando una delle operazioni previste per il ripristino non può essere -eseguita immediatamente perché ad esempio il semaforo è occupato; in tal caso -infatti, se si pone il processo in stato di \textit{sleep} aspettando la -disponibilità del semaforo (come faceva l'implementazione originaria) si perde -l'atomicità dell'operazione. La scelta fatta dal kernel è pertanto quella di -effettuare subito le operazioni che non prevedono un blocco del processo e di -ignorare silenziosamente le altre; questo però comporta il fatto che il -ripristino non è comunque garantito in tutte le occasioni. +applicate al semaforo. Siccome un processo può accumulare delle richieste di +ripristino per semafori differenti chiamate attraverso diverse chiamate a +\func{semop}, si pone il problema di come eseguire il ripristino dei semafori +all'uscita del processo, ed in particolare se questo può essere fatto +atomicamente. + +Il punto è cosa succede quando una delle operazioni previste per il ripristino +non può essere eseguita immediatamente perché ad esempio il semaforo è +occupato; in tal caso infatti, se si pone il processo in stato di +\textit{sleep} aspettando la disponibilità del semaforo (come faceva +l'implementazione originaria) si perde l'atomicità dell'operazione. La scelta +fatta dal kernel è pertanto quella di effettuare subito le operazioni che non +prevedono un blocco del processo e di ignorare silenziosamente le altre; +questo però comporta il fatto che il ripristino non è comunque garantito in +tutte le occasioni. Come esempio di uso dell'interfaccia dei semafori vediamo come implementare con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice diff --git a/session.tex b/session.tex index 8ac200a..64d3f21 100644 --- a/session.tex +++ b/session.tex @@ -964,7 +964,7 @@ bufferizzazione\footnote{completamente indipendente dalla eventuale ulteriore kernel. \begin{figure}[htb] - \centering \includegraphics[width=13cm]{img/term_struct} + \centering \includegraphics[width=14.5cm]{img/term_struct} \caption{Struttura interna generica di un driver per un terminale.} \label{fig:term_struct} \end{figure} diff --git a/signal.tex b/signal.tex index c34a7d3..61d340f 100644 --- a/signal.tex +++ b/signal.tex @@ -433,16 +433,13 @@ processo che li ha causati. In genere oltre a questo il segnale provoca pure la registrazione su disco di un file di \textit{core dump} che viene scritto in un file \file{core} nella directory corrente del processo al momento dell'errore, che il debugger può usare per ricostruire lo stato del programma -al momento della terminazione. - -Questi segnali sono: +al momento della terminazione. Questi segnali sono: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{SIGFPE}] Riporta un errore aritmetico fatale. Benché il nome derivi da \textit{floating point exception} si applica a tutti gli errori - aritmetici compresa la divisione per zero e l'overflow. - - Se il gestore ritorna il comportamento del processo è indefinito, ed - ignorare questo segnale può condurre ad un ciclo infinito. + aritmetici compresa la divisione per zero e l'overflow. Se il gestore + ritorna il comportamento del processo è indefinito, ed ignorare questo + segnale può condurre ad un ciclo infinito. % Per questo segnale le cose sono complicate dal fatto che possono esserci % molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo @@ -578,9 +575,8 @@ sempre la necessit Questi segnali operano in congiunzione con le funzioni di I/O asincrono. Per questo occorre comunque usare \func{fcntl} per abilitare un file descriptor a -generare questi segnali. - -L'azione predefinita è di essere ignorati. Questi segnali sono: +generare questi segnali. L'azione predefinita è di essere ignorati. Questi +segnali sono: \begin{basedescript}{\desclabelwidth{2.0cm}} \item[\const{SIGIO}] Questo segnale viene inviato quando un file descriptor è pronto per eseguire dell'input/output. In molti sistemi solo i @@ -651,10 +647,8 @@ cui si trattano gli argomenti relativi. Questi segnali sono: Questi segnali sono usati per riportare al programma errori generati da operazioni da lui eseguite; non indicano errori del programma quanto errori che impediscono il completamento dell'esecuzione dovute all'interazione con il -resto del sistema. - -L'azione predefinita di questi segnali è di terminare il processo, questi -segnali sono: +resto del sistema. L'azione predefinita di questi segnali è di terminare il +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 @@ -663,9 +657,12 @@ segnali sono: terminato inavvertitamente alla scrittura sulla pipe il kernel genera questo segnale. Se il segnale è bloccato, intercettato o ignorato la chiamata che lo ha causato fallisce, restituendo l'errore \errcode{EPIPE}. -\item[\const{SIGLOST}] Sta per \textit{Resource lost}. Viene generato quando - c'è un advisory lock su un file NFS, ed il server riparte dimenticando la - situazione precedente. +\item[\const{SIGLOST}] Sta per \textit{Resource lost}. Tradizionalmente è il + segnale che generato quando si ha un advisory lock su un file su NFS che + viene perso perché il server NFS è stato riavviato. Il progetto GNU lo + utilizza per indicare ad un client il crollo inaspettato di un server. In + Linux è definito come sinonimo di \const{SIGIO}.\footnote{ed è segnalato + come BUG nella pagina di manuale.} \item[\const{SIGXCPU}] Sta per \textit{CPU time limit exceeded}. Questo segnale è generato quando un processo eccede il limite impostato per il tempo di CPU disponibile, vedi sez.~\ref{sec:sys_resource_limit}. @@ -805,9 +802,10 @@ presenta questa situazione presenti (come per certi file di dispositivo\index{file!di~dispositivo}, i socket\index{socket} o le pipe). \item la scrittura sugli stessi file, nel caso in cui dati non possano essere - accettati immediatamente. + accettati immediatamente (di nuovo comune per i socket). \item l'apertura di un file di dispositivo che richiede operazioni non - immediate per una risposta. + immediate per una risposta (ad esempio l'apertura di un nastro che deve + essere riavvolto). \item le operazioni eseguite con \func{ioctl} che non è detto possano essere eseguite immediatamente. \item le funzioni di intercomunicazione che si bloccano in attesa di risposte @@ -817,12 +815,12 @@ presenta questa situazione \item la funzione \func{wait} (se nessun processo figlio è ancora terminato). \end{itemize*} -In questo caso si pone il problema di cosa fare una volta che il gestore -sia ritornato. La scelta originaria dei primi Unix era quella di far ritornare +In questo caso si pone il problema di cosa fare una volta che il gestore sia +ritornato. La scelta originaria dei primi Unix era quella di far ritornare anche la system call restituendo l'errore di \errcode{EINTR}. Questa è a tutt'oggi una scelta corrente, ma comporta che i programmi che usano dei -gestori controllino lo stato di uscita delle funzioni per ripeterne la -chiamata qualora l'errore fosse questo. +gestori controllino lo stato di uscita delle funzioni che eseguono una system +call lenta per ripeterne la chiamata qualora l'errore fosse questo. Dimenticarsi di richiamare una system call interrotta da un segnale è un errore comune, tanto che le \acr{glibc} provvedono una macro diff --git a/sockctrl.tex b/sockctrl.tex index 4bc3bc4..ebbcee9 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -49,7 +49,7 @@ necessita di compiere questa operazione. \begin{figure}[htb] \centering - \includegraphics[width=10cm]{img/resolver} + \includegraphics[width=9cm]{img/resolver} \caption{Schema di funzionamento delle routine del \textit{resolver}.} \label{fig:sock_resolver_schema} \end{figure} diff --git a/socket.tex b/socket.tex index 48947e3..eb43ce5 100644 --- a/socket.tex +++ b/socket.tex @@ -750,6 +750,14 @@ due modi, chiamati rispettivamente \textit{big endian} e \textit{little variabili intere (ed in genere in diretta corrispondenza a come sono poi in realtà cablati sui bus interni del computer). +\begin{figure}[htb] + \centering + \includegraphics[height=3cm]{img/endianess} + \caption{Schema della disposizione dei dati in memoria a seconda della + \textit{endianess}.} + \label{fig:sock_endianess} +\end{figure} + Per capire meglio il problema si consideri un intero a 32 bit scritto in una locazione di memoria posta ad un certo indirizzo. Come illustrato in fig.~\ref{fig:sock_endianess} i singoli bit possono essere disposti un memoria @@ -761,14 +769,6 @@ dato che si trova per prima la parte pi parte dal bit meno significativo è detto per lo stesso motivo \textit{little endian}. -\begin{figure}[htb] - \centering - \includegraphics[height=3cm]{img/endianess} - \caption{Schema della disposizione dei dati in memoria a seconda della - \textit{endianess}.} - \label{fig:sock_endianess} -\end{figure} - Si può allora verificare quale tipo di \textit{endianess} usa il proprio computer con un programma elementare che si limita ad assegnare un valore ad una variabile per poi ristamparne il contenuto leggendolo un byte alla volta. @@ -808,12 +808,6 @@ in Linux l'ordinamento resta sempre lo stesso, anche quando il processore permetterebbe di eseguire questi cambiamenti. -Per controllare quale tipo di ordinamento si ha sul proprio computer si è -scritta una piccola funzione di controllo, il cui codice è riportato -fig.~\ref{fig:sock_endian_code}, che restituisce un valore nullo (falso) se -l'architettura è \textit{big endian} ed uno non nullo (vero) se l'architettura -è \textit{little endian}. - \begin{figure}[htb] \footnotesize \centering \begin{minipage}[c]{15cm} @@ -825,6 +819,12 @@ l'architettura \label{fig:sock_endian_code} \end{figure} +Per controllare quale tipo di ordinamento si ha sul proprio computer si è +scritta una piccola funzione di controllo, il cui codice è riportato +fig.~\ref{fig:sock_endian_code}, che restituisce un valore nullo (falso) se +l'architettura è \textit{big endian} ed uno non nullo (vero) se l'architettura +è \textit{little endian}. + Come si vede la funzione è molto semplice, e si limita, una volta assegnato (\texttt{\small 9}) un valore di test pari a \texttt{0xABCD} ad una variabile di tipo \ctyp{short} (cioè a 16 bit), a ricostruirne una copia byte a byte. -- 2.30.2