Aggiunte alla shared memory
authorSimone Piccardi <piccardi@gnulinux.it>
Thu, 5 Dec 2002 00:58:49 +0000 (00:58 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Thu, 5 Dec 2002 00:58:49 +0000 (00:58 +0000)
ipc.tex
sources/Makefile

diff --git a/ipc.tex b/ipc.tex
index 783bfee98646f71c1683a4f133c0768828d19dd9..2975185b6e64412ae225c8e6cdff4a83ab8cbb71 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1963,7 +1963,7 @@ soffrono di altri due, ben pi
 Il primo difetto è che non esiste una funzione che permetta di creare ed
 inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme
 dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si
 Il primo difetto è che non esiste una funzione che permetta di creare ed
 inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme
 dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si
-perde così ogni possibilità di eseguire atomicamente questa operazione.
+perde così ogni possibilità di eseguire l'operazione atomicamente.
 
 Il secondo difetto deriva dalla caratteristica generale degli oggetti del
 \textit{SysV IPC} di essere risorse globali di sistema, che non vengono
 
 Il secondo difetto deriva dalla caratteristica generale degli oggetti del
 \textit{SysV IPC} di essere risorse globali di sistema, che non vengono
@@ -2121,12 +2121,6 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
 \param{semid} o sul singolo semaforo di un insieme, specificato da
 \param{semnum}. 
 
 \param{semid} o sul singolo semaforo di un insieme, specificato da
 \param{semnum}. 
 
-Qualora la funzione operi con quattro argomenti \param{arg} è
-un argomento generico, che conterrà un dato diverso a seconda dell'azione
-richiesta; per unificare l'argomento esso deve essere passato come una
-\var{union semun}, la cui definizione, con i possibili valori che può
-assumere, è riportata in \figref{fig:ipc_semun}.
-
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -2146,6 +2140,12 @@ union semun {
   \label{fig:ipc_semun}
 \end{figure}
 
   \label{fig:ipc_semun}
 \end{figure}
 
+Qualora la funzione operi con quattro argomenti \param{arg} è
+un argomento generico, che conterrà un dato diverso a seconda dell'azione
+richiesta; per unificare l'argomento esso deve essere passato come una
+\var{union semun}, la cui definizione, con i possibili valori che può
+assumere, è riportata in \figref{fig:ipc_semun}.
+
 Come già accennato sia il comportamento della funzione che il numero di
 parametri con cui deve essere invocata, dipendono dal valore dell'argomento
 \param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
 Come già accennato sia il comportamento della funzione che il numero di
 parametri con cui deve essere invocata, dipendono dal valore dell'argomento
 \param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
@@ -2464,7 +2464,7 @@ nullo per segnalarne l'indisponibilit
 /*
  * Function MutexCreate: create a mutex/semaphore
  */
 /*
  * Function MutexCreate: create a mutex/semaphore
  */
-inline int MutexCreate(key_t ipc_key) 
+int MutexCreate(key_t ipc_key) 
 {
     const union semun semunion={1};             /* semaphore union structure */
     int sem_id, ret;
 {
     const union semun semunion={1};             /* semaphore union structure */
     int sem_id, ret;
@@ -2481,14 +2481,14 @@ inline int MutexCreate(key_t ipc_key)
 /*
  * Function MutexFind: get the semaphore/mutex Id given the IPC key value
  */
 /*
  * Function MutexFind: get the semaphore/mutex Id given the IPC key value
  */
-inline int MutexFind(key_t ipc_key) 
+int MutexFind(key_t ipc_key) 
 {
     return semget(ipc_key,1,0);
 }
 /*
  * Function MutexRead: read the current value of the mutex/semaphore
  */
 {
     return semget(ipc_key,1,0);
 }
 /*
  * Function MutexRead: read the current value of the mutex/semaphore
  */
-inline int MutexRead(int sem_id) 
+int MutexRead(int sem_id) 
 {
     return semctl(sem_id, 0, GETVAL);
 }
 {
     return semctl(sem_id, 0, GETVAL);
 }
@@ -2502,18 +2502,18 @@ struct sembuf sem_lock={                                /* to lock semaphore */
 struct sembuf sem_ulock={                             /* to unlock semaphore */
     0,                                   /* semaphore number (only one so 0) */
     1,                                  /* operation (1 to release resource) */
 struct sembuf sem_ulock={                             /* to unlock semaphore */
     0,                                   /* semaphore number (only one so 0) */
     1,                                  /* operation (1 to release resource) */
-    SEM_UNO};                                       /* flag (in this case 0) */
+    SEM_UNDO};                                      /* flag (in this case 0) */
 /*
  * Function MutexLock: to lock a mutex/semaphore
  */
 /*
  * Function MutexLock: to lock a mutex/semaphore
  */
-inline int MutexLock(int sem_id) 
+int MutexLock(int sem_id) 
 {
     return semop(sem_id, &sem_lock, 1);
 }
 /*
  * Function MutexUnlock: to unlock a mutex/semaphore
  */
 {
     return semop(sem_id, &sem_lock, 1);
 }
 /*
  * Function MutexUnlock: to unlock a mutex/semaphore
  */
-inline int MutexUnlock(int sem_id) 
+int MutexUnlock(int sem_id) 
 {
     return semop(sem_id, &sem_ulock, 1);
 }
 {
     return semop(sem_id, &sem_ulock, 1);
 }
@@ -2561,21 +2561,21 @@ il mutex. Entrambe fanno da wrapper per \func{semop}, utilizzando le due
 strutture \var{sem\_lock} e \var{sem\_unlock} definite in precedenza
 (\texttt{\small 32--42}). Si noti come per queste ultime si sia fatto uso
 dell'opzione \macro{SEM\_UNDO} per evitare che il semaforo resti bloccato in
 strutture \var{sem\_lock} e \var{sem\_unlock} definite in precedenza
 (\texttt{\small 32--42}). Si noti come per queste ultime si sia fatto uso
 dell'opzione \macro{SEM\_UNDO} per evitare che il semaforo resti bloccato in
-caso di terminazione imprevista del processo. Si noti infine come, essendo
-tutte le funzioni riportate in \figref{fig:ipc_mutex_create} estremamente
-semplici, se si sono definite tutte come \ctyp{inline}.\footnote{la direttiva
-  \func{inline} viene usata per dire al compilatore di non trattare la
-  funzione cui essa fa riferimento come una funzione, ma di inserire il codice
-  direttamente nel testo del programma.  Anche se i compilatori più moderni
-  sono in grado di effettuare da soli queste manipolazioni (impostando le
-  opportune ottimizzazioni) questa è una tecnica usata per migliorare le
-  prestazioni per le funzioni piccole ed usate di frequente, in tal caso
-  infatti le istruzioni per creare un nuovo frame nello stack per chiamare la
-  funzione costituirebbero una parte rilevante del codice, appesantendo
-  inutilmente il programma. Originariamente questa era fatto utilizzando delle
-  macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio
-  degli argomenti (si veda ad esempio \cite{PratC} che in questo modo possono
-  essere evitati.}
+caso di terminazione imprevista del processo.%%  Si noti infine come, essendo
+%% tutte le funzioni riportate in \figref{fig:ipc_mutex_create} estremamente
+%% semplici, se si sono definite tutte come \ctyp{inline}.\footnote{la direttiva
+%%   \func{inline} viene usata per dire al compilatore di non trattare la
+%%   funzione cui essa fa riferimento come una funzione, ma di inserire il codice
+%%   direttamente nel testo del programma.  Anche se i compilatori più moderni
+%%   sono in grado di effettuare da soli queste manipolazioni (impostando le
+%%   opportune ottimizzazioni) questa è una tecnica usata per migliorare le
+%%   prestazioni per le funzioni piccole ed usate di frequente, in tal caso
+%%   infatti le istruzioni per creare un nuovo frame nello stack per chiamare la
+%%   funzione costituirebbero una parte rilevante del codice, appesantendo
+%%   inutilmente il programma. Originariamente questa era fatto utilizzando delle
+%%   macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio
+%%   degli argomenti (si veda ad esempio \cite{PratC} che in questo modo possono
+%%   essere evitati.}
 
 
 Chiamare \func{MutexLock} decrementa il valore del semaforo: se questo è
 
 
 Chiamare \func{MutexLock} decrementa il valore del semaforo: se questo è
@@ -2594,8 +2594,6 @@ analoga senza questo problemi usando il file locking.
 
 
 
 
 
 
-
-
 \subsection{Memoria condivisa}
 \label{sec:ipc_sysv_shm}
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_sysv_shm}
 
@@ -2648,7 +2646,7 @@ quest'ultimo non acceda al segmento di memoria condivisa prima che il primo
 non abbia completato le operazioni di scrittura, inoltre nel corso di una
 lettura si deve essere sicuri che i dati restano coerenti e non vengono
 sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
 non abbia completato le operazioni di scrittura, inoltre nel corso di una
 lettura si deve essere sicuri che i dati restano coerenti e non vengono
 sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
-altro processo; per questo in genere la memoria condivisa viene sempre
+altro processo. Per questo in genere la memoria condivisa viene sempre
 utilizzata in abbinamento ad un meccanismo di sincronizzazione, il che, di
 norma, significa insieme a dei semafori.
 
 utilizzata in abbinamento ad un meccanismo di sincronizzazione, il che, di
 norma, significa insieme a dei semafori.
 
@@ -2687,7 +2685,7 @@ invece:
   inizializzato al valore di \param{size}.
 \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
   segmento, viene inizializzato al tempo corrente.
   inizializzato al valore di \param{size}.
 \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
   segmento, viene inizializzato al tempo corrente.
-\item i campi \var{shm\_atime} e \var{shm\_atime}, che esprimono
+\item i campi \var{shm\_atime} e \var{shm\_dtime}, che esprimono
   rispettivamente il tempo dell'ultima volta che il segmento è stato
   agganciato o sganciato da un processo, vengono inizializzati a zero.
 \item il campo \var{shm\_lpid}, che esprime il \acr{pid} del processo che ha
   rispettivamente il tempo dell'ultima volta che il segmento è stato
   agganciato o sganciato da un processo, vengono inizializzati a zero.
 \item il campo \var{shm\_lpid}, che esprime il \acr{pid} del processo che ha
@@ -2699,11 +2697,14 @@ invece:
 \end{itemize*}
 
 Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
 \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, i cui valori, riportati in
-\tabref{tab:ipc_shm_limits} sono associati ad altrettante costanti.  Alcuni di
-questi limiti sono al solito accessibili e modificabili attraverso
+di memoria condivisa esistono una serie di limiti imposti dal sistema.  Alcuni
+di questi limiti sono al solito accessibili e modificabili attraverso
 \func{sysctl} o scrivendo direttamente nei rispettivi file di
 \func{sysctl} o scrivendo direttamente nei rispettivi file di
-\file{/proc/sys/kernel/}.
+\file{/proc/sys/kernel/}. In \tabref{tab:ipc_shm_limits} si sono riportate le
+costanti simboliche associate a ciascuno di essi, il loro significato, i
+valori preimpostati, e, quando presente, il file in \file{/proc/sys/kernel/}
+che permettono di cambiarne il valore. 
+
 
 \begin{table}[htb]
   \footnotesize
 
 \begin{table}[htb]
   \footnotesize
@@ -2714,15 +2715,25 @@ questi limiti sono al solito accessibili e modificabili attraverso
     & \textbf{Significato} \\
     \hline
     \hline
     & \textbf{Significato} \\
     \hline
     \hline
-    \macro{SHMALL}&0x200000&\file{shmall}& Numero massimo di pagine che 
+    \macro{SHMALL}& 0x200000&\file{shmall}& Numero massimo di pagine che 
                                        possono essere usate per i segmenti di
                                        memoria condivisa. \\
     \macro{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento 
                                        possono essere usate per i segmenti di
                                        memoria condivisa. \\
     \macro{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento 
-                                       di memoria condivisa.\\
-    \macro{SHMMNI}&4096&\file{msgmni}& Numero massimo di segmenti di memoria
-                                       condivisa presenti nel kernel.\\
-    \macro{SHMMIN}&   1& ---         & Dimensione minima di un segmento di
-                                       memoria condivisa. \\
+                                            di memoria condivisa.\\
+    \macro{SHMMNI}&     4096&\file{msgmni}& Numero massimo di segmenti di 
+                                            memoria condivisa presenti nel
+                                            kernel.\\ 
+    \macro{SHMMIN}&        1& ---         & Dimensione minima di un segmento di
+                                            memoria condivisa. \\
+    \macro{SHMLBA}&\macro{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni
+                                            minime di un segmento (deve essere
+                                            allineato alle dimensioni di una
+                                            pagina di memoria). \\
+    \macro{SHMSEG}&   ---   &     ---     & Numero massimo di segmenti di
+                                            memoria condivisa 
+                                            per ciascun processo.\\
+
+
     \hline
   \end{tabular}
   \caption{Valori delle costanti associate ai limiti dei segmenti di memoria
     \hline
   \end{tabular}
   \caption{Valori delle costanti associate ai limiti dei segmenti di memoria
@@ -2767,18 +2778,20 @@ attraverso l'argomento \param{cmd}, i valori possibili sono i seguenti:
 \item[\macro{IPC\_RMID}] Marca il segmento di memoria condivisa per la
   rimozione, questo verrà cancellato effettivamente solo quando l'ultimo
   processo ad esso agganciato si sarà staccato. Questo comando può essere
 \item[\macro{IPC\_RMID}] Marca il segmento di memoria condivisa per la
   rimozione, questo verrà cancellato effettivamente solo quando l'ultimo
   processo ad esso agganciato si sarà staccato. Questo comando può essere
-  eseguito solo da un processo con userid effettivo, corrispondente al
-  creatore o al proprietario della coda, o all'amministratore.
+  eseguito solo da un processo con userid effettivo corrispondente o al
+  creatore della coda, o al proprietario della coda, o all'amministratore.
 \item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
   del segmento.  Per modificare i valori di \var{shm\_perm.mode},
   \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
   il creatore della coda, oppure l'amministratore. Compiuta l'operazione
   aggiorna anche il valore del campo \var{shm\_ctime}.
 \item[\macro{SHM\_LOCK}] Abilita il \textit{memory locking}\index{memory
 \item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
   del segmento.  Per modificare i valori di \var{shm\_perm.mode},
   \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
   il creatore della coda, oppure l'amministratore. Compiuta l'operazione
   aggiorna anche il valore del campo \var{shm\_ctime}.
 \item[\macro{SHM\_LOCK}] Abilita il \textit{memory locking}\index{memory
-    locking} (vedi \secref{sec:proc_mem_lock}) sul segmento di memoria
+    locking}\footnote{impedisce cioè che la memoria usata per il segmento
+    venga salvata su disco dal meccanismo della memoria virtuale; si ricordi
+    quanto trattato in \secref{sec:proc_mem_lock}.} sul segmento di memoria
   condivisa. Solo l'amministratore può utilizzare questo comando.
   condivisa. Solo l'amministratore può utilizzare questo comando.
-\item[\macro{SHM\_UNLOCK}] Disabilita il \textit{memory locking}. Solo
-  l'amministratore può utilizzare questo comando.
+\item[\macro{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento
+  di memoria condivisa. Solo l'amministratore può utilizzare questo comando.
 \end{basedescript}
 i primi tre comandi sono gli stessi già visti anche per le code ed i semafori,
 gli ultimi due sono delle estensioni previste da Linux. 
 \end{basedescript}
 i primi tre comandi sono gli stessi già visti anche per le code ed i semafori,
 gli ultimi due sono delle estensioni previste da Linux. 
@@ -2811,8 +2824,10 @@ La funzione inserisce un segmento di memoria condivisa all'interno dello
 spazio di indirizzi del processo, in modo che questo possa accedervi
 direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
 \figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
 spazio di indirizzi del processo, in modo che questo possa accedervi
 direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
 \figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
-ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). Si
-tenga presente che la funzione ha successo anche se il segmento è stato
+ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). In
+particolare l'indirizzo finale del segmento dati (quello impostato da
+\func{brk}, vedi \secref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga
+presente infine che la funzione ha successo anche se il segmento è stato
 marcato per la cancellazione.
 
 \begin{figure}[htb]
 marcato per la cancellazione.
 
 \begin{figure}[htb]
@@ -2834,7 +2849,13 @@ memoria libera (questo 
 Altrimenti il kernel aggancia il segmento all'indirizzo specificato da
 \param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il
 limite di una pagina, cioè se è un multiplo esatto del parametro di sistema
 Altrimenti il kernel aggancia il segmento all'indirizzo specificato da
 \param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il
 limite di una pagina, cioè se è un multiplo esatto del parametro di sistema
-\macro{SHMLBA}, che in Linux è sempre uguale \macro{PAGE\_SIZE}.
+\macro{SHMLBA}, che in Linux è sempre uguale \macro{PAGE\_SIZE}. 
+
+Si tenga presente però che quando si usa \macro{NULL} come valore di
+\param{shmaddr}, l'indirizzo restituito da \func{shmat} può cambiare da
+processo a processo; pertanto se nell'area di memoria condivisa si salvano
+anche degli indirizzi, si deve avere cura di usare valori relativi (in genere
+riferiti all'indirizzo di partenza del segmento).
 
 L'argomento \param{shmflg} permette di cambiare il comportamento della
 funzione; esso va specificato come maschera binaria, i bit utilizzati sono
 
 L'argomento \param{shmflg} permette di cambiare il comportamento della
 funzione; esso va specificato come maschera binaria, i bit utilizzati sono
@@ -2845,15 +2866,16 @@ solo due e sono identificati dalle costanti \macro{SHM\_RND} e
 un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
 agganciato, ma al più vicino multiplo di \macro{SHMLBA} (il nome della
 costante sta infatti per \textit{rounded}, e serve per specificare un
 un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
 agganciato, ma al più vicino multiplo di \macro{SHMLBA} (il nome della
 costante sta infatti per \textit{rounded}, e serve per specificare un
-indirizzo come arrotondamento).
+indirizzo come arrotondamento, in Linux è equivalente a \macro{PAGE\_SIZE}).
 
 
-Il secondo bit permette di agganciare il segmento in sola lettura (si ricordi
-che anche le pagine di memoria hanno dei permessi), in tal caso un tentativo
-di scrivere sul segmento comporterà una violazione di accesso con l'emissione
-di un segnale di \macro{SIGSEGV}. Il comportamento usuale di \func{shmat} è
-quello di agganciare il segmento con l'accesso in lettura e scrittura (ed il
-processo deve aver questi permessi in \var{shm\_perm}), non è prevista la
-possibilità di agganciare un segmento in sola scrittura.
+L'uso di \macro{SHM\_RDONLY} permette di agganciare il segmento in sola
+lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
+caso un tentativo di scrivere sul segmento comporterà una violazione di
+accesso con l'emissione di un segnale di \macro{SIGSEGV}. Il comportamento
+usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in
+lettura e scrittura (ed il processo deve aver questi permessi in
+\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in
+sola scrittura.
 
 In caso di successo la funzione aggiorna anche i seguenti campi di
 \var{shmid\_ds}:
 
 In caso di successo la funzione aggiorna anche i seguenti campi di
 \var{shmid\_ds}:
@@ -2875,7 +2897,6 @@ diverso, tutti i segmenti agganciati al processo originario vengono
 automaticamente sganciati. Lo stesso avviene all'uscita del processo
 attraverso una \func{exit}.
 
 automaticamente sganciati. Lo stesso avviene all'uscita del processo
 attraverso una \func{exit}.
 
-
 Una volta che un segmento di memoria condivisa non serve più, si può
 sganciarlo esplicitamente dal processo usando l'altra funzione
 dell'interfaccia, \func{shmdt}, il cui prototipo è:
 Una volta che un segmento di memoria condivisa non serve più, si può
 sganciarlo esplicitamente dal processo usando l'altra funzione
 dell'interfaccia, \func{shmdt}, il cui prototipo è:
@@ -2897,6 +2918,20 @@ memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr}
 restituito dalla precedente chiamata a \func{shmat} con il quale era stato
 agganciato al processo.
 
 restituito dalla precedente chiamata a \func{shmat} con il quale era stato
 agganciato al processo.
 
+In caso di successo la funzione aggiorna anche i seguenti campi di
+\var{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_dtime} dell'ultima operazione di sganciamento viene
+  impostato al tempo corrente.
+\item il \acr{pid} \var{shm\_lpid} dell'ultimo processo che ha operato sul
+  segmento viene impostato a quello del processo corrente.
+\item il numero \var{shm\_nattch} di processi agganciati al segmento viene
+  decrementato di uno.
+\end{itemize*} 
+inoltre la regione di indirizzi usata per il segmento di memoria condivisa
+viene tolta dallo spazio di indirizzi del processo.
+
+
 %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
 %% riferimento alle strutture con cui il kernel implementa i segmenti di memoria
 %% condivisa; uno schema semplificato della struttura è illustrato in
 %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
 %% riferimento alle strutture con cui il kernel implementa i segmenti di memoria
 %% condivisa; uno schema semplificato della struttura è illustrato in
index 64f7648681bd1c80085f2bf22ed4c18904988db8..a4e31fd61fb6d5f329ca558b47f6be4ee9939049 100644 (file)
@@ -25,7 +25,7 @@ all: $(FINAL) $(LIB)
 flock: Flock.c
        $(CC) $(CFLAGJ) $^ -o $@ 
 
 flock: Flock.c
        $(CC) $(CFLAGJ) $^ -o $@ 
 
-mqfortune: MQFortuneClient.c
+mqfortune: MQFortuneClient.c FortuneParse.c
        $(CC) $(CFLAGJ) $^ -o $@
 
 mqfortuned: MQFortuneServer.c FortuneParse.c 
        $(CC) $(CFLAGJ) $^ -o $@
 
 mqfortuned: MQFortuneServer.c FortuneParse.c