%% ipc.tex
%%
-%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
Tutto ciò ci mostra come sia immediato realizzare un meccanismo di
comunicazione fra processi attraverso una pipe, utilizzando le proprietà
-ordinarie dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
+ordinarie dei file, ma ci mostra anche qual è il principale\footnote{Stevens
in \cite{APUE} riporta come limite anche il fatto che la comunicazione è
unidirezionale, ma in realtà questo è un limite facilmente superabile usando
una coppia di pipe.} limite nell'uso delle pipe. È necessario infatti che i
\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
-di un codice a barre, specificato come parametro di input.
+di un codice a barre, specificato come argomento in ingresso.
Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
delle caratteristiche specifiche, esso infatti non viene lanciato da una
shell, ma dallo stesso web server, alla richiesta di una specifica URL, che di
solito ha la forma:
\begin{verbatim}
- http://www.sito.it/cgi-bin/programma?parametro
+ http://www.sito.it/cgi-bin/programma?argomento
\end{verbatim}
ed il risultato dell'elaborazione deve essere presentato (con una intestazione
che ne descrive il mime-type) sullo standard output, in modo che il web-server
effettivamente eseguiti. Questo non comporta nessun problema dato che la
lettura su una pipe è bloccante, per cui ciascun processo, per quanto lanciato
per primo, si bloccherà in attesa di ricevere sullo standard input il
-risultato dell'elaborazione del precedente, benchè quest'ultimo venga invocato
+risultato dell'elaborazione del precedente, benché quest'ultimo venga invocato
dopo.
\begin{figure}[!htb]
La funzione restituisce in \param{sv} la coppia di descrittori connessi fra di
loro: quello che si scrive su uno di essi sarà ripresentato in input
-sull'altro e viceversa. I parametri \param{domain}, \param{type} e
-\param{protocol} derivano dall'interfaccia dei socket\index{socket} (che è
-quella che fornisce il substrato per connettere i due descrittori), ma in
-questo caso i soli valori validi che possono essere specificati sono
-rispettivamente \const{AF\_UNIX}, \const{SOCK\_STREAM} e \val{0}.
+sull'altro e viceversa. Gli argomenti \param{domain}, \param{type} e
+\param{protocol} derivano dall'interfaccia dei socket\index{socket} (vedi
+sez.~\ref{sec:sock_creation}) che è quella che fornisce il substrato per
+connettere i due descrittori, ma in questo caso i soli valori validi che
+possono essere specificati sono rispettivamente \const{AF\_UNIX},
+\const{SOCK\_STREAM} e \val{0}.
L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe}
può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei
Usando la stessa chiave due processi diversi possono ricavare l'identificatore
associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è
come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
-sono \textsl{parenti} la soluzione è relativamente semplice, in tal caso
+sono \textsl{imparentati} la soluzione è relativamente semplice, in tal caso
infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un
nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà
-disponibile in tutti i figli, e potrà essere passato come parametro attraverso
+disponibile in tutti i figli, e potrà essere passato come argomento attraverso
una \func{exec}.
-Però quando i processi non sono \textsl{parenti} (come capita tutte le volte
-che si ha a che fare con un sistema client-server) tutto questo non è
+Però quando i processi non sono \textsl{imparentati} (come capita tutte le
+volte che si ha a che fare con un sistema client-server) tutto questo non è
possibile; si potrebbe comunque salvare l'identificatore su un file noto, ma
questo ovviamente comporta lo svantaggio di doverselo andare a rileggere. Una
alternativa più efficace è quella che i programmi usino un valore comune per
\end{figure}
-Una coda di messaggi è costituita da una \textit{linked list};\footnote{una
- \textit{linked list} è una tipica struttura di dati, organizzati in una
- lista in cui ciascun elemento contiene un puntatore al successivo. In questo
- modo la struttura è veloce nell'estrazione ed immissione dei dati dalle
- estremità dalla lista (basta aggiungere un elemento in testa o in coda ed
- aggiornare un puntatore), e relativamente veloce da attraversare in ordine
- sequenziale (seguendo i puntatori), è invece relativamente lenta
- nell'accesso casuale e nella ricerca.} i nuovi messaggi vengono inseriti in
-coda alla lista e vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si
-è riportato lo schema con cui queste strutture vengono mantenute dal
-kernel.\footnote{lo schema illustrato in fig.~\ref{fig:ipc_mq_schema} è in
- realtà una semplificazione di quello usato effettivamente fino ai kernel
- della serie 2.2.x, nei kernel della serie 2.4.x la gestione delle code di
- messaggi è stata modificata ed è effettuata in maniera diversa; abbiamo
- mantenuto lo schema precedente in quanto illustra comunque in maniera più
- che adeguata i principi di funzionamento delle code di messaggi.}
+Una coda di messaggi è costituita da una
+\index{\textit{linked~list}}\textit{linked list};\footnote{una \textit{linked
+ list} è una tipica struttura di dati, organizzati in una lista in cui
+ ciascun elemento contiene un puntatore al successivo. In questo modo la
+ struttura è veloce nell'estrazione ed immissione dei dati dalle estremità
+ dalla lista (basta aggiungere un elemento in testa o in coda ed aggiornare
+ un puntatore), e relativamente veloce da attraversare in ordine sequenziale
+ (seguendo i puntatori), è invece relativamente lenta nell'accesso casuale e
+ nella ricerca.} i nuovi messaggi vengono inseriti in coda alla lista e
+vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si è riportato lo
+schema con cui queste strutture vengono mantenute dal kernel.\footnote{lo
+ schema illustrato in fig.~\ref{fig:ipc_mq_schema} è in realtà una
+ semplificazione di quello usato effettivamente fino ai kernel della serie
+ 2.2.x, nei kernel della serie 2.4.x la gestione delle code di messaggi è
+ stata modificata ed è effettuata in maniera diversa; abbiamo mantenuto lo
+ schema precedente in quanto illustra comunque in maniera più che adeguata i
+ principi di funzionamento delle code di messaggi.}
\begin{figure}[!htb]
\footnotesize \centering
}
\end{functions}
-La funzione può avere tre o quattro parametri, a seconda dell'operazione
+La funzione può avere tre o quattro argomenti, a seconda dell'operazione
specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
\param{semid} o sul singolo semaforo di un insieme, specificato da
\param{semnum}.
fig.~\ref{fig:ipc_semun}.
Come già accennato sia il comportamento della funzione che il numero di
-parametri con cui deve essere invocata, dipendono dal valore dell'argomento
+argomenti con cui deve essere invocata dipendono dal valore dell'argomento
\param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
cioè non causano un errore di \errcode{EINVAL}) per questo argomento sono i
seguenti:
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}
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
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
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
fig.~\ref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
ricordi quanto illustrato al proposito in sez.~\ref{sec:proc_mem_layout}). In
particolare l'indirizzo finale del segmento dati (quello impostato da
-\func{brk}, vedi sez.~\ref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga
-presente infine che la funzione ha successo anche se il segmento è stato
-marcato per la cancellazione.
+\func{brk}, vedi sez.~\ref{sec:proc_mem_sbrk_alloca}) non viene influenzato.
+Si tenga presente infine che la funzione ha successo anche se il segmento è
+stato marcato per la cancellazione.
\begin{figure}[htb]
\centering
\bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
errore, la funzione fallisce solo quando non c'è un segmento agganciato
- all'indirizzo \func{shmaddr}, con \var{errno} che assume il valore
+ all'indirizzo \param{shmaddr}, con \var{errno} che assume il valore
\errval{EINVAL}.}
\end{functions}
riga di comando (che si limitano alla eventuale stampa di un messaggio di
aiuto a video ed all'impostazione della durata dell'intervallo con cui viene
ripetuto il calcolo delle proprietà della directory) controlla (\texttt{\small
- 20--23}) che sia stato specificato il parametro necessario contenente il
-nome della directory da tenere sotto controllo, senza il quale esce
-immediatamente con un messaggio di errore.
+ 20--23}) che sia stato specificato l'argoemnto necessario contenente il nome
+della directory da tenere sotto controllo, senza il quale esce immediatamente
+con un messaggio di errore.
-Poi, per verificare che il parametro specifichi effettivamente una directory,
+Poi, per verificare che l'argomento specifichi effettivamente una directory,
si esegue (\texttt{\small 24--26}) su di esso una \func{chdir}, uscendo
immediatamente in caso di errore. Questa funzione serve anche per impostare
la directory di lavoro del programma nella directory da tenere sotto
Le code di messaggi non sono ancora supportate nel kernel ufficiale, esiste
però una implementazione sperimentale di Michal Wronski e Krzysztof
Benedyczak,\footnote{i patch al kernel e la relativa libreria possono essere
- trovati su \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
- {http://www.mat.uni.torun.pl/\tild{}wrona/posix\_ipc}, questi sono stati
- inseriti nel kernel ufficiale a partire dalla versione 2.6.6-rc1.}. In
+trovati su \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
+{\textsf{http://www.mat.uni.torun.pl/\tild{}wrona/posix\_ipc}}, questi sono
+stati inseriti nel kernel ufficiale a partire dalla versione 2.6.6-rc1.}. In
generale, come le corrispettive del SysV IPC, le code di messaggi sono poco
usate, dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono
più comodi, e che in casi più complessi la comunicazione può essere gestita