Versione finale del client ECHO su TCP, con esempio di uso della funzione
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 9676970e57dcf5372c91c85d63d8ff00e8ada585..56caf92637cb7f867130c134554b638387f9f3bf 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -112,7 +112,7 @@ essere bloccante (qualora non siano presenti dati), inoltre se si legge da una
 pipe il cui capo in scrittura è stato chiuso, si avrà la ricezione di un EOF
 (vale a dire che la funzione \func{read} ritornerà restituendo 0).  Se invece
 si esegue una scrittura su una pipe il cui capo in lettura non è aperto il
-processo riceverà il segnale \errcode{EPIPE}, e la funzione di scrittura
+processo riceverà il segnale \const{SIGPIPE}, e la funzione di scrittura
 restituirà un errore di \errcode{EPIPE} (al ritorno del gestore, o qualora il
 segnale sia ignorato o bloccato).
 
@@ -190,55 +190,7 @@ nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[], char *envp[])
-{
-    ...
-    /* create two pipes, pipein and pipeout, to handle communication */
-    if ( (retval = pipe(pipein)) ) {
-        WriteMess("input pipe creation error");
-        exit(0);        
-    }
-    if ( (retval = pipe(pipeout)) ) {
-        WriteMess("output pipe creation error");
-        exit(0);        
-    }    
-    /* First fork: use child to run barcode program */
-    if ( (pid = fork()) == -1) {          /* on error exit */
-        WriteMess("child creation error");
-        exit(0);        
-    }
-    /* if child */
-    if (pid == 0) {
-        close(pipein[1]);                /* close pipe write end  */
-        dup2(pipein[0], STDIN_FILENO);   /* remap stdin to pipe read end */
-        close(pipeout[0]);
-        dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */
-        execlp("barcode", "barcode", size, NULL);
-    } 
-    close(pipein[0]);                    /* close input side of input pipe */
-    write(pipein[1], argv[1], strlen(argv[1]));  /* write parameter to pipe */
-    close(pipein[1]);                    /* closing write end */
-    waitpid(pid, NULL, 0);               /* wait child completion */
-    /* Second fork: use child to run ghostscript */
-    if ( (pid = fork()) == -1) {
-        WriteMess("child creation error");
-        exit(0);
-    }
-    /* second child, convert PS to JPEG  */
-    if (pid == 0) {                     
-        close(pipeout[1]);              /* close write end */
-        dup2(pipeout[0], STDIN_FILENO); /* remap read end to stdin */
-        /* send mime type */
-        write(STDOUT_FILENO, content, strlen(content));
-        execlp("gs", "gs", "-q", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL);
-    }
-    /* still parent */
-    close(pipeout[1]); 
-    waitpid(pid, NULL, 0);
-    exit(0);
-}
-    \end{lstlisting}
+    \includecodesample{listati/BarCodePage.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del \textit{CGI} 
@@ -423,37 +375,7 @@ invocato dopo.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[], char *envp[])
-{
-    FILE *pipe[4];
-    FILE *pipein;
-    char *cmd_string[4]={
-        "pnmtopng",
-        "pnmmargin -white 10",
-        "pnmcrop",
-        "gs -sDEVICE=ppmraw -sOutputFile=- -sNOPAUSE -q - -c showpage -c quit"
-    };  
-    char content[]="Content-type: image/png\n\n";
-    int i;
-    /* write mime-type to stdout */ 
-    write(STDOUT_FILENO, content, strlen(content));
-    /* execute chain of command */
-    for (i=0; i<4; i++) {
-        pipe[i] = popen(cmd_string[i], "w");
-        dup2(fileno(pipe[i]), STDOUT_FILENO); 
-    }
-    /* create barcode (in PS) */
-    pipein = popen("barcode", "w");
-    /* send barcode string to barcode program */
-    write(fileno(pipein), argv[1], strlen(argv[1]));
-    /* close all pipes (in reverse order) */
-    for (i=4; i==0; i--) {
-        pclose((pipe[i]));
-    }
-    exit(0);
-}
-    \end{lstlisting}
+    \includecodesample{listati/BarCode.c}
   \end{minipage} 
   \normalsize 
   \caption{Codice completo del \textit{CGI} \file{BarCode.c}.}
