Nouvi esempi finiti. E scritto un po' di roba
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 4 Jan 2003 17:24:30 +0000 (17:24 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 4 Jan 2003 17:24:30 +0000 (17:24 +0000)
filedir.tex
ipc.tex
sources/DirMonitor.c
sources/DirScan.c
sources/Gapil.h
sources/Makefile
sources/Mutex.c
sources/myls.c

index efdefa2..fe34045 100644 (file)
@@ -830,10 +830,12 @@ il nome del relativo campo; nel nostro caso sono definite le macro
 
 Per quanto riguarda il significato dei campi opzionali, il campo \var{d\_type}
 indica il tipo di file (fifo, directory, link simbolico, ecc.); i suoi
-possibili valori sono riportati in \tabref{tab:file_dtype_macro}; per la
-conversione da e verso l'analogo valore mantenuto dentro il campo
-\var{st\_mode} di \struct{stat} sono definite anche due macro di conversione
-\macro{IFTODT} e \macro{DTTOIF}:
+possibili valori\footnote{fino alla versione 2.1 delle \acr{glibc} questo
+  campo, pur presente nella struttura, non è implementato, e resta sempre al
+  valore \const{DT\_UNKNOWN}.}  sono riportati in
+\tabref{tab:file_dtype_macro}; per la conversione da e verso l'analogo valore
+mantenuto dentro il campo \var{st\_mode} di \struct{stat} sono definite anche
+due macro di conversione \macro{IFTODT} e \macro{DTTOIF}:
 \begin{functions}
   \funcdecl{int IFTODT(mode\_t MODE)} Converte il tipo di file dal formato di
   \var{st\_mode} a quello di \var{d\_type}.
@@ -846,9 +848,9 @@ Il campo \var{d\_off} contiene invece la posizione della voce successiva della
 directory, mentre il campo \var{d\_reclen} la lunghezza totale della voce
 letta. Con questi due campi diventa possibile, determinando la posizione delle
 varie voci, spostarsi all'interno dello stream usando la funzione
-\func{seekdir},\footnote{sia questa funzione, che la corrispondente
-  \func{telldir}, sono estensioni prese da BSD, non previste dallo standard
-  POSIX.} il cui prototipo è:
+\func{seekdir},\footnote{sia questa funzione che \func{telldir}, sono
+  estensioni prese da BSD, non previste dallo standard POSIX.} il cui
+prototipo è:
 \begin{prototype}{dirent.h}{void seekdir(DIR *dir, off\_t offset)}
   Cambia la posizione all'interno di un \textit{directory stream}.
 \end{prototype}
diff --git a/ipc.tex b/ipc.tex
index c7aa4fc..3151c40 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -2940,23 +2940,210 @@ sequenziale\footnote{come accennato in \secref{sec:ipc_sysv_mq} per la
 modalità predefinita.
 
 Un esempio classico di uso della memoria condivisa è quello del
-``\textit{monitor}'', in cui essa viene per scambiare informazioni fra un
-processo server che vi scrive dei dati di interesse generale che ha
-ottenuto, e tutti i processi client interessati agli stessi dati che così
-possono leggerli in maniera completamente asincrona.  Con questo schema di
-funzionamento da una parte si evita che ciascun processo client debba
-compiere l'operazione, potenzialmente onerosa, di ricavare e trattare i dati,
-e dall'altra si evita al processo server di dover gestire l'invio a tutti
-i client di tutti i dati (non potendo il server sapere quali di essi servono
-effettivamente al singolo client).
+``\textit{monitor}'', in cui viene per scambiare informazioni fra un processo
+server, che vi scrive dei dati di interesse generale che ha ottenuto, e i
+processi client interessati agli stessi dati che così possono leggerli in
+maniera completamente asincrona.  Con questo schema di funzionamento da una
+parte si evita che ciascun processo client debba compiere l'operazione,
+potenzialmente onerosa, di ricavare e trattare i dati, e dall'altra si evita
+al processo server di dover gestire l'invio a tutti i client di tutti i dati
+(non potendo il server sapere quali di essi servono effettivamente al singolo
+client).
 
 Nel nostro caso implementeremo un ``\textsl{monitor}'' di una directory: un
 processo si incaricherà di tenere sotto controllo alcuni parametri relativi ad
-una directory (il numero dei file contenuti, la dimensione totale, ecc.) che
-saranno salvati in un segmento di memoria condivisa cui altri processi
-potranno accedere per ricavare la parte di informazione che interessa.
+una directory (il numero dei file contenuti, la dimensione totale, quante
+directory, link simbolici, file normali, ecc.) che saranno salvati in un
+segmento di memoria condivisa cui altri processi potranno accedere per
+ricavare la parte di informazione che interessa.
+
+In \figref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del
+corpo del programma server, insieme alle definizioni delle altre funzioni
+usate nel programma e delle variabili globali, omettendo tutto quello che
+riguarda la gestione delle opzioni e la stampa delle istruzioni di uso a
+video; al solito il codice completo si trova con i sorgenti allegati nel file
+\file{DirMonitor.c}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+/* computation function for DirScan */
+int ComputeValues(struct dirent * direntry);
+void HandSIGTERM(int signo);
+/* 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;
+};
+struct DirProp *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();
+    }
+    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
+    Signal(SIGINT, HandSIGTERM);
+    Signal(SIGQUIT, HandSIGTERM);
+    /* create needed IPC objects */
+    key = ftok("./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");
+    }
+    if ((mutex = MutexCreate(key)) == -1) {                   /* get a Mutex */
+        perror("Cannot create mutex");
+        exit(1);
+    }
+    /* main loop, monitor directory properties each 10 sec */
+    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}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice della funzione principale del programma \file{DirMonitor.c}.}
+  \label{fig:ipc_dirmonitor_main}
+\end{figure}
+
+Il programma usa delle variabili globali (\texttt{\small 4--18}) per mantenere
+i valori relativi agli oggetti usati per la comunicazione inter-processo; si è
+definita inoltre una apposita struttura \struct{DirProp} che contiene i dati
+relativi alle proprietà che si vogliono mantenere nella memoria condivisa, per
+l'accesso da parte dei client.
+
+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
+  25--28}) che sia stato specificato un parametro (il nome della directory da
+tenere sotto controllo) senza il quale esce immediatamente con un messaggio di
+errore.
+
+Il passo successivo (\texttt{\small 29--31}) è quello di installare i gestori
+per i segnali di terminazione, infatti, visto che il programma è progettato
+come server, non è prevista una conclusione esplicita nel corpo principale,
+per cui, per gestire l'uscita, si è fatto uso di questi ultimi.
+
+Si può poi passare a creare (\texttt{\small 32--45}) gli oggetti di
+intercomunicazione necessari. Si ricava (\texttt{\small 33}) una chiave usando
+il nome del programma, con questa si ottiene (\texttt{\small 34--38}) un
+segmento di memoria condivisa \var{shmid} (uscendo in caso di errore), che si
+aggancia (\texttt{\small 39--41}) al processo all'indirizzo \var{shmptr}; sarà
+attraverso questo puntatore che potremo accedere alla memoria condivisa, che
+sarà vista nella forma data da \struct{DirProp}. Infine con la stessa chiave
+si crea (\texttt{\small 42--45}) anche un mutex, che utilizzaremo per regolare
+l'accesso alla memoria condivisa.
+
+Una volta completata l'inizializzazione e la creazione degli oggetti di
+intercomunicazione il programma eseguirà indefinitamente (\texttt{\small
+  46--53}) il ciclo principale: si inizia bloccando il mutex (\texttt{\small
+  48}) per poter accedere alla memoria condivisa (la funzione si bloccherà
+automaticamente se qualche client sta leggendo), poi si cancellano
+(\texttt{\small 49}) i valori precedentemente memorizzati, e si esegue
+(\texttt{\small 50}) un nuovo calcolo degli stessi; infine si sblocca il mutex
+(\texttt{\small 51}), e si attende (\texttt{\small 52}) per il periodo di
+tempo specificato a riga di comando con l'opzione \code{-p}.
 
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+...
+/*
+ * Routine to print file name and size 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}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice delle funzione ausiliarie usate da \file{DirMonitor.c}.}
+  \label{fig:ipc_dirmonitor_sub}
+\end{figure}
+
+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
+effettuare la scansione delle voci della directory, chiamando per ciascuna di
+esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari.
+
+Il codice di quest'ultima è riportato in \figref{fig:ipc_dirmonitor_sub}. Come
+si vede la funzione (\texttt{\small 5--19}) è molto semplice e si limita a
+chiamare (\texttt{\small 8}) la funzione \func{stat} sul file indicato da
+ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari
+contatori.
+
+Dato che la funzione è chiamata da \func{DirScan}, si è all'interno del ciclo
+principale del programma, con un mutex acquisito, perciò non è necessario
+effettuare nessun controllo e si può accedere direttamente alla memoria
+condivisa usando \var{shmptr} riempiendo i campi della struttura
+\struct{DirProp}; così prima (\texttt{\small 9--10}) si sommano le dimensioni
+dei file ed il loro numero, poi utilizzando le macro di
+\tabref{tab:file_type_macro}, si contano (\texttt{\small 11--17}) quanti ce ne
+sono per ciascun tipo.
+
+In \figref{fig:ipc_dirmonitor_sub} è riportato inoltre (\texttt{\small
+  23--35}) il codice del gestore di segnali usato per terminare il programma,
+che si incarica di cancellare tutti gli oggetti non più necessari. 
+
+Anzitutto (\texttt{\small 24}) si acquisisce il mutex per evitare di operare
+mentre un client sta ancora leggendo i dati, dopo di che si distacca
+(\texttt{\small 25--28}) il segmento e lo si cancella (\texttt{\small
+  29--32}). Infine (\texttt{\small 33}) si rimuove il mutex e si esce.
 
 
 %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
@@ -2981,9 +3168,9 @@ potranno accedere per ricavare la parte di informazione che interessa.
 Come abbiamo detto in \secref{sec:ipc_sysv_generic}, e ripreso nella
 descrizione dei singoli oggetti che ne fan parte, il \textit{SysV IPC}
 presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
-  capitolo 14.}  Stevens ne effettua una accurata analisi (alcuni dei
-concetti sono già stati accennati in precedenza) ed elenca alcune possibili
-tecniche alternative, che vogliamo riprendere in questa sezione.
+  capitolo 14.}  Stevens ne effettua una accurata analisi (alcuni dei concetti
+sono già stati accennati in precedenza) ed elenca alcune possibili tecniche
+alternative, che vogliamo riprendere in questa sezione.
 
 
 \subsection{Alternative alle code di messaggi}
@@ -3064,7 +3251,6 @@ int UnlockFile(const char* path_name)
 {
     return unlink(path_name);
 }
-
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
@@ -3101,6 +3287,7 @@ pi
 accedere alla seriale si limita a segnalare che la risorsa non è
 disponibile.\index{file!di lock|)}
 
+
 \subsection{La sincronizzazione con il \textit{file locking}}
 \label{sec:ipc_lock_file}
 
index c8fad95..7e6b288 100644 (file)
@@ -25,7 +25,7 @@
  *
  * Author: S. Piccardi Jan. 2003
  *
- * $Id: DirMonitor.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ * $Id: DirMonitor.c,v 1.2 2003/01/04 17:24:30 piccardi Exp $
  *
  *****************************************************************************/
 #include <sys/types.h>
 #include <unistd.h>
 
 #include "Gapil.h"
