\macro{ENFILE} e \macro{EFAULT}.}
\end{prototype}
-La funzione restituisce la coppia di file descriptor nell'array
+La funzione restituisce la coppia di file descriptor nel vettore
\param{filedes}; il primo è aperto in lettura ed il secondo in scrittura. Come
accennato concetto di funzionamento di una pipe è semplice: quello che si
scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
Questo approccio però non funziona, per via di una delle caratteristiche
principali delle pipe. Per poter effettuare la conversione di un PDF infatti è
necessario, per la struttura del formato, potersi spostare (con \func{lseek})
-all'interno del file da convertire; se si eseguela conversione con \cmd{gs} su
+all'interno del file da convertire; se si esegue la conversione con \cmd{gs} su
un file regolare non ci sono problemi, una pipe però è rigidamente
sequenziale, e l'uso di \func{lseek} su di essa fallisce sempre con un errore
di \macro{ESPIPE}, rendendo impossibile la conversione. Questo ci dice che in
comunque una fifo in scrittura anche se non ci sono ancora processi il
lettura; è possibile anche usare la fifo all'interno di un solo processo, nel
qual caso però occorre stare molto attenti alla possibili
-deadlock.\footnote{se si cerca di leggere da una fifo che non contiene dati si
+situazioni di stallo.\footnote{se si cerca di leggere da una fifo che non contiene dati si
avrà un deadlock immediato, dato che il processo si blocca e non potrà
quindi mai eseguire le funzioni di scrittura.}
lettura in attesa di una richiesta.} si esegue una seconda apertura in
scrittura (\texttt{\small 29--32}), scartando il relativo file descriptor che
non sarà mai usato, ma lasciando la fifo comunque aperta anche in scrittura,
-cosicchè le successive possano bloccarsi.
+cosicché le successive possano bloccarsi.
A questo punto si può entrare nel ciclo principale del programma che fornisce
le risposte ai client (\texttt{\small 34--50}), che viene eseguito
richiesta dalla fifo nota (che a questo punto si bloccherà tutte le volte che
non ci sono richieste). Dopo di che, una volta terminata la stringa
(\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per
-ricavare la frase da invaire, si procederà (\texttt{\small 42--46})
+ricavare la frase da inviare, si procederà (\texttt{\small 42--46})
all'apertura della fifo per la risposta, che \texttt{\small 47--48}) poi vi
sarà scritta. Infine (\texttt{\small 49}) si chiude la fifo di risposta che
non serve più.
(\texttt{\small 13-18}) si procede alla creazione del relativo file, uscendo
in caso di errore (a meno che il file non sia già presente sul filesystem).
-A questo punto il client può effettuare l'interrogazione del server, pe questo
-prima si apre la fifo nota (\texttt{\small 19--23}), e poi ci si scrive
+A questo punto il client può effettuare l'interrogazione del server, per
+questo prima si apre la fifo nota (\texttt{\small 19--23}), e poi ci si scrive
(\texttt{\small 24}) la stringa composta in precedenza, che contiene il nome
della fifo da utilizzare per la risposta. Infine si richiude la fifo del
server che a questo punto non serve più (\texttt{\small 25}).
Gli oggetti usati nel System V IPC vengono creati direttamente dal kernel, e
sono accessibili solo specificando il relativo \textsl{identificatore}. Questo
è un numero progressivo (un po' come il \acr{pid} dei processi) che il kernel
-assegna a ciascuno di essi quanto vengono creati (sul prodedimento di
+assegna a ciascuno di essi quanto vengono creati (sul procedimento di
assegnazione torneremo in \secref{sec:ipc_sysv_id_use}). L'identificatore
viene restituito dalle funzioni che creano l'oggetto, ed è quindi locale al
processo che le ha eseguite. Dato che l'identificatore viene assegnato
come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
sono \textsl{parenti} 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'idenficatore così ottenuto sarà
+nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà
disponibile in tutti i figli, e potrà essere passato come parametro 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 è
-possibile; si potebbe comunque salvare l'identificatore su un file noto, ma
+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
la chiave (che ad esempio può essere dichiarato in un header comune), ma c'è
sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
con i 16 bit meno significativi dell'inode del file \param{pathname} (che
vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori),
-e gli 8 bit meno significativi del numero del device su cui è il file. Diventa
-perciò relativamente facile ottenere delle collisioni, specie se i file sono
-su dispositivi con lo stesso \textit{minor number}, come \file{/dev/hda1} e
-\file{/dev/sda1}.
+e gli 8 bit meno significativi del numero del dispositivo su cui è il file.
+Diventa perciò relativamente facile ottenere delle collisioni, specie se i
+file sono su dispositivi con lo stesso \textit{minor number}, come
+\file{/dev/hda1} e \file{/dev/sda1}.
In genere quello che si fa è utilizzare un file comune usato dai programmi che
devono comunicare (ad esempio un haeder comune, o uno dei programmi che devono
-usare l'oggetto in questione), utilizzando il numero di progetto per ottere le
-chiavi che interessano. In ogni caso occorre sempre controllare, prima di
+usare l'oggetto in questione), utilizzando il numero di progetto per ottenere
+le chiavi che interessano. In ogni caso occorre sempre controllare, prima di
creare un oggetto, che la chiave non sia già stata utilizzata. Se questo va
bene in fase di creazione, le cose possono complicarsi per i programmi che
devono solo accedere, in quanto, a parte gli eventuali controlli sugli altri
direttamente (in lettura o scrittura) all'oggetto. In tal caso lo schema dei
controlli è simile a quello dei file, ed avviene secondo questa sequenza:
\begin{itemize}
-\item se il processo ha i privilegi di amministatore l'accesso è sempre
+\item se il processo ha i privilegi di amministratore l'accesso è sempre
consentito.
\item se l'userid effettivo del processo corrisponde o al valore del campo
\var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario
Quando il sistema si avvia, alla creazione di ogni nuovo oggetto di IPC viene
assegnato un numero progressivo, pari al numero di oggetti di quel tipo
-esistenti. Se il comportamente fosse sempre questo sarebbe identico a quello
+esistenti. Se il comportamento fosse sempre questo sarebbe identico a quello
usato nell'assegnazione dei file descriptor nei processi, ed i valori degli
identificatori tenderebbero ad essere riutilizzati spesso e restare di piccole
-dimensioni (inferiori al numero massimo di oggetti diponibili).
+dimensioni (inferiori al numero massimo di oggetti disponibili).
Questo va benissimo nel caso dei file descriptor, che sono locali ad un
processo, ma qui il comportamento varrebbe per tutto il sistema, e per
in caso di errore, nel qual caso \var{errno} viene settato ad uno dei
valori:
\begin{errlist}
- \item[\macro{EACCES}] Il processo chiamante non ha i provilegi per accedere
+ \item[\macro{EACCES}] Il processo chiamante non ha i privilegi per accedere
alla coda richiesta.
\item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}.
Si tenga conto che l'uso di \macro{IPC\_PRIVATE} non impedisce ad altri
processi di accedere alla coda (se hanno privilegi sufficienti) una volta che
-questi possano indovinare o ricavare l'identificatore ad essa associato. Per
-la loro implementazione non esiste cioè una maniera che garantisca l'accesso
-esclusivo ad una coda di messaggi. Usare \macro{IPC\_PRIVATE} o
-macro{IPC\_CREAT} e \macro{IPC\_EXCL} per \param{flag} comporta solo la
-creazione di una nuova coda.
-
-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.} in cui nuovi messaggi vengono
-inseriti in coda per poi essere letti dalla cima, con una struttura del tipo
-di quella illustrata in \secref{fig:ipc_mq_schema}.\footnote{la struttura è
- effettivamente in uso fino ai kernel della serie 2.2.x. Viene mantenuta nei
- kernel della serie 2.4.x, dove la gestione è effettuata con strutture
- diverse, solo per compatibilità; essa comunque è quella restituita dalle
- funzioni dell'interfaccia ed illustra in maniera adeguata i principi di
- funzionamento delle code di messaggi.}
-
-\begin{figure}[htb]
- \centering
- \includegraphics[width=15cm]{img/mqstruct}
- \caption{Schema della struttura di una coda messaggi.}
- \label{fig:ipc_mq_schema}
-\end{figure}
-
-Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
-negli header e corrispondenti alle prime tre costanti riportate in , come
-accennato però in Linux è possibile modificare questi limiti attraverso l'uso
-di \func{syscntl} o scrivendo nei file \file{msgmax}, \file{msgmnb} e
-\file{msgmni} di \file{/proc/sys/kernel/}.
-
+questi possano indovinare o ricavare (ad esempio per tentativi)
+l'identificatore ad essa associato. Per come sono implementati gli oggetti di
+IPC infatti non esiste una maniera che garantisca l'accesso esclusivo ad una
+coda di messaggi. Usare \macro{IPC\_PRIVATE} o macro{IPC\_CREAT} e
+\macro{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
+coda.
\begin{table}[htb]
+ \footnotesize
\centering
- \begin{tabular}[c]{|c|c|l|l}
+ \begin{tabular}[c]{|c|r|l|l|}
\hline
\textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
& \textbf{Significato} \\
\label{tab:ipc_msg_limits}
\end{table}
-Una volta creata una coda di messaggi se ne può controllare
+Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
+negli header e corrispondenti alle prime tre costanti riportate in
+\tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
+modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}.
+
+
+\begin{figure}[htb]
+ \centering \includegraphics[width=15cm]{img/mqstruct}
+ \caption{Schema della struttura di una coda messaggi.}
+ \label{fig:ipc_mq_schema}
+\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 \figref{fig:ipc_mq_schema} si è
+riportato lo schema con cui queste strutture vengono mantenute dal
+kernel.\footnote{lo schema illustrato in figura è in realtà una semplificazione
+ di quanto usato fino ai kernel della serie 2.2.x, nei kernel della serie
+ 2.4.x la gestione è effettuata in maniera diversa; ma esso illustra comunque
+ in maniera adeguata i principi di funzionamento delle code di messaggi.}
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}
+struct msqid_ds {
+ struct ipc_perm msg_perm; /* structure for operation permission */
+ time_t msg_stime; /* time of last msgsnd command */
+ time_t msg_rtime; /* time of last msgrcv command */
+ time_t msg_ctime; /* time of last change */
+ unsigned long int msg_cbytes; /* current number of bytes on queue */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ pid_t msg_lspid; /* pid of last msgsnd() */
+ pid_t msg_lrpid; /* pid of last msgrcv() */
+ struct msg *msg_first; /* first message on queue, unused */
+ struct msg *msg_last; /* last message in queue, unused */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
+ messaggi. Si sono riportati i campi significativi definiti in
+ \file{sys/msg.h}, aggiungendo anche due campi interni, non visibili in
+ user space.}
+ \label{fig:ipc_msgid_sd}
+\end{figure}
+
+A ciascuna coda è associata una struttura \var{msgid\_ds}, la cui definizione
+è riportata in \secref{fig:ipc_msgid_sd}, il significato dei vari campi è
+riportato nella figura. In questa struttura il kernel\footnote{come accennato
+ questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel
+ della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle
+ funzioni dell'interfaccia.} mantiene le principali informazioni riguardo lo
+stato corrente della coda. Quando si crea una nuova coda con \func{msgget}
+questa struttura viene inizializzata, in particolare il campo \var{msg\_perm}
+viene inizializzato come illustrato in \secref{sec:ipc_sysv_access_control},
+per quanto riguarda gli altri campi invece:
+\begin{itemize}
+\item i campi \var{msg\_qnum}, \var{msg\_lspid}, \var{msg\_lrpid},
+ \var{msg\_stime}, \var{msg\_rtime} sono inizializzati a 0
+\item il campo \var{msg\_ctime} viene settato al tempo corrente
+\item il campo \var{msg\_qbytes} al limite di sistema.
+\item i campi \var{msg\_first} e \var{msg\_last} (che non vengono visti in
+ user space) sono inizializzati a \macro{NULL} essendo la coda vuota.
+\end{itemize}
+
+Una volta creata una coda di messaggi le operazioni di controllo vengono
+effettuate con la funzione \func{msgctl}, che (come le analoghe \func{semctl}
+e \func{shmctl}) fa le veci di quello che \func{ioctl} è per i file; il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgctl(int msqid, int cmd, struct msqid\_ds *buf)}
+
+ Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+ errore, nel qual caso \var{errno} viene settato a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
+ non ha i privilegi di lettura sulla coda.
+ \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+ \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+ il processo non ha i privilegi, o si è richiesto di aumentare il valore di
+ \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
+ amministratore.
+ \end{errlist}
+ ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+La funzione permette di accedere ai valori della struttura \var{msqid\_ds},
+mantenuta all'indirizzo \param{buf}, per la coda specificata
+dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
+valore dell'argomento \param{cmd}, che specifica il tipo di azione da
+eseguire; i valori possibili sono:
+\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+ struttura indicata da \param{buf}. Occorre avere il permesso di lettura
+ sulla coda.
+\item[\macro{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
+ effetto immediato. Tutti i processi che cercheranno di accedere alla coda
+ riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su
+ funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
+ il medesimo errore. Questo comando può essere eseguito solo da un processo
+ con userid effettivo corrispondente al creatore a o al proprietario della
+ coda, o all'amministratore.
+\item[\macro{IPC\_SET}]
+\end{basedescript}
\subsection{Semafori}
La funzione è del tutto analoga a \func{msgget} ed identico è l'uso degli
argomenti \param{key} e \param{flag}, per cui non ripeteremo quanto detto al
proposito in \secref{sec:ipc_sysv_mq}. L'argomento \param{nsems} permette di
-specificare quanti semfori deve contenere l'insieme qualora se ne richieda la
+specificare quanti semafori deve contenere l'insieme qualora se ne richieda la
creazione, e deve essere nullo quando si effettua una richiesta
dell'identificatore di un insieme già esistente.