@@ -594,60 +516,7 @@ diverso da quelli preimpostati. Il codice completo 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-char *fifoname = "/tmp/fortune.fifo";
-int main(int argc, char *argv[])
-{
-/* Variables definition */
-    int i, n = 0;
-    char *fortunefilename = "/usr/share/games/fortunes/linux";
-    char **fortune;
-    char line[80];
-    int fifo_server, fifo_client;
-    int nread;
-    ...
-    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 */
-    if (mkfifo(fifoname, 0622)) {  /* create well known fifo if does't exist */
-        if (errno!=EEXIST) {
-            perror("Cannot create well known fifo");
-            exit(1);
-        }
-    }
-    daemon(0, 0);
-    /* open fifo two times to avoid EOF */
-    fifo_server = open(fifoname, O_RDONLY);
-    if (fifo_server < 0) {
-        perror("Cannot open read only well known fifo");
-        exit(1);
-    }
-    if (open(fifoname, O_WRONLY) < 0) {                        
-        perror("Cannot open write only well known fifo");
-        exit(1);
-    }
-    /* Main body: loop over requests */
-    while (1) {
-        nread = read(fifo_server, line, 79);                 /* read request */
-        if (nread < 0) {
-            perror("Read Error");
-            exit(1);
-        }
-        line[nread] = 0;                       /* terminate fifo name string */
-        n = random() % i;                             /* select random value */
-        fifo_client = open(line, O_WRONLY);              /* open client fifo */
-        if (fifo_client < 0) {
-            perror("Cannot open");
-            exit(1);
-        }
-        nread = write(fifo_client,                           /* write phrase */
-                      fortune[n], strlen(fortune[n])+1);
-        close(fifo_client);                             /* close client fifo */
-    }
-}
-    \end{lstlisting}
+    \includecodesample{listati/FortuneServer.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del server di \textit{fortunes}
@@ -737,44 +606,7 @@ principale del programma e le definizioni delle variabili. Il codice completo
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[])
-{
-/* Variables definition */
-    int n = 0;
-    char *fortunefilename = "/tmp/fortune.fifo";
-    char line[80];
-    int fifo_server, fifo_client;
-    char fifoname[80];
-    int nread;
-    char buffer[PIPE_BUF];
-    ...
-    snprintf(fifoname, 80, "/tmp/fortune.%d", getpid());     /* compose name */
-    if (mkfifo(fifoname, 0622)) {                        /* open client fifo */
-        if (errno!=EEXIST) {
-            perror("Cannot create well known fifo");
-            exit(-1);
-        }
-    }
-    fifo_server = open(fortunefilename, O_WRONLY);       /* open server fifo */
-    if (fifo_server < 0) {
-        perror("Cannot open well known fifo");
-        exit(-1);
-    }
-    nread = write(fifo_server, fifoname, strlen(fifoname)+1);  /* write name */
-    close(fifo_server);                                 /* close server fifo */
-    fifo_client = open(fifoname, O_RDONLY);              /* open client fifo */
-    if (fifo_client < 0) {
-        perror("Cannot open well known fifo");
-        exit(-1);
-    }
-    nread = read(fifo_client, buffer, sizeof(buffer));        /* read answer */
-    printf("%s", buffer);                                   /* print fortune */
-    close(fifo_client);                                      /* close client */
-    close(fifo_server);                                      /* close server */
-    unlink(fifoname);                                  /* remove client fifo */
-}
-    \end{lstlisting}
+    \includecodesample{listati/FortuneClient.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del client di \textit{fortunes}
@@ -1002,18 +834,7 @@ mantiene varie propriet
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm ]{}
-struct ipc_perm
-{
-    key_t key;                        /* Key.  */
-    uid_t uid;                        /* Owner's user ID.  */
-    gid_t gid;                        /* Owner's group ID.  */
-    uid_t cuid;                       /* Creator's user ID.  */
-    gid_t cgid;                       /* Creator's group ID.  */
-    unsigned short int mode;          /* Read/write permission.  */
-    unsigned short int seq;           /* Sequence number.  */
-};
-    \end{lstlisting}
+    \includestruct{listati/ipc_perm.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{ipc\_perm}, come definita in
@@ -1210,41 +1031,7 @@ s
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[])
-{
-    ...
-    switch (type) {
-    case 'q':   /* Message Queue */
-        debug("Message Queue Try\n");
-        for (i=0; i<n; i++) {
-            id = msgget(IPC_PRIVATE, IPC_CREAT|0666);
-            printf("Identifier Value %d \n", id);
-            msgctl(id, IPC_RMID, NULL);
-        }
-        break;
-    case 's':   /* Semaphore */
-        debug("Semaphore\n");
-        for (i=0; i<n; i++) {
-            id = semget(IPC_PRIVATE, 1, IPC_CREAT|0666);
-            printf("Identifier Value %d \n", id);
-            semctl(id, 0, IPC_RMID);
-        }
-        break;
-    case 'm':   /* Shared Memory */
-        debug("Shared Memory\n");
-        for (i=0; i<n; i++) {
-            id = shmget(IPC_PRIVATE, 1000, IPC_CREAT|0666);
-            printf("Identifier Value %d \n", id);
-            shmctl(id, IPC_RMID, NULL);
-        }
-        break;
-    default:    /* should not reached */
-        return -1;
-    }
-    return 0;
-}
-    \end{lstlisting}
+    \includecodesample{listati/IPCTestId.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del programma di test per l'assegnazione degli
@@ -1415,21 +1202,7 @@ kernel.\footnote{lo schema illustrato in \figref{fig:ipc_mq_schema} 
 \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 */
-    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 */
-    unsigned long int msg_cbytes; /* current number of bytes on queue */
-};
-    \end{lstlisting}
+    \includestruct{listati/msqid_ds.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{msqid\_ds}, associata a ciascuna coda di
@@ -1455,7 +1228,7 @@ 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}
+\begin{itemize*}
 \item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
   sulla coda, viene inizializzato a 0.
 \item i campi \var{msg\_lspid} e \var{msg\_lrpid}, che esprimono
@@ -1474,7 +1247,7 @@ gli altri campi invece:
   \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).
