From 07d6f8f2907315b4004b4f612110247ba1eabdbc Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Mon, 26 Aug 2002 21:11:49 +0000 Subject: [PATCH] Abbozzo di fortune server con le message queues --- ipc.tex | 141 ++++++++++++++++++++++-------------- sources/MQFortuneServer.c | 147 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 53 deletions(-) create mode 100644 sources/MQFortuneServer.c diff --git a/ipc.tex b/ipc.tex index 0637d47..286cfdd 100644 --- a/ipc.tex +++ b/ipc.tex @@ -124,7 +124,7 @@ consiste nell'inviare l'output di un processo (lo standard output) sull'input di un'altro. Realizzeremo il programma di esempio nella forma di un \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 + all'interno di una pagina HTML.} per Apache, che genera una immagine JPEG di un codice a barre, specificato come parametro di input. Un programma che deve essere eseguito come \textit{CGI} deve rispondere a @@ -558,7 +558,7 @@ leggerli, quando i dati inviati sono destinati a loro. Per risolvere questo problema, si può usare un'architettura come quella illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le richieste al server su una fifo nota mentre le risposte vengono reinviate dal -server a ciascuno di essi su una fifo temporanea creata per l'occazione. +server a ciascuno di essi su una fifo temporanea creata per l'occasione. \begin{figure}[htb] \centering @@ -1229,11 +1229,11 @@ coda. messaggi. \\ \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo messaggio.\\ - \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima di una coda di - messaggi.\\ + \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di + una coda.\\ \hline \end{tabular} - \caption{Valori delle costanti associati ai limiti delle code di messaggi.} + \caption{Valori delle costanti associate ai limiti delle code di messaggi.} \label{tab:ipc_msg_limits} \end{table} @@ -1297,7 +1297,7 @@ 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. In \figref{fig:ipc_msgid_sd} sono elencati i - campi significativi definiti in \file{sys/msg.h}, a cui si sono agguinti gli + campi significativi definiti in \file{sys/msg.h}, a cui si sono aggiunti gli ultimi tre campi che sono previsti dalla implementazione originale di System V, ma non dallo standard Unix98.} mantiene le principali informazioni riguardo lo stato corrente della coda. Quando si crea una nuova coda con @@ -1315,9 +1315,10 @@ invece: rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo messaggio sulla coda, sono inizializzati a 0. \item il campo \var{msg\_ctime} viene inizializzato al tempo corrente. -\item il campo \var{msg\_qbytes} viene inizializzati al limite di sistema. +\item il campo \var{msg\_qbytes} viene inizializzato al valore preimpostato + del sistema (\macro{MSGMNB}). \item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del - primo e ultimo messagio sono inizializzati a \macro{NULL} e + primo e ultimo messaggio sono inizializzati a \macro{NULL} e \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è inizializzato a zero. Questi campi sono ad uso interno dell'implementazione e non devono essere utilizzati da programmi in user space). @@ -1356,7 +1357,7 @@ 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}} +\begin{basedescript}{\desclabelwidth{2.2cm}\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. @@ -1373,9 +1374,8 @@ eseguire; i valori possibili sono: struttura \var{msqid\_ds} puntata da \param{buf}. Per modificare i valori di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre essere il proprietario o il creatore della coda, oppure l'amministratore; lo - stesso vale per \var{msg\_qbytes}, con la restrizione che solo - l'amministratore può incrementarne il valore a limiti superiori a - \macro{MSGMNB}. + stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di + incrementarne il valore a limiti superiori a \macro{MSGMNB}. \end{basedescript} @@ -1413,22 +1413,31 @@ La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso l'argomento \param{msgp}. Quest'ultimo deve venire passato sempre in una forma che corrisponda alla struttura \var{msgbuf} riportata in -\figref{fig:ipc_msbug}. La struttura è solo un modello, la sola cosa che -conta è abbia come primo membro un campo \var{mtype}, come nell'esempio; esso -infatti serve ad identificare il tipo di messaggio e deve essere sempre -specificato come intero positivo. Il campo \var{mtext} invece può essere di -qualsiasi tipo e dimensione, e deve contenere il testo del messaggio. - -In generale pertanto occorrerà ridefinire una struttura analoga a quella di -\figref{fig:ipc_msbug}, adattando alle proprie esigenze il campo \var{mtype}, -e avendo cura di mantenere come primo campo un valore di tipo \ctyp{long}. Il -resto della struttura andrà a costituire il corpo del messaggio, la cui -dimensione deve essere specificata sempre attraverso \param{msgsz}. Si tenga -presente che la lunghezza che deve essere indicata in questo argomento è solo -quella del messaggio, non di tutta la struttura, se cioè \var{message} è la -struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a -\code{sizeof(message)-sizeof(long)} (se consideriamo il caso dell'esempio in -\figref{fig:ipc_msbug} \param{msgsz} dovrà essere pari a \macro{LENGHT}). +\figref{fig:ipc_msbug}. La dimensione massima per il testo di un messaggio +non può comunque superare il limite \macro{MSGMAX}. + +La struttura di \figref{fig:ipc_msbug} comunque è solo un modello, tanto che +la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo +campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici. +La sola cosa che conta è che abbia come primo membro un campo \var{mtype}, +come nell'esempio; esso infatti serve ad identificare il tipo di messaggio e +deve essere sempre specificato come intero positivo. Il campo \var{mtext} +invece può essere di qualsiasi tipo e dimensione, e deve contenere il testo +del messaggio. + +In generale pertanto per inviare un messaggio con \func{msgsnd} si usa +ridefinire una struttura simile a quella di \figref{fig:ipc_msbug}, adattando +alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il +corpo del messaggio, anche con più campi o con strutture più complesse) avendo +però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne +indica il tipo. + +Si tenga presente che la lunghezza che deve essere indicata in questo +argomento è solo quella del messaggio, non quella di tutta la struttura, se +cioè \var{message} è una propria struttura che si passa alla funzione, +\param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se +consideriamo il caso dell'esempio in \figref{fig:ipc_msbug}, \param{msgsz} +dovrà essere pari a \macro{LENGHT}). \begin{figure}[!htb] \footnotesize \centering @@ -1512,46 +1521,51 @@ rimosso dalla stessa) } \end{functions} -La funzione permette di estrarre un messaggio dalla coda e di scriverlo nel -buffer indicato da \param{msgp}, che deve puntare ad una struttura della forma -mostrata in \figref{fig:ipc_msbug}. L'argomento \param{msgsz} indica la -lunghezza massima del testo del messaggio (equivalente al valore del parametro -\macro{LENGHT} nell'esempio di \figref{fig:ipc_msbug}). +La funzione legge un messaggio dalla coda specificata scrivendolo nel buffer +indicato da \param{msgp}, che avrà un formato analogo a quello di +\figref{fig:ipc_msbug}. L'argomento \param{msgsz} indica la lunghezza massima +del testo del messaggio (equivalente al valore del parametro \macro{LENGHT} +nell'esempio di \figref{fig:ipc_msbug}). Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene -rimosso dalla coda, in caso contrario se \param{msgflg} è impostato a -\macro{MSG\_NOERROR} il messaggio viene troncato e la parte in eccesso viene +rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a +\macro{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con un errore di \macro{E2BIG}. L'argomento \param{msgtyp} permette di restringere la ricerca ad un -sottoinsieme dei messaggi presenti sulla coda; in particolare: +sottoinsieme dei messaggi presenti sulla coda; la ricerca infatti è fatta con +una scansione della struttura mostrata in \figref{fig:ipc_mq_schema}, +restituendo il primo messaggio incontrato che corrisponde ai criteri +specificati (che quindi, visto che i messaggi vengono sempre inseriti dalla +coda, è quello meno recente); in particolare: \begin{itemize} \item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè quello fra i presenti che è stato inserito inserito per primo. \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui - tipo (il valore del campo \var{mtype}) corrisponde a quanto specificato. -\item se \param{msgtyp} è negativo viene estratto il primo messaggio nella coda - con il tipo più basso, fra quelli di tipo inferiore al valore assoluto di - quanto specificato. + tipo (il valore del campo \var{mtype}) corrisponde al valore di + \param{msgtyp}. +\item se \param{msgtyp} è negativo viene estratto il primo fra i messaggi con + il tipo di valore più basso, fra tutti quelli con un tipo inferiore al + valore assoluto di \param{msgtyp}. \end{itemize} Il valore di \param{msgflg} permette di controllare il comportamento della -funzione, esso può assumere valore nullo o essere specificato come maschera -binaria di uno o più dei valori. Oltre al precedente \macro{MSG\_NOERROR}, si -può impostare il valore \macro{MSG\_EXCEPT}, che quando \param{msgtyp} è -positivo permette di leggere il primo messaggio nella coda con tipo diverso da -\param{msgtyp}, ed il valore \macro{IPC\_NOWAIT} che causa il ritorno -immediato della funzione quando non ci sono messaggi sulla coda. - -Il comportamento usuale della funzione infatti, quando non ci sono messaggi +funzione, esso può essere nullo o una maschera binaria composta da uno o più +valori. Oltre al precedente \macro{MSG\_NOERROR}, sono possibili altri due +valori: \macro{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo, +di leggere il primo messaggio nella coda con tipo diverso da \param{msgtyp}, e +\macro{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non +ci sono messaggi sulla coda. + +Il comportamento usuale della funzione infatti, se non ci sono messaggi disponibili per la lettura, è di bloccare il processo in stato di -\textit{sleep}; nel caso però si sia specificato \macro{IPC\_NOWAIT} la +\textit{sleep}. Nel caso però si sia specificato \macro{IPC\_NOWAIT} la funzione ritorna immediatamente con un errore \macro{ENOMSG}. Altrimenti la funzione ritorna normalmente non appena viene inserito un messaggio del tipo -desiderato, oppure ritorna con errore qualora la cosa sia rimossa (con un -\macro{EIDRM}) o se il processo viene interrotto da un segnale (con un -\macro{EINTR}). +desiderato, oppure ritorna con errore qualora la coda sia rimossa (con +\var{errno} settata a \macro{EIDRM}) o se il processo viene interrotto da un +segnale (con \var{errno} settata a \macro{EINTR}). Una volta completata con successo l'estrazione del messaggio dalla coda, la funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono @@ -1563,6 +1577,10 @@ modificati: \item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente. \end{itemize} +Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro +server di \textit{fortunes} usando queste al posto delle fifo. In questo caso +useremo una coda di messaggi, usando il \acr{pid} del client come valore per +il tipo di messaggio, per restituire indietro le frasi ai client. @@ -1621,7 +1639,6 @@ struct semid_ds time_t sem_ctime; /* last time changed by semctl() */ unsigned long int sem_nsems; /* number of semaphores in set */ }; - \end{lstlisting} \end{minipage} \normalsize @@ -1630,6 +1647,24 @@ struct semid_ds \label{fig:ipc_semid_sd} \end{figure} +\begin{table}[htb] + \footnotesize + \centering + \begin{tabular}[c]{|c|r|l|l|} + \hline + \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \macro{SEMMNI}& 16& Numero massimo di insiemi di semafori. \\ + \macro{SEMMAX}& 8192& .\\ + \macro{SEMMNB}&16384& .\\ + \hline + \end{tabular} + \caption{Valori delle costanti associate ai limiti degli insiemi di + semafori.} + \label{tab:ipc_sem_limits} +\end{table} + \subsection{Memoria condivisa} \label{sec:ipc_sysv_shm} diff --git a/sources/MQFortuneServer.c b/sources/MQFortuneServer.c new file mode 100644 index 0000000..e131978 --- /dev/null +++ b/sources/MQFortuneServer.c @@ -0,0 +1,147 @@ +/* MQFortuneServer.c + * + * Copyright (C) 2002 Simone Piccardi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/**************************************************************** + * + * Program fortuned + * Fortune server - Using Messag queues + * + * Author: Simone Piccardi + * Aug. 2002 + * + * Usage: fortuned -h give all info + * + * $Id: MQFortuneServer.c,v 1.1 2002/08/26 21:11:49 piccardi Exp $ + * + ****************************************************************/ +/* + * Include needed headers + */ +#include /* predefined types */ +#include /* */ +#include /* include unix standard library */ +#include /* include standard I/O library */ +#include /* standard library */ +#include /* ANSI C standard string */ +#include /* errorstring */ +#include /* signals */ +#include /* */ + +#include "macros.h" +#include "wrappers.h" + +/* Subroutines declaration */ +void usage(void); +void HandSIGTERM(int signo); +int FortuneParse(char *file, char **fortune, int n); + +/* name of well known fifo */ +int main(int argc, char *argv[]) +{ +/* Variables definition */ + int i, n = 0; + char **fortune; + struct msgbuf_read { + long mtype; /* message type, must be > 0 */ + int pid; /* message data */ + } msg_read; + struct msgbuf_write { + long mtype; /* message type, must be > 0 */ + char mtext[MSGMAX]; /* message data */ + } msg_write; + int msgid; + key_t key; + int size; + /* + * Input section: decode parameters passed in the calling + * Use getopt function + */ + opterr = 0; /* don't want writing to stderr */ + while ( (i = getopt(argc, argv, "hn:f:")) != -1) { + switch (i) { + /* + * Handling options + */ + case 'h': + printf("Wrong -h option use\n"); + usage(); + return(0); + break; + case 'f': + fortunefilename = optarg; + break; + case 'n': + n = strtol(optarg, NULL, 10); + fortune = (char **) calloc(sizeof(*fortune), n); + break; + case '?': /* unrecognized options */ + printf("Unrecognized options -%c\n",optopt); + usage(); + default: /* should not reached */ + usage(); + } + } + /* *********************************************************** + * + * Options processing completed + * + * Main code beginning + * + * ***********************************************************/ + if (n==0) usage(); /* if no pool depth exit printing usage info */ + Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ + Signal(SIGINT, HandSIGTERM); + Signal(SIGQUIT, HandSIGTERM); + i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */ + for (n=0; n