From 7463fc5258c5afb139286c2509f5161bc0d76290 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 18 Aug 2002 14:38:04 +0000 Subject: [PATCH] Corretta cattiva riallocazione su linee multiple, iniziato a inserire l'esempio. --- ipc.tex | 121 ++++++++++++++++++++++++++++++++-------- sources/FortuneParse.c | 18 +++--- sources/FortuneServer.c | 40 +++++++------ sources/Makefile | 10 ++-- 4 files changed, 135 insertions(+), 54 deletions(-) diff --git a/ipc.tex b/ipc.tex index ed2d492..37d55d5 100644 --- a/ipc.tex +++ b/ipc.tex @@ -556,20 +556,96 @@ struttura sequenziale delle fifo, i client dovrebbero sapere, prima di leggerli, quando i dati inviati sono destinati a loro. Per risolvere questo problema, si può usare un'architettura come quella -illustrata da Stevens in \cite{APUE}, in cui le risposte vengono inviate su -fifo temporanee identificate dal \acr{pid} dei client, ma in ogni caso il -sistema è macchinoso e continua ad avere vari inconvenienti\footnote{lo stesso - Stevens nota come sia impossibile per il server sapere se un client è andato - in crash, con la possibilità di far restare le fifo temporanee sul - filesystem, come sia necessario intercettare \macro{SIGPIPE} dato che un - client può terminare dopo aver fatto una richiesta, ma prima che la risposta - sia inviata, e come occorra gestire il caso in cui non ci sono client attivi - (e la lettura dalla fifo nota restituisca al serve un end-of-file.}; in -generale infatti l'interfaccia delle fifo non è adatta a risolvere questo tipo -di problemi, che possono essere affrontati in maniera più semplice ed efficace -o usando i \textit{socket}\index{socket} (che tratteremo in dettaglio a -partire da \capref{cha:socket_intro}) o ricorrendo a meccanismi di -comunicazione diversi, come quelli che esamineremo in seguito. +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. + +\begin{figure}[htb] + \centering + \includegraphics[height=9cm]{img/fifoserver} + \caption{Schema dell'utilizzo delle fifo nella realizzazione di una + architettura di comunicazione client/server.} + \label{fig:ipc_fifo_server_arch} +\end{figure} + +Come esempio di uso questa architettura e dell'uso delle fifo, abbiamo scritto +un server di \textit{fortunes}, che restituisce, alle richieste di un client, +un detto a caso estratto da un insieme di frasi; sia il numero delle frasi +dell'insieme, che i file da cui esse vengono lette all'avvio, sono importabili +da riga di comando. Il corpo principale del server è riportato in +\figref{fig:ipc_fifo_server}, dove si è tralasciata la parte che tratta la +gestione delle opzioni a riga di comando, che effettua il settaggio delle +variabili \var{fortunefilename}, che indica il file da cui leggere le frasi, +ed \var{n}, che indica il numero di frasi tenute in memoria, ad un valore +diverso da quelli preimpostati. Il codice completo è nel file +\file{FortuneServer.c}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}{} +int main(int argc, char *argv[]) +{ + int i, n = 10; + char *fortunefilename = "/usr/share/games/fortunes/kids"; + char *fifoname = "/tmp/fortune.fifo"; + char **fortune; + char line[80]; + int fifo_server, fifo_client; + int nread; + ... + if (n==0) usage(); /* if no pool depth exit printing usage info */ + i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */ + /* + * Comunication section + */ + if (mkfifo(fifoname, 0622)) { /* create well known fifo if does't exist */ + if (errno!=EEXIST) { + perror("Cannot create well known fifo"); + exit(-1); + } + } + while (1) { + fifo_server = open(fifoname, O_RDONLY); /* open well known fifo */ + if (fifo_server < 0) { + perror("Cannot open well known fifo"); + exit(-1); + } + nread = read(fifo_server, line, 79); /* read request */ + line[nread] = 0; + n = random() % i; /* select random value */ + fifo_client = open(line, O_WRONLY); /* open client fifo */ + nread = write(fifo_client, /* write phrase */ + fortune[n], strlen(fortune[n])+1); + close(fifo_client); /* close well known fifo */ + close(fifo_server); /* close client fifo */ + } +} + \end{lstlisting} + \end{minipage} + \normalsize + \caption{Sezione principale del codice del server di \textit{fortunes} + basato sulle fifo.} + \label{fig:ipc_fifo_server} +\end{figure} + + + + +Benché il nostro sistema client-server funzioni, la sua struttura è piuttosto +complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens, + che esamina questa architettura in \cite{APUE}, nota come sia impossibile + per il server sapere se un client è andato in crash, con la possibilità di + far restare le fifo temporanee sul filesystem, come sia necessario + intercettare \macro{SIGPIPE} dato che un client può terminare dopo aver + fatto una richiesta, ma prima che la risposta sia inviata, e come occorra + gestire il caso in cui non ci sono client attivi (e la lettura dalla fifo + nota restituisca al serve un end-of-file.}; in generale infatti +l'interfaccia delle fifo non è adatta a risolvere questo tipo di problemi, che +possono essere affrontati in maniera più semplice ed efficace o usando i +\textit{socket}\index{socket} (che tratteremo in dettaglio a partire da +\capref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione diversi, +come quelli che esamineremo in seguito. @@ -813,13 +889,14 @@ assumere tutti i valori possibili, rendendo molto pi un identificatore può venire riutilizzato. Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino - al kernel 2.2.x questo numero, ed altri limiti relativi al \textit{System V - IPC}, potevano essere cambiati solo con una ricompilazione del kernel, - andando a modificare le costanti definite nei relativi haeder file. A - partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo - scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di - \file{/proc/sys/kernel} o con \texttt{syscntl}.} e per ciascuno di essi -viene mantenuto in \var{seq} un numero di sequenza progressivo che viene + al kernel 2.2.x questi valori, definiti dalle costanti \macro{MSGMNI}, + \macro{SEMMNI} e \macro{SHMMNI}, potevano essere cambiati (come tutti gli + altri limiti relativi al \textit{System V IPC}) solo con una ricompilazione + del kernel, andando a modificarne la definizione nei relativi haeder file. + A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema + attivo scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di + \file{/proc/sys/kernel} o con l'uso di \texttt{syscntl}.} e per ciascuno di +essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene incrementato di uno ogni volta che l'oggetto viene cancellato. Quando l'oggetto viene creato usando uno spazio che era già stato utilizzato in precedenza per restituire l'identificatore al numero di oggetti presenti viene @@ -827,7 +904,7 @@ sommato il valore di \var{seq} moltiplicato per il numero massimo di oggetti di quel tipo,\footnote{questo vale fino ai kernel della serie 2.2.x, dalla serie 2.4.x viene usato lo stesso fattore per tutti gli oggetti, esso è dato dalla costante \macro{IPCMNI}, definita in \file{include/linux/ipc.h}, che - indica il limite massimo per il numero di oggetti di IPC, il cui valore è + indica il limite massimo per il numero di oggetti di IPC, ed il cui valore è 32768.} si evita così il riutilizzo degli stessi numeri, e si fa sì che l'identificatore assuma tutti i valori possibili. diff --git a/sources/FortuneParse.c b/sources/FortuneParse.c index 962ffc5..24dabd1 100644 --- a/sources/FortuneParse.c +++ b/sources/FortuneParse.c @@ -28,7 +28,7 @@ * Read n fortunes from fortune file file, and put it into the * string array fortune * - * $Id: FortuneParse.c,v 1.1 2002/08/18 10:34:10 piccardi Exp $ + * $Id: FortuneParse.c,v 1.2 2002/08/18 14:38:04 piccardi Exp $ * ****************************************************************/ /* @@ -43,6 +43,8 @@ #include /* error definitions */ #include /* */ +#include "macros.h" + /* Subroutines declaration */ extern void usage(void); @@ -51,7 +53,7 @@ int FortuneParse(char *file, char **fortune, int n) /* Variables definition */ FILE *fortunefile; char line[80]; - int i; + int i, len; /* * fortune file scanning, read string in memory */ @@ -67,16 +69,18 @@ int FortuneParse(char *file, char **fortune, int n) perror("Read error"); exit(-1); } - if (line[0]=='\n') { + debug("i=%d, line=%s", i, line); + if (line[0]=='%') { if (fortune[i]!=NULL) i++; continue; } + len = strlen(line) + 1; if (fortune[i]==NULL) { - fortune[i] = (char *) malloc(strlen(line)+1); - strncpy(fortune[i], line, strlen(line)+1); + fortune[i] = malloc(len); + strncpy(fortune[i], line, len); } else { - fortune[i] = (char *) realloc(fortune[i], strlen(line)+1); - strncat(fortune[i], line, strlen(line)+1); + fortune[i] = realloc(fortune[i], strlen(fortune[i])+len+1); + strncat(fortune[i], line, len); } } while (i