-\end{itemize}
+\end{itemize*}
 
 Una volta creata una coda di messaggi le operazioni di controllo vengono
 effettuate con la funzione \funcd{msgctl}, che (come le analoghe \func{semctl}
@@ -1595,12 +1368,7 @@ dovr
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-    struct msgbuf {
-         long mtype;          /* message type, must be > 0 */
-         char mtext[LENGTH];  /* message data */
-    };
-    \end{lstlisting}
+    \includestruct{listati/msgbuf.h}
   \end{minipage} 
   \normalsize 
   \caption{Schema della struttura \structd{msgbuf}, da utilizzare come
@@ -1755,57 +1523,8 @@ in maniera indipendente con client diversi.
 
 \begin{figure}[!bht]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int msgid;                                       /* Message queue identifier */
-int main(int argc, char *argv[])
-{
-/* Variables definition */
-    int i, n = 0;
-    char **fortune;                       /* array of fortune message string */
-    char *fortunefilename = "/usr/share/games/fortunes/linux";  /* file name */
-    struct msgbuf_read {      /* message struct to read request from clients */
-        long mtype;                               /* message type, must be 1 */
-        long pid;             /* message data, must be the pid of the client */
-    } msg_read;
-    struct msgbuf_write {       /* message struct to write result to clients */
-        long mtype;            /* message type, will be the pid of the client*/
-        char mtext[MSGMAX];             /* message data, will be the fortune */
-    } msg_write;
-    key_t key;                                          /* Message queue key */
-    int size;                                                /* message size */
-    ...
-    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
-    Signal(SIGINT, HandSIGTERM);
-    Signal(SIGQUIT, HandSIGTERM);
-    if (n==0) usage();          /* if no pool depth exit printing usage info */
-    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
-    /* Create the queue */
-    key = ftok("./MQFortuneServer.c", 1); 
-    msgid = msgget(key, IPC_CREAT|0666);
-    if (msgid < 0) {
-        perror("Cannot create message queue");
-        exit(1);
-    }
-    /* Main body: loop over requests */
-    daemon(0, 0);
-    while (1) {
-        msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR);
-        n = random() % i;                             /* select random value */
-        strncpy(msg_write.mtext, fortune[n], MSGMAX);
-        size = min(strlen(fortune[n])+1, MSGMAX);  
-        msg_write.mtype=msg_read.pid;             /* use request pid as type */
-        msgsnd(msgid, &msg_write, size, 0);
-    }
-}
-/*
- * Signal Handler to manage termination
- */
-void HandSIGTERM(int signo) {
-    msgctl(msgid, IPC_RMID, NULL);                   /* remove message queue */
-    exit(0);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MQFortuneServer.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del server di \textit{fortunes}
@@ -1878,26 +1597,8 @@ gestore \code{HandSIGTERM}, che semplicemente si limita a cancellare la coda
 
 \begin{figure}[!bht]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[])
-{
-    ...
-    key = ftok("./MQFortuneServer.c", 1); 
-    msgid = msgget(key, 0); 
-    if (msgid < 0) {
-        perror("Cannot find message queue");
-        exit(1);
-    }
-    /* Main body: do request and write result */
-    msg_read.mtype = 1;                      /* type for request is always 1 */
-    msg_read.pid = getpid();                   /* use pid for communications */
-    size = sizeof(msg_read.pid);  
-    msgsnd(msgid, &msg_read, size, 0);               /* send request message */
-    msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR);
-    printf("%s", msg_write.mtext);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MQFortuneClient.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del client di \textit{fortunes}
@@ -2087,15 +1788,7 @@ semaforo all'uscita del processo.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct semid_ds
-{
-    struct ipc_perm sem_perm;           /* operation permission struct */
-    time_t sem_otime;                   /* last semop() time */
-    time_t sem_ctime;                   /* last time changed by semctl() */
-    unsigned long int sem_nsems;        /* number of semaphores in set */
-};
-    \end{lstlisting}
+    \includestruct{listati/semid_ds.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{semid\_ds}, associata a ciascun insieme di
@@ -2137,14 +1830,7 @@ controllo.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct sem {
-  short   sempid;         /* pid of last operation */
-  ushort  semval;         /* current value */
-  ushort  semncnt;        /* num procs awaiting increase in semval */
-  ushort  semzcnt;        /* num procs awaiting semval = 0 */
-};
-    \end{lstlisting}
+    \includestruct{listati/sem.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{sem}, che contiene i dati di un singolo
@@ -2234,15 +1920,7 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-union semun {
-      int val;                  /* value for SETVAL */
-      struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
-      unsigned short *array;    /* array for GETALL, SETALL */
-                                /* Linux specific part: */
-      struct seminfo *__buf;    /* buffer for IPC_INFO */
-};
-    \end{lstlisting}
+    \includestruct{listati/semun.h}
   \end{minipage} 
   \normalsize 
   \caption{La definizione dei possibili valori di una \direct{union}
@@ -2388,14 +2066,7 @@ effettivamente eseguite se e soltanto se 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct sembuf
-{
-  unsigned short int sem_num;   /* semaphore number */
-  short int sem_op;             /* semaphore operation */
-  short int sem_flg;            /* operation flag */
-};
-    \end{lstlisting}
+    \includestruct{listati/sembuf.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{sembuf}, usata per le operazioni sui
@@ -2571,57 +2242,7 @@ nullo per segnalarne l'indisponibilit
 \begin{figure}[!bht]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* Function MutexCreate: create a mutex/semaphore */
-int MutexCreate(key_t ipc_key) 
-{
-    const union semun semunion={1};             /* semaphore union structure */
-    int sem_id, ret;
-    sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
-    if (sem_id == -1) {                              /* if error return code */
-        return sem_id;
-    }
-    ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
-    if (ret == -1) {
-        return ret;
-    }
-    return sem_id;
-}
-/* Function MutexFind: get the semaphore/mutex Id given the IPC key value */
-int MutexFind(key_t ipc_key) 
-{
-    return semget(ipc_key,1,0);
-}
-/* Function MutexRead: read the current value of the mutex/semaphore */
-int MutexRead(int sem_id) 
-{
-    return semctl(sem_id, 0, GETVAL);
-}
-/* Define sembuf structures to lock and unlock the semaphore  */
-struct sembuf sem_lock={                                /* to lock semaphore */
-    0,                                   /* semaphore number (only one so 0) */
-    -1,                                    /* operation (-1 to use resource) */
-    SEM_UNDO};                                /* flag (set for undo at exit) */
-struct sembuf sem_ulock={                             /* to unlock semaphore */
-    0,                                   /* semaphore number (only one so 0) */
-    1,                                  /* operation (1 to release resource) */
-    SEM_UNDO};                                      /* flag (in this case 0) */
-/* Function MutexLock: to lock a mutex/semaphore */
-int MutexLock(int sem_id) 
-{
-    return semop(sem_id, &sem_lock, 1);
-}
-/* Function MutexUnlock: to unlock a mutex/semaphore */
-int MutexUnlock(int sem_id) 
-{
-    return semop(sem_id, &sem_ulock, 1);
-}
-/* Function MutexRemove: remove a mutex/semaphore */
-int MutexRemove(int sem_id) 
-{
-    return semctl(sem_id, 0, IPC_RMID);
-}
-    \end{lstlisting}
+    \includecodesample{listati/Mutex.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni che permettono di creare o recuperare
@@ -2749,18 +2370,7 @@ norma, significa insieme a dei semafori.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct shmid_ds {
-     struct    ipc_perm shm_perm;  /* operation perms */
-     int  shm_segsz;               /* size of segment (bytes) */
-     time_t    shm_atime;          /* last attach time */
-     time_t    shm_dtime;          /* last detach time */
-     time_t    shm_ctime;          /* last change time */
-     unsigned short shm_cpid;      /* pid of creator */
-     unsigned short shm_lpid;      /* pid of last operator */
-     short     shm_nattch;         /* no. of current attaches */
-};
-    \end{lstlisting}
+    \includestruct{listati/shmid_ds.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{shmid\_ds}, associata a ciascun segmento di
@@ -2776,7 +2386,7 @@ campo \var{shm\_perm} viene inizializzato come illustrato in
 \secref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte
 relativamente ai permessi di accesso; per quanto riguarda gli altri campi
 invece:
-\begin{itemize*}
+\begin{itemize}
 \item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene
   inizializzato al valore di \param{size}.
 \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
@@ -2790,7 +2400,7 @@ invece:
   creato il segmento, viene inizializzato al \acr{pid} del processo chiamante.
 \item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati
   al segmento viene inizializzato a zero.
-\end{itemize*}
+\end{itemize}
 
 Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
 di memoria condivisa esistono una serie di limiti imposti dal sistema.  Alcuni
@@ -3044,6 +2654,55 @@ In caso di successo la funzione aggiorna anche i seguenti campi di
 inoltre la regione di indirizzi usata per il segmento di memoria condivisa
 viene tolta dallo spazio di indirizzi del processo.
 
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/SharedMem.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni che permettono di creare, trovare e
+    rimuovere un segmento di memoria condivisa.}
+  \label{fig:ipc_sysv_shm_func}
+\end{figure}
+
+Come esempio di uso di queste funzioni vediamo come implementare una serie di
+funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni
+più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in
+\figref{fig:ipc_sysv_shm_func}.
+
+La prima funzione (\texttt{\small 3--16}) è \func{ShmCreate} che, data una
+chiave, crea il segmento di memoria condivisa restituendo il puntatore allo
+stesso. La funzione comincia (\texttt{\small 6}) con il chiamare
+\func{shmget}, usando il flag \const{IPC\_CREATE} per creare il segmento
+qualora non esista, ed assegnandogli i privilegi specificati dall'argomento
+\var{perm} e la dimensione specificata dall'argomento \var{shm\_size}.  In
+caso di errore (\texttt{\small 7--9}) si ritorna immediatamente un puntatore
+nullo, altrimenti (\texttt{\small 10}) si prosegue agganciando il segmento di
+memoria condivisa al processo con \func{shmat}. In caso di errore
+(\texttt{\small 11--13}) si restituisce di nuovo un puntatore nullo, infine
+(\texttt{\small 14}) si inizializza con \func{memset} il contenuto del
+segmento al valore costante specificato dall'argomento \var{fill}, e poi si
+ritorna il puntatore al segmento stesso.
+
+La seconda funzione (\texttt{\small 17--31}) è \func{ShmFind}, che, data una
+chiave, restituisce l'indirizzo del segmento ad essa associato. Anzitutto
+(\texttt{\small 22}) si richiede l'identificatore del segmento con
+\func{shmget}, ritornando (\texttt{\small 23--25}) un puntatore nullo in caso
+di errore. Poi si prosegue (\texttt{\small 26}) agganciando il segmento al
+processo con \func{shmat}, restituendo (\texttt{\small 27--29}) di nuovo un
+puntatore nullo in caso di errore, se invece non ci sono errori si restituisce
+il puntatore ottenuto da \func{shmat}.
+
+La terza funzione (\texttt{\small 32--51}) è \func{ShmRemove} che, data la
+chiave ed il puntatore associati al segmento di memoria condivisa, prima lo
+sgancia dal processo e poi lo rimuove. Il primo passo (\texttt{\small 37}) è
+la chiamata a \func{shmdt} per sganciare il segmento, restituendo
+(\texttt{\small 38--39}) un valore -1 in caso di errore. Il passo successivo
+(\texttt{\small 41}) è utilizzare \func{shmget} per ottenre l'identificatore
+associato al segmento data la chiave \var{key}. Al solito si restituisce un
+valore di -1 (\texttt{\small 42--45}) in caso di errore, mentre se tutto va
+bene si conclude restituendo un valore nullo.
+
 Benché la memoria condivisa costituisca il meccanismo di intercomunicazione
 fra processi più veloce, essa non è sempre il più appropriato, dato che, come
 abbiamo visto, si avrà comunque la necessità di una sincronizzazione degli
@@ -3084,63 +2743,8 @@ video; al solito il codice completo si trova con i sorgenti allegati nel file
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* global variables for shared memory segment */
-struct DirProp {
-    int tot_size;    
-    int tot_files;   
-    int tot_regular; 
-    int tot_fifo;    
-    int tot_link;    
-    int tot_dir;     
-    int tot_block;   
-    int tot_char;    
-    int tot_sock;
-} *shmptr;
-int shmid; 
-int mutex;
-/* main body */
-int main(int argc, char *argv[]) 
-{
-    int i;
-    key_t key;
-    ...
-    if ((argc - optind) != 1) {          /* There must be remaing parameters */
-        printf("Wrong number of arguments %d\n", argc - optind);
-        usage();
-    }
-    if (chdir(argv[1])) {                      /* chdir to be sure dir exist */
-        perror("Cannot find directory to monitor");
-    }
-    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
-    Signal(SIGINT, HandSIGTERM);
-    Signal(SIGQUIT, HandSIGTERM);
-    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
-    shmid = shmget(key, 4096, IPC_CREAT|0666);        /* get a shared memory */
-    if (shmid < 0) {
-        perror("Cannot create shared memory");
-        exit(1);
-    }
-    if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
-        perror("Cannot attach segment");
-        exit(1);
-    }
-    if ((mutex = MutexCreate(key)) == -1) {                   /* get a Mutex */
-        perror("Cannot create mutex");
-        exit(1);
-    }
-    /* main loop, monitor directory properties each 10 sec */
-    daemon(1, 0);              /* demonize process, staying in monitored dir */
-    while (1) {
-        MutexLock(mutex);                              /* lock shared memory */
-        memset(shmptr, 0, sizeof(struct DirProp));    /* erase previous data */
-        DirScan(argv[1], ComputeValues);                     /* execute scan */
-        MutexUnlock(mutex);                          /* unlock shared memory */
-        sleep(pause);                              /* sleep until next watch */
-    }
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/DirMonitor.c}
   \end{minipage} 
   \normalsize 
   \caption{Codice della funzione principale del programma \file{DirMonitor.c}.}
@@ -3157,104 +2761,68 @@ Il programma, dopo la sezione, omessa, relativa alla gestione delle opzioni da
 riga di comando (che si limitano alla eventuale stampa di un messaggio di
 aiuto a video ed all'impostazione della durata dell'intervallo con cui viene
 ripetuto il calcolo delle proprietà della directory) controlla (\texttt{\small
-  21--24}) che sia stato specificato il parametro necessario contenente il
+  20--23}) che sia stato specificato il parametro necessario contenente il
 nome della directory da tenere sotto controllo, senza il quale esce
 immediatamente con un messaggio di errore.
 
 Poi, per verificare che il parametro specifichi effettivamente una directory,
-si esegue (\texttt{\small 25--27}) su di esso una \func{chdir}, uscendo
+si esegue (\texttt{\small 24--26}) su di esso una \func{chdir}, uscendo
 immediatamente in caso di errore.  Questa funzione serve anche per impostare
 la directory di lavoro del programma nella directory da tenere sotto
 controllo, in vista del successivo uso della funzione
-\func{daemon}.\footnote{Si noti come si è potuta fare questa scelta,
+\func{daemon}.\footnote{si noti come si è potuta fare questa scelta,
   nonostante le indicazioni illustrate in \secref{sec:sess_daemon}, per il
   particolare scopo del programma, che necessita comunque di restare
-  all'interno di una directory.} Infine (\texttt{\small 28--30}) si installano
+  all'interno di una directory.} Infine (\texttt{\small 27--29}) si installano
 i gestori per i vari segnali di terminazione che, avendo a che fare con un
 programma che deve essere eseguito come server, sono il solo strumento
 disponibile per concluderne l'esecuzione.
 
-Il passo successivo (\texttt{\small 31--44}) è quello di creare gli oggetti di
-intercomunicazione necessari. Si inizia costruendo (\texttt{\small 31}) la
+Il passo successivo (\texttt{\small 30--39}) è quello di creare gli oggetti di
+intercomunicazione necessari. Si inizia costruendo (\texttt{\small 30}) la
 chiave da usare come riferimento con il nome del programma,\footnote{si è
   usato un riferimento relativo alla home dell'utente, supposto che i sorgenti
   di GaPiL siano stati installati direttamente in essa. Qualora si effettui
   una installazione diversa si dovrà correggere il programma.} dopo di che si
-richiede (\texttt{\small 32}) la creazione di un segmento di memoria condivisa
-con \func{shmget} (una pagina di memoria è sufficiente per i dati che
-useremo), uscendo (\texttt{\small 33--36}) qualora la creazione non abbia
-successo.
-
-Una volta ottenutone l'identificatore in \var{shmid}, si può agganciare
-(\texttt{\small 37--40}) il segmento al processo con \func{shmat} anche in
-questo caso si esce qualora la funzione non abbia successo. Con l'indirizzo
-\var{shmptr} così ottenuto potremo poi accedere alla memoria condivisa, che,
-per come abbiamo lo abbiamo definito, sarà vista nella forma data da
-\struct{DirProp}. Infine (\texttt{\small 41--44}) utilizzando sempre la stessa
-chiave, si crea, tramite le funzioni di interfaccia già descritte in
-\secref{sec:ipc_sysv_sem}, anche un mutex, che utilizzeremo per regolare
-l'accesso alla memoria condivisa.
-
-Una volta completata l'inizializzazione e la creazione degli oggetti di
-intercomunicazione il programma entra nel ciclo principale (\texttt{\small
-  45--54}) dove vengono eseguite indefinitamente le attività di monitoraggio.
-Il primo passo (\texttt{\small 46}) è eseguire \func{daemon} per proseguire con
-l'esecuzione in background come si conviene ad un programma demone; si noti
-che si è mantenuta, usando un valore non nullo del primo argomento, la
-directory di lavoro corrente.
-
-Una volta che il programma è andato in background l'esecuzione prosegue
-(\texttt{\small 47--53}) all'interno di un ciclo infinito: si inizia
-(\texttt{\small 48}) bloccando il mutex con \func{MutexLock} per poter
-accedere alla memoria condivisa (la funzione si bloccherà automaticamente se
-qualche client sta leggendo), poi (\texttt{\small 49}) si cancellano i valori
-precedentemente immagazzinati nella memoria condivisa con \func{memset}, e si
-esegue (\texttt{\small 50}) un nuovo calcolo degli stessi utilizzando la
-funzione \func{DirScan}; infine (\texttt{\small 51}) si sblocca il mutex con
-\func{MutexUnlock}, e si attende (\texttt{\small 52}) per il periodo di tempo
-specificato a riga di comando con l'opzione \code{-p} con una \func{sleep}.
+richiede (\texttt{\small 31}) la creazione di un segmento di memoria condivisa
+con usando la funzione \func{ShmCreate} illustrata in precedenza (una pagina
+di memoria è sufficiente per i dati che useremo), uscendo (\texttt{\small
+  32--35}) qualora la creazione ed il successivo agganciamento al processo non
+abbia successo. Con l'indirizzo \var{shmptr} così ottenuto potremo poi
+accedere alla memoria condivisa, che, per come abbiamo lo abbiamo definito,
+sarà vista nella forma data da \struct{DirProp}. Infine (\texttt{\small
+  36--39}) utilizzando sempre la stessa chiave, si crea, tramite le funzioni
+di interfaccia già descritte in \secref{sec:ipc_sysv_sem}, anche un mutex, che
+utilizzeremo per regolare l'accesso alla memoria condivisa.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* Routine  to compute directory properties inside DirScan */
-int ComputeValues(struct dirent * direntry) 
-{
-    struct stat data;
-    stat(direntry->d_name, &data);                          /* get stat data */
-    shmptr->tot_size += data.st_size;
-    shmptr->tot_files++;
-    if (S_ISREG(data.st_mode)) shmptr->tot_regular++;
-    if (S_ISFIFO(data.st_mode)) shmptr->tot_fifo++;
-    if (S_ISLNK(data.st_mode)) shmptr->tot_link++;
-    if (S_ISDIR(data.st_mode)) shmptr->tot_dir++;
-    if (S_ISBLK(data.st_mode)) shmptr->tot_block++;
-    if (S_ISCHR(data.st_mode)) shmptr->tot_char++;
-    if (S_ISSOCK(data.st_mode)) shmptr->tot_sock++;
-    return 0;
-}
-/* Signal Handler to manage termination */
-void HandSIGTERM(int signo) {
-    MutexLock(mutex);
-    if (shmdt(shmptr)) {
-        perror("Error detaching shared memory");
-        exit(1);
-    }
-    if (shmctl(shmid, IPC_RMID, NULL)) {
-        perror("Cannot remove shared memory segment");
-        exit(1);
-    }
-    MutexRemove(mutex);
-    exit(0);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ComputeValues.c}
   \end{minipage} 
   \normalsize 
-  \caption{Codice delle funzione ausiliarie usate da \file{DirMonitor.c}.}
+  \caption{Codice delle funzioni ausiliarie usate da \file{DirMonitor.c}.}
   \label{fig:ipc_dirmonitor_sub}
 \end{figure}
 
+Completata l'inizializzazione e la creazione degli oggetti di
+intercomunicazione il programma entra nel ciclo principale (\texttt{\small
+  40--49}) dove vengono eseguite indefinitamente le attività di monitoraggio.
+Il primo passo (\texttt{\small 41}) è eseguire \func{daemon} per proseguire
+con l'esecuzione in background come si conviene ad un programma demone; si
+noti che si è mantenuta, usando un valore non nullo del primo argomento, la
+directory di lavoro corrente.  Una volta che il programma è andato in
+background l'esecuzione prosegue (\texttt{\small 42--48}) all'interno di un
+ciclo infinito: si inizia (\texttt{\small 43}) bloccando il mutex con
+\func{MutexLock} per poter accedere alla memoria condivisa (la funzione si
+bloccherà automaticamente se qualche client sta leggendo), poi (\texttt{\small
+  44}) si cancellano i valori precedentemente immagazzinati nella memoria
+condivisa con \func{memset}, e si esegue (\texttt{\small 45}) un nuovo calcolo
+degli stessi utilizzando la funzione \func{DirScan}; infine (\texttt{\small
+  46}) si sblocca il mutex con \func{MutexUnlock}, e si attende
+(\texttt{\small 47}) per il periodo di tempo specificato a riga di comando con
+l'opzione \code{-p} con una \func{sleep}.
+
 Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si
 sia usata ancora una volta la funzione \func{DirScan}, già utilizzata (e
 descritta in dettaglio) in \secref{sec:file_dir_read}, che ci permette di
@@ -3277,55 +2845,20 @@ dei file ed il loro numero, poi, utilizzando le macro di
 \tabref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce ne
 sono per ciascun tipo.
 
-In \figref{fig:ipc_dirmonitor_sub} è riportato anche (\texttt{\small 17--30})
-il codice del gestore dei segnali di terminazione, usato per chiudere il
+In \figref{fig:ipc_dirmonitor_sub} è riportato anche il codice (\texttt{\small
+  17--23}) del gestore dei segnali di terminazione, usato per chiudere il
 programma. Esso, oltre a provocare l'uscita del programma, si incarica anche
 di cancellare tutti gli oggetti di intercomunicazione non più necessari.  Per
 questo anzitutto (\texttt{\small 19}) acquisisce il mutex con
 \func{MutexLock}, per evitare di operare mentre un client sta ancora leggendo
-i dati, dopo di che (\texttt{\small 20--23}) prima distacca il segmento di
-memoria condivisa con \func{shmad} e poi (\texttt{\small 24--27}) lo cancella
-con \func{shctl}.  Infine (\texttt{\small 28}) rimuove il mutex con
-\func{MutexRemove} ed esce.
+i dati, dopo di che (\texttt{\small 20}) distacca e rimuove il segmento di
+memoria condivisa usando \func{ShmRemove}.  Infine (\texttt{\small 21})
+rimuove il mutex con \func{MutexRemove} ed esce (\texttt{\small 22}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-int main(int argc, char *argv[]) 
-{
-    int i;
-    key_t key;
-    ...
-    /* create needed IPC objects */
-    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
-    shmid = shmget(key, 4096, 0);                /* get the shared memory ID */
-    if (shmid < 0) {
-        perror("Cannot find shared memory");
-        exit(1);
-    }
-    if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
-        perror("Cannot attach segment");
-        exit(1);
-    }
-    if ((mutex = MutexFind(key)) == -1) {                   /* get the Mutex */
-        perror("Cannot find mutex");
-        exit(1);
-    }
-    /* main loop */
-    MutexLock(mutex);                                  /* lock shared memory */
-    printf("Ci sono %d file dati\n", shmptr->tot_regular);
-    printf("Ci sono %d directory\n", shmptr->tot_dir);
-    printf("Ci sono %d link\n", shmptr->tot_link);
-    printf("Ci sono %d fifo\n", shmptr->tot_fifo);
-    printf("Ci sono %d socket\n", shmptr->tot_sock);
-    printf("Ci sono %d device a caratteri\n", shmptr->tot_char);
-    printf("Ci sono %d device a blocchi\n", shmptr->tot_block);
-    printf("Totale  %d file, per %d byte\n",
-           shmptr->tot_files, shmptr->tot_size);
-    MutexUnlock(mutex);                              /* unlock shared memory */
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6 cm}
+    \includecodesample{listati/ReadMonitor.c}
   \end{minipage} 
   \normalsize 
   \caption{Codice del programma client del monitor delle proprietà di una
@@ -3333,31 +2866,25 @@ int main(int argc, char *argv[])
   \label{fig:ipc_dirmonitor_client}
 \end{figure}
 
-Il codice del client, che permette di leggere le informazioni mantenute nella
-memoria condivisa, è riportato in \figref{fig:ipc_dirmonitor_client}. Al
-solito si è omessa la sezione di gestione delle opzioni e la funzione che
-stampa a video le istruzioni; il codice completo è nei sorgenti allegati, nel
-file \file{ReadMonitor.c}.
+Il codice del client usato per leggere le informazioni mantenute nella memoria
+condivisa è riportato in \figref{fig:ipc_dirmonitor_client}. Al solito si è
+omessa la sezione di gestione delle opzioni e la funzione che stampa a video
+le istruzioni; il codice completo è nei sorgenti allegati, nel file
+\file{ReadMonitor.c}.
 
-Una volta completata la gestione delle opzioni a riga di comando il programma
+Una volta conclusa la gestione delle opzioni a riga di comando il programma
 rigenera (\texttt{\small 7}) con \func{ftok} la stessa chiave usata dal server
 per identificare il segmento di memoria condivisa ed il mutex, poi
-(\texttt{\small 8}) si richiede con \func{semget} l'identificatore della
-memoria condivisa, ma in questo caso si vuole che esso esista di già; al
-solito (\texttt{\small 9--12}) si esce in caso di errore. Una volta ottenuto
-l'identificatore in \var{shmid} si può (\texttt{\small 13--16}) agganciare il
-segmento al processo all'indirizzo \func{shmptr}; anche in questo caso si
-chiude immediatamente il programma se qualcosa non funziona.  Infine
+(\texttt{\small 8}) richiede con \func{ShmFind} l'indirizzo della memoria
+condivisa agganciando al contempo il segmento al processo, Infine
 (\texttt{\small 17--20}) con \func{MutexFind} si richiede l'identificatore del
-mutex.
-
-Una volta completata l'inizializzazione ed ottenuti i riferimenti agli oggetti
+mutex.  Completata l'inizializzazione ed ottenuti i riferimenti agli oggetti
 di intercomunicazione necessari viene eseguito il corpo principale del
 programma (\texttt{\small 21--33}); si comincia (\texttt{\small 22})
 acquisendo il mutex con \func{MutexLock}; qui avviene il blocco del processo
 se la memoria condivisa non è disponibile.  Poi (\texttt{\small 23--31}) si
 stampano i vari valori mantenuti nella memoria condivisa attraverso l'uso di
-\var{shmptr}. Infine (\texttt{\small 41}) con \func{MutexUnlock} si rilascia
+\var{shmptr}.  Infine (\texttt{\small 41}) con \func{MutexUnlock} si rilascia
 il mutex, prima di uscire.
 
 Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando
@@ -3399,8 +2926,8 @@ key        msqid      owner      perms      used-bytes   messages
 \end{verbatim}%$
 
 Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova},
-potremo verificare (passati nel peggiore dei casi almeno 10 secondi, cioè
-l'intervallo scelto per la rilettura dei dati), che:
+potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o
+l'eventuale altro intervallo impostato per la rilettura dei dati) avremo:
 \begin{verbatim}
 [piccardi@gont sources]$ ./readmon 
 Ci sono 69 file dati
@@ -3413,14 +2940,15 @@ Ci sono 0 device a blocchi
 Totale  72 file, per 489887 byte
 \end{verbatim}%$
 
-Infine potremo terminare il server con il comando \code{killall dirmonitor},
-nel qual caso, ripetendo la lettura otterremo che:
+A questo punto possiamo far uscire il server inviandogli un segnale di
+\const{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto
+ripetendo la lettura, otterremo un errore:
 \begin{verbatim}
 [piccardi@gont sources]$ ./readmon 
 Cannot find shared memory: No such file or directory
 \end{verbatim}%$
-e potremo verificare che anche gli oggetti di intercomunicazione sono stati
-cancellati:
+e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione
+visti in precedenza sono stati regolarmente  cancellati:
 \begin{verbatim}
 [piccardi@gont sources]$ ipcs
 ------ Shared Memory Segments --------
@@ -3519,26 +3047,8 @@ cancella con \func{unlink}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>                               /* unix standard functions */
-/*
- * Function LockFile:
- */
-int LockFile(const char* path_name)
-{
-    return open(path_name, O_EXCL|O_CREAT);
-}
-/*
- * Function UnlockFile:
- */
-int UnlockFile(const char* path_name) 
-{
-    return unlink(path_name);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/LockFile.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni \func{LockFile} e \func{UnlockFile} che
@@ -3599,64 +3109,8 @@ leggermente pi
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* Function CreateMutex: Create a mutex using file locking. */
-int CreateMutex(const char *path_name)
-{
-    return open(path_name, O_EXCL|O_CREAT);
-}
-/* Function UnlockMutex: unlock a file. */
-int FindMutex(const char *path_name)
-{
-    return open(path_name, O_RDWR);
-}
-/* Function LockMutex: lock mutex using file locking. */
-int LockMutex(int fd)
-{
-    struct flock lock;                                /* file lock structure */
-    /* set flock structure */
-    lock.l_type = F_WRLCK;                        /* set type: read or write */
-    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
-    lock.l_start = 0;                  /* set the start of the locked region */
-    lock.l_len = 0;                   /* set the length of the locked region */
-    /* do locking */
-    return fcntl(fd, F_SETLKW, &lock);
-}
-/* Function UnlockMutex: unlock a file. */
-int UnlockMutex(int fd)
-{
-    struct flock lock;                                /* file lock structure */
-    /* set flock structure */
-    lock.l_type = F_UNLCK;                               /* set type: unlock */
-    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
-    lock.l_start = 0;                  /* set the start of the locked region */
-    lock.l_len = 0;                   /* set the length of the locked region */
-    /* do locking */
-    return fcntl(fd, F_SETLK, &lock);
-}
-/* Function RemoveMutex: remove a mutex (unlinking the lock file). */
-int RemoveMutex(const char *path_name)
-{
-    return unlink(path_name);
-}
-/* Function ReadMutex: read a mutex status. */
-int ReadMutex(int fd)
-{
-    int res;
-    struct flock lock;                                /* file lock structure */
-    /* set flock structure */
-    lock.l_type = F_WRLCK;                               /* set type: unlock */
-    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
-    lock.l_start = 0;                  /* set the start of the locked region */
-    lock.l_len = 0;                   /* set the length of the locked region */
-    /* do locking */
-    if ( (res = fcntl(fd, F_GETLK, &lock)) ) {
-        return res;
-    }
-    return lock.l_type;
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MutexLocking.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni che permettono per la gestione dei 
@@ -3812,22 +3266,24 @@ Data la assoluta genericit
 è pertanto subordinato in maniera quasi completa alla relativa
 implementazione.\footnote{tanto che Stevens in \cite{UNP2} cita questo caso
   come un esempio della maniera standard usata dallo standard POSIX per
-  consentire implementazioni non standardizzabili.} Nel caso di Linux per
-quanto riguarda la memoria condivisa, tutto viene creato nella directory
-\file{/dev/shm}, ed i nomi sono presi come pathname assoluto (comprendente
-eventuali sottodirectory) rispetto a questa radice (per maggiori dettagli si
-veda quanto illustrato in \secref{sec:ipc_posix_shm}). Lo stesso accade per
-l'implementazione sperimentale delle code di messaggi, che però fa riferimento
-alla directory \file{/dev/mqueue}.
+  consentire implementazioni non standardizzabili.} Nel caso di Linux, sia per
+quanto riguarda la memoria condivisa, che per quanto riguarda le code di
+messaggi, tutto viene creato usando come radici delle opportune directory
+(rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si
+faccia riferimento a \secref{sec:ipc_posix_shm} e \secref{sec:ipc_posix_mq})
+ed i nomi specificati nelle relative funzioni sono considerati come un
+pathname assoluto (comprendente eventuali sottodirectory) rispetto a queste
+radici. 
 
 Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti
 nell'albero dei file, e possono essere maneggiati con le usuali funzioni e
-comandi di accesso ai file,\footnote{questo è vero nel caso di Linux, che usa
-  una implementazione che lo consente, non è detto che altrettanto valga per
-  altri kernel. In particolare per la memoria condivisa, come si può
-  facilmente evincere con uno \cmd{strace}, le system call utilizzate sono le
-  stesse, in quanto essa è realizzata con file in uno speciale filesystem.}
-che funzionano come su dei file normali.
+comandi di accesso ai file,\footnote{questo è ancora più vero nel caso di
+  Linux, che usa una implementazione che lo consente, non è detto che
+  altrettanto valga per altri kernel. In particolare sia la memoria condivisa
+  che per le code di messaggi, come si può facilmente evincere con uno
+  \cmd{strace}, le system call utilizzate sono le stesse, in quanto esse sono
+  realizzate con dei file in speciali filesystem.}  che funzionano come su dei
+file normali.
 
 In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai
 permessi dei file, e il controllo di accesso segue esattamente la stessa
@@ -3849,7 +3305,7 @@ per
 Benedyczak,\footnote{i patch al kernel e la relativa libreria possono essere
 trovati su
 \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
-{http://www.mat.uni.torun.pl/\~{}wrona/posix\_ipc}.}.
+{http://www.mat.uni.torun.pl/\tild{}wrona/posix\_ipc}.}.
 In generale, come le corrispettive del SysV IPC, le code di messaggi sono poco
 usate, dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono
 più comodi, e che in casi più complessi la comunicazione può essere gestita
@@ -3962,14 +3418,7 @@ struttura \struct{mq\_attr}, la cui definizione 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct mq_attr {
-        long    mq_flags;       /* message queue flags                  */
-        long    mq_maxmsg;      /* maximum number of messages           */
-        long    mq_msgsize;     /* maximum message size                 */
-        long    mq_curmsgs;     /* number of messages currently queued  */
-};
-    \end{lstlisting}
+    \includestruct{listati/mq_attr.h}
   \end{minipage} 
   \normalsize
   \caption{La struttura \structd{mq\_attr}, contenente gli attributi di una
@@ -4317,34 +3766,178 @@ POSIX. L'interfaccia corrente 
 \label{sec:ipc_posix_shm}
 
 La memoria condivisa è l'unico degli oggetti di IPC POSIX già presente nel
-kernel ufficiale. Per poterla utilizzare occorre abilitare il filesystem
-\texttt{tmpfs}, uno speciale filesystem che mantiene tutti i suoi contenuti in
-memoria,\footnote{il filesystem \texttt{tmpfs} è diverso da un normale RAM
-  disk, anch'esso disponibile attraverso il filesystem \texttt{ramfs}, proprio
-  perché realizza una interfaccia utilizzabile anche per la memoria condivisa;
-  esso infatti non ha dimensione fissa, ed usa direttamente la cache interna
-  del kernel (viene usato anche per la SysV shared memory). In più i suoi
-  contenuti, essendo trattati direttamente dalla memoria
-  virtuale\index{memoria virtuale} e possono essere salvati sullo swap
-  automaticamente.} abilitando l'opzione \texttt{CONFIG\_TMPFS} in fase di
-compilazione del kernel, e montando il filesystem aggiungendo una riga tipo:
+kernel ufficiale; in realtà il supporto a questo tipo di oggetti è realizzato
+attraverso il filesystem \texttt{tmpfs}, uno speciale filesystem che mantiene
+tutti i suoi contenuti in memoria,\footnote{il filesystem \texttt{tmpfs} è
+  diverso da un normale RAM disk, anch'esso disponibile attraverso il
+  filesystem \texttt{ramfs}, proprio perché realizza una interfaccia
+  utilizzabile anche per la memoria condivisa; esso infatti non ha dimensione
+  fissa, ed usa direttamente la cache interna del kernel (che viene usata
+  anche per la shared memory in stile SysV). In più i suoi contenuti, essendo
+  trattati direttamente dalla memoria virtuale\index{memoria virtuale} possono
+  essere salvati sullo swap automaticamente.} che viene attivato abilitando
+l'opzione \texttt{CONFIG\_TMPFS} in fase di compilazione del kernel.
+
+
+Per potere utilizzare l'interfaccia POSIX per le code di messaggi le
+\acr{glibc}\footnote{le funzioni sono state introdotte con le glibc-2.2.}
+richiedono di compilare i programmi con l'opzione \code{-lrt}; inoltre è
+necessario che in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs};
+questo di norma viene eseguita aggiungendo una riga tipo:
 \begin{verbatim}
 tmpfs   /dev/shm        tmpfs   defaults        0      0
 \end{verbatim}
-ad \file{/etc/fstab}, oppure dove si preferisce con un comando del
-tipo:\footnote{il filesystem riconosce, oltre quelle mostrate, le opzioni
-  \texttt{uid} e \texttt{gid} che identificano rispettivamente utente e gruppo
-  cui assegnarne la titolarità, e \texttt{nr\_blocks} che permette di
-  specificarne la dimensione in blocchi, cioè in multipli di
-  \const{PAGECACHE\_SIZE}.}
+ad \file{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs}
+dove si vuole, per usarlo come RAM disk, con un comando del tipo:
 \begin{verbatim}
-mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs
+mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs
 \end{verbatim}
 
+Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
+\texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
+la titolarità, e \texttt{nr\_blocks} che permette di specificarne la
+dimensione in blocchi, cioè in multipli di \const{PAGECACHE\_SIZE} che in
+questo caso è l'unità di allocazione elementare.
+
+La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
+eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
+prototipo è:
+\begin{prototype}{mqueue.h}
+{int shm\_open(const char *name, int oflag, mode\_t mode)}
+
+Apre un segmento di memoria condivisa.
+  
+\bodydesc{La funzione restituisce un file descriptor positivo in caso di
+  successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
+  stessi valori riportati da \func{open}.}
+\end{prototype}
+
+La funzione apre un segmento di memoria condivisa identificato dal nome
+\param{name}. Come già spiegato in \secref{sec:ipc_posix_generic} questo nome
+può essere specificato in forma standard solo facendolo iniziare per \file{/}
+e senza ulteriori \file{/}, Linux supporta comunque nomi generici, che
+verranno intepretati prendendo come radice \file{/dev/shm}.\footnote{occorre
+  pertanto evitare di specificare qualcosa del tipo \file{/dev/shm/nome}
+  all'interno di \param{name}, perché questo comporta, da parte delle routine
+  di libereria, il tentativo di accedere a \file{/dev/shm/dev/shm/nome}.}
+
+La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
+possono essere specificati per \param{oflag}, che deve essere specificato come
+maschera binaria comprendente almeno uno dei due valori \const{O\_RDONLY} e
+\const{O\_RDWR}; i valori possibili per i vari bit sono quelli visti in
+\tabref{tab:file_open_flags} dei quali però \func{shm\_open} riconosce solo i
+seguenti:
+\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{O\_RDONLY}] Apre il file descriptor associato al segmento di
+  memoria condivisa per l'accesso in sola lettura.
+\item[\const{O\_RDWR}] Apre il file descriptor associato al segmento di
+  memoria condivisa per l'accesso in lettura e scrittura.
+\item[\const{O\_CREAT}] Necessario qualora si debba creare il segmento di
+  memoria condivisa se esso non esiste; in questo caso viene usato il valore
+  di \param{mode} per impostare i permessi, che devono essere compatibili con
+  le modalità con cui si è aperto il file.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+  chiamata a \func{shm\_open} se il segmento esiste già, altrimenti esegue la
+  creazione atomicamente.
+\item[\const{O\_TRUNC}] Se il segmento di memoria condivisa esiste già, ne
+  tronca le dimensioni a 0 byte.
+\end{basedescript}
+
+In caso di successo la funzione restituisce un file descriptor associato al
+segmento di memoria condiviso con le stesse modalità di
+\func{open}\footnote{in realtà, come accennato, \func{shm\_open} è un semplice
+  wrapper per \func{open}, usare direttamente quest'ultima avrebbe lo stesso
+  effetto.}  viste in \secref{sec:file_open}; in particolare viene impostato
+il flag \const{FD\_CLOEXEC}.  Chiamate effettuate da diversi processi usando
+lo stesso nome, restituiranno file descriptor associati allo stesso segmento
+(così come, nel caso di file di dati, essi sono associati allo stesso inode).
+In questo modo è possibile effettuare una chiamata ad \func{mmap} sul file
+descriptor restituito da \func{shm\_open} ed i processi vedranno lo stesso
+segmento di memoria condivisa.
+
+Quando il nome non esiste il segmento può essere creato specificando
+\const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file)
+lunghezza nulla. Dato che un segmento di lunghezza nulla è di scarsa utilità,
+per impostarne la dimensione si deve usare \func{ftruncate} (vedi
+\secref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}. Si
+tenga presente che una volta chiamata \func{mmap} si può chiudere il file
+descriptor (con \func{close}), senza che la mappatura ne risenta.
+
+
+Come per i file, quando si vuole effettivamente rimuovere segmento di memoria
+condivisa, occorre usare la funzione \funcd{shm\_unlink}, il cui prototipo è:
+\begin{prototype}{mqueue.h}
+{int shm\_unlink(const char *name)}
+
+Rimuove un segmento di memoria condivisa.
+  
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+  errore; nel quel caso \var{errno} assumerà gli stessi valori riportati da
+  \func{unlink}.}
+\end{prototype}
+
+La funzione è del tutto analoga ad \func{unlink}, e si limita a cancellare il
+nome del segmento da \file{/dev/shm}, senza nessun effetto né sui file
+descriptor precedentemente aperti con \func{shm\_open}, né sui segmenti già
+mappati in memoria; questi verranno cancellati automaticamente dal sistema
+solo con le rispettive chiamate a \func{close} e \func{munmap}.  Una volta
+eseguita questa funzione però, qualora si richieda l'apertura di un segmento
+con lo stesso nome, la chiamata a \func{shm\_open} fallirà, a meno di non aver
+usato \const{O\_CREAT}, in quest'ultimo caso comunque si otterrà un file
+descriptor che fa riferimento ad un segmento distinto da eventuali precedenti.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MemShared.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni di gestione dei segmenti di memoria
+    condivisa POSIX.}
+  \label{fig:ipc_posix_shmmem}
+\end{figure}
+
+Come esempio per l'uso di queste funzioni vediamo come è possibile riscrivere
+una interfaccia semplificata analoga a quella vista in
+\secref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il
+codice, riportato in \figref{fig:ipc_posix_shmmem}, è sempre contenuto nel
+file \file{SharedMem.c} dei sorgenti allegati.
+
+La prima funzione (\texttt{\small 1--24}) è \func{CreateShm} che, dato un nome
+nell'argomento \var{name} crea un nuovo segmento di memoria condivisa,
+accessibile in lettura e scrittura, e ne restituisce l'indirizzo. Anzitutto si
+definiscono (\texttt{\small 8}) i flag per la successiva (\texttt{\small 9})
+chiamata a \func{shm\_open}, che apre il segmento in lettura e scrittura
+(creandolo se non esiste, ed uscendo in caso contrario) assegnandogli sul
+filesystem i permessi specificati dall'argomento \var{perm}. In caso di errore
+(\texttt{\small 10--12}) si restituisce un puntatore nullo, altrimenti si
+prosegue impostando (\texttt{\small 14}) la dimensione del segmento con
+\func{ftruncate}. Di nuovo (\texttt{\small 15--16}) si esce immediatamente
+restituendo un puntatore nullo in caso di errore. Poi si passa (\texttt{\small
+  18}) a mappare in memoria il segmento con \func{mmap} specificando dei
+diritti di accesso corrispondenti alla modalità di apertura.  Di nuovo si
+restituisce (\texttt{\small 19--21}) un puntatore nullo in caso di errore,
+altrimenti si inizializza (\texttt{\small 22}) il contenuto del segmento al
+valore specificato dall'argomento \var{fill} con \func{memset}, e se ne
+restituisce (\texttt{\small 23}) l'indirizzo.
+
+La seconda funzione (\texttt{\small 25--40}) è \func{FindShm} che trova un
+segmento di memoria condiviso già esistente, restituendone l'indirizzo. In
+questo caso si apre (\texttt{\small 31}) il segmento con \func{shm\_open}
+richiedendo che il segmento sia già esistente, in caso di errore
+(\texttt{\small 31--33}) si ritorna immediatamente un puntatore nullo.
+Ottenuto il file descriptor del segmento lo si mappa (\texttt{\small 35}) in
+memoria con \func{mmap}, restituendo (\texttt{\small 36--38}) un puntatore
+nullo in caso di errore, o l'indirizzo (\texttt{\small 39}) dello stesso in
+caso di successo.
+
+La terza funzione (\texttt{\small 40--45}) è \func{RemoveShm}, e serve a
+cancellare un segmento di memoria condivisa. Dato che al contrario di quanto
+avveniva con i segmenti del SysV IPC gli oggetti allocati nel kernel vengono
+rilasciati automaticamente quando nessuna li usa più, tutto quello che c'è da
+fare (\texttt{\small 44}) in questo caso è chiamare \func{shm\_unlink},
+retituendo al chiamante il valore di ritorno.
 
- la memoria
-condivisa è trattata come un filesystem separato, con tutte le caratteristiche
-di un qualunque filesystem,
 
 
 %%% Local Variables: