Corretta cattiva riallocazione su linee multiple, iniziato a inserire
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 18 Aug 2002 14:38:04 +0000 (14:38 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 18 Aug 2002 14:38:04 +0000 (14:38 +0000)
l'esempio.

ipc.tex
sources/FortuneParse.c
sources/FortuneServer.c
sources/Makefile

diff --git a/ipc.tex b/ipc.tex
index ed2d49267e852aa29b90c8141c9bca17c9a69791..37d55d5b96358c9ef8bd420ddb1d3871f1b4c824 100644 (file)
--- 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.
 
index 962ffc53e78da873abd07a96889086c09a114db0..24dabd1a51c2cbd0e873a8612b264cbb30d475e9 100644 (file)
@@ -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 <errno.h>      /* error definitions */
 #include <fcntl.h>      /*  */
 
+#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<n);
     return i;
index c00b3fedf5a80ca33d6de56dbb3652bd97b8132c..e767c1c849e8252650c5e91f0fce1c73227f05f4 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Usage: fortuned -h give all info
  *
- * $Id: FortuneServer.c,v 1.1 2002/08/18 10:34:10 piccardi Exp $
+ * $Id: FortuneServer.c,v 1.2 2002/08/18 14:38:04 piccardi Exp $
  *
  ****************************************************************/
 /* 
@@ -50,9 +50,8 @@ int FortuneParse(char *file, char **fortune, int n);
 int main(int argc, char *argv[])
 {
 /* Variables definition */
-    int n = 0;
-    FILE *fortunefile;
-    char *fortunefilename = "/usr/share/misc/fortune/fortune.it";
+    int i, n = 0;
+    char *fortunefilename = "/usr/share/games/fortunes/kids";
     char *fifoname = "/tmp/fortune.fifo";
     char **fortune;
     char line[80];
@@ -62,8 +61,7 @@ int main(int argc, char *argv[])
      * Input section: decode parameters passed in the calling 
      * Use getopt function
      */
-    int i;
-    opterr = 0;         /* don't want writing to stderr */
+    opterr = 0;                                     /* don't want writing to stderr */
     while ( (i = getopt(argc, argv, "hn:f:")) != -1) {
        switch (i) {
        /* 
@@ -81,10 +79,10 @@ int main(int argc, char *argv[])
            n = strtol(optarg, NULL, 10);
            fortune = (char **) calloc(sizeof(*fortune), n);
            break;
-       case '?':   /* unrecognized options */
+       case '?':                                    /* unrecognized options */
            printf("Unrecognized options -%c\n",optopt);
            usage();
-       default:    /* should not reached */
+       default:                                       /* should not reached */
            usage();
        }
     }
@@ -95,35 +93,35 @@ int main(int argc, char *argv[])
      *               Main code beginning
      * 
      * ***********************************************************/
-    if (n==0) {                                   /* if no pool depth exit */
-       usage();                                       /* print usage info */
-    }
-    i = FortuneParse(fortunefilename, fortune, n);
-    for (n=0; n<i; n++) debug("%s", fortune[n]);
+    if (n==0) usage();          /* if no pool depth exit printing usage info */
+    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
+    for (n=0; n<i; n++) debug("%s\n\n", fortune[n]);
     /* 
      * Comunication section 
      */
-    if (mkfifo(fifoname, 0622)) {
+    if (mkfifo(fifoname, 0622)) {  /* create well known fifo if does't exist */
        if (errno!=EEXIST) {
            perror("Cannot create well known fifo");
            exit(-1);
        }
     }
+    /* Main body: loop over requests */
     while (1) {
-       fifo_server = open(fifoname, O_RDONLY);
+       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);
+       nread = read(fifo_server, line, 79);                 /* read request */
        line[nread] = 0;
        debug("%s %d\n", line,nread);
-       n = random() % i;
+       n = random() % i;                             /* select random value */
        debug("fortune[%d]=%s\n", n, fortune[n]);
-       fifo_client = open(line, O_WRONLY);
-       nread = write(fifo_client, fortune[n], strlen(fortune[n])+1);
-       close(fifo_client);
-       close(fifo_server);
+       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 */
     }
 }
 /*
index e74f482bc438130f6fcb39b3d4552df419c496ec..d572d49ba65142a6b1fe5e73ea55833c5bb97931 100644 (file)
@@ -9,9 +9,7 @@ CFLADJ=-c
 OBJ = SockRead.o SockWrite.o
 
 FINAL = forktest errcode echo echod daytimed iterdaytimed daytime testfopen \
-       testren
-
-all: fortune fortuned
+       testren fortune fortuned
 
 fortune: FortuneClient.c
        $(CC) $^ -o $@
@@ -19,10 +17,14 @@ fortune: FortuneClient.c
 fortuned: FortuneServer.c FortuneParse.c
        $(CC) $^ -o $@
 
-
 barcode: BarCode.c
        $(CC) $(CFLAGS) $^ -o $@
 
+
+barcodepage: BarCodePage.c
+       $(CC) $(CFLAGS) $^ -o $@
+
+
 getparam: getparam.c
        $(CC) $(CFLAGS) $^ -o $@