From: Simone Piccardi Date: Thu, 24 Oct 2002 17:34:16 +0000 (+0000) Subject: Corrette speigazione sul server con le message queue X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=ab0e3c2c239f3342d1e7bf0519f1831bbd4fa88b;p=gapil.git Corrette speigazione sul server con le message queue --- diff --git a/ipc.tex b/ipc.tex index 7cc86fa..a17bf4a 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1718,55 +1718,58 @@ void HandSIGTERM(int signo) { In \figref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti primcipali del codice del nuovo server (il codice completo è nel file \file{MQFortuneServer.c} nei sorgenti allegati). Il programma è basato su un -uso accorto dei tipi di messaggi per permettere una comunicazione indipendente -fra il server ed i vari client, usando il \acr{pid} di questi ultimi come -identificativo. Questo è possibile in quanto, al contrario di una fifo, la -lettura di una coda di messaggi può non essere sequanziale, proprio grazie -alla classificazione dei messaggi sulla base del loro tipo. - - -Oltre alle solite variabili per il nome del file delle fifo e per il vettore -di stringhe che contiene le frasi, il programma utilizza due strutture per la -comunicazione; con \var{msgbuf\_read} (\texttt{\small 8--11}) vengono passate -le richieste mentre con \var{msgbuf\_write} (\texttt{\small 12--15}) vengono -restituite le frasi. - -La gestione delle opzioni si è al solito omessa, essa si curerà di restituire -in \var{n} il numero di file da leggere ed in \var{fortunefilename} il file da -cui leggerle; dopo aver installato (\texttt{\small 19--21}) dei manipolatori -per gestire l'uscita prima viene controllato (\texttt{\small 22}) che si siano -richiesti un numero positivo di messaggi, che poi (\texttt{\small 23}) vengono -letti con la stessa funzione \code{FortuneParse()} usata anche per il server -basato sulle fifo. +uso accorto della caratteristica di poter associate un ``tipo'' ai messaggi +per permettere una comunicazione indipendente fra il server ed i vari client, +usando il \acr{pid} di questi ultimi come identificativo. Questo è possibile +in quanto, al contrario di una fifo, la lettura di una coda di messaggi può +non essere sequanziale, proprio grazie alla classificazione dei messaggi sulla +base del loro tipo. + +Il programma, oltre alle solite variabili per il nome del file da cui leggere +le \textit{fortunes} e per il vettore di stringhe che contiene le frasi, +definisce due strutture appositamente per la comunicazione; con +\var{msgbuf\_read} (\texttt{\small 8--11}) vengono passate le richieste mentre +con \var{msgbuf\_write} (\texttt{\small 12--15}) vengono restituite le frasi. + +La gestione delle opzioni si è al solito omessa, essa si curerà di impostare +in \var{n} il numero di frasi da leggere specificato a linea di comando ed in +\var{fortunefilename} il file da cui leggerle; dopo aver installato +(\texttt{\small 19--21}) dei manipolatori per gestire l'uscita dal server, +viene prima controllato (\texttt{\small 22}) il numero di frasi richieste +abbia senso (cioè sia maggiore di zero), le quali poi (\texttt{\small 23}) +vengono lette nel vettore in memoria con la stessa funzione +\code{FortuneParse()} usata anche per il server basato sulle fifo. Una volta inizializzato il vettore di stringhe coi messaggi presi dal file -delle fortunes si procede (\texttt{\small 25}) con la generazione di una -chiave (si usa il nome del file dei sorgenti del server) con la quale poi si -esegue (\texttt{\small 26}) la creazione della nostra coda di messaggi (si -noti come si sia chiamata \func{msgget} con un valore opportuno per il flag), -avendo cura di abortire il programma (\texttt{\small 27--29}) in caso di -errore. +delle \textit{fortune} si procede (\texttt{\small 25}) con la generazione di +una chiave per identificare la coda di messaggi (si usa il nome del file dei +sorgenti del server) con la quale poi si esegue (\texttt{\small 26}) la +creazione della stessa (si noti come si sia chiamata \func{msgget} con un +valore opportuno per l'argomento \param{flag}), avendo cura di abortire il +programma (\texttt{\small 27--29}) in caso di errore. Finita la fase di inizializzazione il server esegue in permanenza il ciclo principale (\texttt{\small 32--41}). Questo inizia (\texttt{\small 33}) con il porsi in attesa di un messaggio di richiesta da parte di un client; si noti -infatti come \func{msgrcv} richieda un messaggio con \var{mtype} uguale a 1, -che è il valore usato per le richieste dato che corriponde al \acr{pid} di +infatti come \func{msgrcv} richieda un messaggio con \var{mtype} uguale a 1: +questo è il valore usato per le richieste dato che corriponde al \acr{pid} di \cmd{init}, che non può essere un client. L'uso del flag \macro{MSG\_NOERROR} è solo per sicurezza, dato che i messaggi di richiesta sono di dimensione -fissa. +fissa (e contengono solo il \acr{pid} del client). -Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà; -all'arrivo sulla coda di un messaggio di richiesta da parte di un client la -funzione ritorna, ed il ciclo prosegue (\texttt{\small 34}) selezionando una -frase a caso, copiandola (\texttt{\small 35}) nella struttura -\var{msgbuf\_write} usata per la risposta e calcolandone (\texttt{\small 36}) -la dimensione. +Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà, +ritornando soltanto in corrispondenza dell'arrivo sulla coda di un messaggio +di richiesta da parte di un client, in tal caso il ciclo prosegue +(\texttt{\small 34}) selezionando una frase a caso, copiandola (\texttt{\small + 35}) nella struttura \var{msgbuf\_write} usata per la risposta e +calcolandone (\texttt{\small 36}) la dimensione. Per poter permettere a ciascun client di ricevere solo la risposta indirizzata a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 37}) -al valore ricevuto nel messaggio di richiesta. L'ultimo passo del ciclo -(\texttt{\small 38}) è inviare sulla coda il messaggio di risposta. +al valore del \acr{pid} del client ricevuto nel messaggio di richiesta. +L'ultimo passo del ciclo (\texttt{\small 38}) è inviare sulla coda il +messaggio di risposta. Si tenga conto che se la coda è piena anche questa +funzione potrà bloccarsi fintanto che non venga liberato dello spazio. Si noti che il programma può terminare solo grazie ad una interruzione da parte di un segnale; in tal caso verrà eseguito il manipolatore @@ -1803,27 +1806,44 @@ int main(int argc, char *argv[]) \end{figure} In \figref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice del -programma client, al solito il codice completo è con i sorgenti allegati, nel +programma client. Al solito il codice completo è con i sorgenti allegati, nel file \file{MQFortuneClient.c}. Come sempre si sono rimosse le parti relative alla gestione delle opzioni, ed in questo caso, anche la dichiarazione delle -variabili. +variabili, che, per la parte relative alle strutture usate per la +comunicazione tramite le code, sono le stesse viste in +\figref{fig:ipc_mq_fortune_server}. Il client in questo caso è molto semplice; la prima parte del programma (\texttt{\small 4--9}) si occupa di accedere alla coda di messaggi, ed è identica a quanto visto per il server, solo che in questo caso \func{msgget} non viene chiamata con il flag di creazione in quanto la coda deve essere -preesistente. +preesistente. In caso di errore (ad esempio se il server non è stato avviato) +il programma termina immediatamente. Una volta acquistito l'identificatore della coda il client compone il messaggio di richiesta (\texttt{\small 12--13}) in \var{msg\_read}, usando 1 per il tipo ed inserendo il proprio \acr{pid} come dato da passare al server. Calcolata (\texttt{\small 14}) la dimensione, provvede (\texttt{\small 15}) ad -immettere la richiesta sulla coda. A questo punto non resta che -(\texttt{\small 16}) rileggere dalla coda la risposta del server richiedendo a -\func{msgrcv} di selezionare i messaggi di tipo corrispondente al valore del -\acr{pid} inviato nella richiesta. L'ultimo passo (\texttt{\small 17}) prima -di uscire è quello di stampare a video il messaggio ricevuto. +immettere la richiesta sulla coda. + +A questo punto non resta che (\texttt{\small 16}) rileggere dalla coda la +risposta del server richiedendo a \func{msgrcv} di selezionare i messaggi di +tipo corrispondente al valore del \acr{pid} inviato nella richiesta. L'ultimo +passo (\texttt{\small 17}) prima di uscire è quello di stampare a video il +messaggio ricevuto. +Benché funzionante questa archietettura risente dello stesso inconveniente +visto anche nel caso del precedente server basato sulle fifo; se il client +viene interrotto dopo l'invio del messaggio di richiesta e prima della lettura +della risposta, quest'ultima resta nella coda (così come per le fifo si aveva +il problema delle fifo che restavano nel filesystem). In questo caso però il +problemi sono maggiori, sia perché è molto più facile esaurire la memoria +dedicata ad una coda di messaggi che gli inode di un filesystem, sia perché, +con il riutilizzo dei \acr{pid} da parte dei processi, un client eseguito in +un momento successivo potrebbe ricevere un messaggio non indirizzato a +lui. + + \subsection{Semafori} \label{sec:ipc_sysv_sem}