+#include "macros.h"
 
 /* Help printing routine */
 void usage(void);
 /* computation function for DirScan */
 int ComputeValues(struct dirent * direntry);
+void HandSIGTERM(int signo);
 
-/* global variable for shared memory segment */
-int shmid;                                       /* Shared memory identifier */
+/* 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;
+};
+struct DirProp *shmptr;
+int shmid; 
+int mutex;
 
 int main(int argc, char *argv[]) 
 {
-    int i;
-    int mutex;
+    int i, pause = 10;
+    key_t key;
     /*
      * Input section: decode command line parameters 
      * Use getopt function
      */
     opterr = 0;         /* don't want writing to stderr */
-    while ( (i = getopt(argc, argv, "hs:l:wrbf")) != -1) {
+    while ( (i = getopt(argc, argv, "hp:")) != -1) {
        switch (i) {
        /* 
         * Handling options 
         */ 
-       case 'h':                                            /* help option */
+       case 'p':                                     /* set pause (in sec.) */
+           pause = strtol(optarg, NULL, 10);
+           break;
+       case 'h':                                             /* help option */
            printf("Wrong -h option use\n");
            usage();
            return -1;
@@ -81,18 +99,48 @@ int main(int argc, char *argv[])
        printf("Wrong number of arguments %d\n", argc - optind);
         usage();
     }
-    
-    DirScan(argv[1], ComputeValues);
-    exit(0);
+    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
+    Signal(SIGINT, HandSIGTERM);
+    Signal(SIGQUIT, HandSIGTERM);
+    /* create needed IPC objects */
+    key = ftok("./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");
+    }
+    if ((mutex = MutexCreate(key)) == -1) {                   /* get a Mutex */
+       perror("Cannot create mutex");
+       exit(1);
+    }
+    /* main loop, monitor directory properties each 10 sec */
+    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 */
+    }
 }
 /*
  * Routine to print file name and size inside DirScan
  */
-int do_ls(struct dirent * direntry) 
+int ComputeValues(struct dirent * direntry) 
 {
     struct stat data;
     stat(direntry->d_name, &data);                          /* get stat data */
-    printf("File: %s \t size: %d\n", direntry->d_name, data.st_size);
+    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;
 }
 /*
@@ -101,7 +149,25 @@ int do_ls(struct dirent * direntry)
 void usage(void) {
     printf("Program myls: list file in a directory \n");
     printf("Usage:\n");
-    printf("  myls [-h] dirname \n");
+    printf("  DirMonitor [-h] [-p sec] dirname \n");
     printf("  -h          print this help\n");
+    printf("  -p sec      set watch interval to sec seconds \n");
     exit(1);
 }
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+    MutexLock(mutex);
+    debug("Terminated by %s\n", strsignal(signo));
+    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);
+}
index 38fb555..4b3f061 100644 (file)
  *
  * Author: S. Piccardi Jan. 2003
  *
- * $Id: DirScan.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ * $Id: DirScan.c,v 1.2 2003/01/04 17:24:30 piccardi Exp $
  *
  *****************************************************************************/
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>        /* directory */
 #include <stdlib.h>        /* C standard library */
+#include <stdio.h>
+#include <unistd.h>
 
 /*
  * Function DirScan: 
index 67dabab..84e7211 100644 (file)
@@ -23,7 +23,7 @@
  *
  * Author: S. Piccardi
  *
- * $Id: Gapil.h,v 1.3 2002/12/05 23:38:22 piccardi Exp $
+ * $Id: Gapil.h,v 1.4 2003/01/04 17:24:30 piccardi Exp $
  *
  *****************************************************************************/
 #include <sys/sem.h>                           /* IPC semaphore declarations */
@@ -33,6 +33,7 @@
 #include <unistd.h>                               /* unix standard functions */
 #include <fcntl.h>                          /* file control (lock) functions */
 #include <signal.h>                          /* signal handling declarations */
+#include <dirent.h>                              /* directory scan functions */
 /*
  * Definition of semun struct; used to implement a MutexXXXX API To
  * create a Mutex use an underlaying semaphore and init it; we put
@@ -63,6 +64,8 @@ inline int MutexRead(int sem_id);
 inline int MutexLock(int sem_id);
 /* Function MutexUnlock: to unlock a mutex/semaphore. See Mutex.c */
 inline int MutexUnlock(int sem_id);
+/* Function MutexRemove: remove the mutex/semphore. See Mutex.c */
+inline int MutexRemove(int sem_id);
 /* Function LockMutex: acquire a mutex (using file locking). See Mutex.c */
 inline int LockFile(const char* path_name);
 /* Function UnlockMutex: release a mutex (using file locking). See Mutex.c */
@@ -88,3 +91,8 @@ void HandSigCHLD(int sig);
 ssize_t SockRead(int fd, void *buf, size_t count);
 /* Function SockWrite: to read from a socket. See SockWrite.c */
 ssize_t SockWrite(int fd, const void *buf, size_t count);
+/*
+ * File miscellaneous
+ */
+/* Function DirScan: simple scan for a directory */
+int DirScan(char * dirname, int(*compute)(struct dirent *));
index 1311095..2d33fbb 100644 (file)
@@ -8,21 +8,27 @@ CFLAGJ= -L./ -lgapil
 
 LIB = libgapil.so
 
-OBJ = SockRead.o SockWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o
+OBJ = SockRead.o SockWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o DirScan.o
 
 FINAL = forktest errcode echo echod daytimed iterdaytimed daytime testfopen \
-       testren fortune fortuned mqfortune mqfortuned flock myls
+       testren fortune fortuned mqfortune mqfortuned flock myls dirmonitor \
+       readmon 
 
 $(LIB): $(OBJ)
        gcc -shared $^ -o $@
 
-
 $(OBJ): Gapil.h
 
 all: $(FINAL) $(LIB)
 
-myls: myls.c DirScan.c 
-       $(CC)  $^ -o $@
+dirmonitor: DirMonitor.c
+       $(CC) $(CFLAGJ) $^ -o $@
+
+readmon: ReadMonitor.c
+       $(CC) $(CFLAGJ) $^ -o $@
+
+myls: myls.c  
+       $(CC) $(CFLAGJ) $^ -o $@
 
 flock: Flock.c
        $(CC) $(CFLAGJ) $^ -o $@ 
index d009998..076c593 100644 (file)
@@ -22,7 +22,7 @@
  *
  * Author: S. Piccardi Dec. 2002
  *
- * $Id: Mutex.c,v 1.3 2002/12/05 23:38:22 piccardi Exp $
+ * $Id: Mutex.c,v 1.4 2003/01/04 17:24:30 piccardi Exp $
  *
  *****************************************************************************/
 #include <sys/sem.h>     /* IPC semaphore declarations */
@@ -65,7 +65,7 @@ int MutexCreate(key_t ipc_key)
  */
 int MutexFind(key_t ipc_key) 
 {
-    return semget(ipc_key,1,0);
+    return semget(ipc_key, 1, 0);
 }
 /*
  * Function MutexRead: read the current value of the mutex/semaphore
@@ -109,6 +109,16 @@ int MutexUnlock(int sem_id)
 {
     return semop(sem_id, &sem_ulock, 1);
 }
+/*
+ * Function MutexRemove: remove a mutex/semaphore
+ *
+ * Input:  a semaphore id #
+ * Return: return code of semctl
+ */
+int MutexRemove(int sem_id) 
+{
+    return semctl(sem_id, 0, IPC_RMID);
+}
 /***************************************************************************** 
  *
  * File locking mutex 
index bd22144..bc2e1a9 100644 (file)
@@ -22,7 +22,7 @@
  *
  * Author: S. Piccardi Jan. 2003
  *
- * $Id: myls.c,v 1.1 2003/01/03 23:16:05 piccardi Exp $
+ * $Id: myls.c,v 1.2 2003/01/04 17:24:30 piccardi Exp $
  *
  *****************************************************************************/
 #include <sys/types.h>
@@ -31,6 +31,7 @@
 #include <stdlib.h>        /* C standard library */
 #include <unistd.h>
 
+#include "Gapil.h"
 /*
  * Program myls
  *