Si e` provveduto anche a mettere il tutto in una bella libreria ...
Come esempio di uso dell'interfaccia dei semafori vediamo come implementare
con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice
-in questione, contenuto nel file \file{wrappers.h} allegato ai sorgenti, è
+in questione, contenuto nel file \file{Mutex.c} allegato ai sorgenti, è
riportato in \figref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per
creare un insieme contenente un singolo semaforo, per il quale poi useremo un
valore unitario per segnalare la disponibilità della risorsa, ed un valore
restituito dalla precedente chiamata a \func{shmat} con il quale era stato
agganciato al 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
-\figref{fig:ipc_shm_struct}.
+%% 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
+%% \figref{fig:ipc_shm_struct}.
-\begin{figure}[htb]
- \centering
- \includegraphics[width=10cm]{img/shmstruct}
- \caption{Schema dell'implementazione dei segmenti di memoria condivisa in
- Linux.}
- \label{fig:ipc_shm_struct}
-\end{figure}
+%% \begin{figure}[htb]
+%% \centering
+%% \includegraphics[width=10cm]{img/shmstruct}
+%% \caption{Schema dell'implementazione dei segmenti di memoria condivisa in
+%% Linux.}
+%% \label{fig:ipc_shm_struct}
+%% \end{figure}
che questa si liberi; ad esempio la si usa spesso per evitare interferenze
sull'uso delle porte seriali da parte di più programmi: qualora si trovi un
file di lock il programma che cerca di accedere alla seriale si limita a
-segnalare che la risorsa non è disponibile; sempre in \file{wrapper.h} si sono
-predisposte due funzioni, \func{LockFile} e \func{UnlockFile}, da utilizzare
-allo scopo.
+segnalare che la risorsa non è disponibile; in \file{LockFile.c} (un'altro dei
+sorgenti allegati alla guida) si sono predisposte due funzioni,
+\func{LockFile} e \func{UnlockFile}, da utilizzare allo scopo.
Dato che i file di lock presentano gli inconvenienti illustrati in precedenza,
la tecnica alternativa più comune è quella di fare ricorso al \textit{file
Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
che abbia le stesse caratteristiche di \func{signal}, a definire una funzione
equivalente attraverso \func{sigaction}; la funzione è \code{Signal}, e si
-trova definita come \code{inline} nel file \file{wrapper.h} (nei sorgenti
-allegati), riportata in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso
-in seguito.
+trova definita nel file \file{SigHand.c} (nei sorgenti allegati), e riportata
+in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso in seguito.
\subsection{La gestione della \textsl{maschera dei segnali} o
\textit{signal mask}}
\label{sec:sig_sigmask}
Come spiegato in \secref{sec:sig_semantics} tutti i moderni sistemi unix-like
-permettono si bloccare temporaneamente (o di eliminare completamente, impostando
-\macro{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è
-fatto specificando la cosiddetta \textsl{maschera dei segnali} (o
-\textit{signal mask}) del processo\footnote{nel caso di Linux essa è mantenuta
- dal campo \var{blocked} della \var{task\_struct} del processo.} cioè
-l'insieme dei segnali la cui consegna è bloccata. Abbiamo accennato in
-\secref{sec:proc_fork} che la \textit{signal mask} viene ereditata dal padre
-alla creazione di un processo figlio, e abbiamo visto al paragrafo precedente
-che essa può essere modificata, durante l'esecuzione di un gestore,
-attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}.
+permettono si bloccare temporaneamente (o di eliminare completamente,
+impostando \macro{SIG\_IGN} come azione) la consegna dei segnali ad un
+processo. Questo è fatto specificando la cosiddetta \textsl{maschera dei
+ segnali} (o \textit{signal mask}) del processo\footnote{nel caso di Linux
+ essa è mantenuta dal campo \var{blocked} della \var{task\_struct} del
+ processo.} cioè l'insieme dei segnali la cui consegna è bloccata. Abbiamo
+accennato in \secref{sec:proc_fork} che la \textit{signal mask} viene
+ereditata dal padre alla creazione di un processo figlio, e abbiamo visto al
+paragrafo precedente che essa può essere modificata, durante l'esecuzione di
+un gestore, attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}.
Uno dei problemi evidenziatisi con l'esempio di \secref{fig:sig_event_wrong} è
che in molti casi è necessario proteggere delle sezioni di codice (nel caso in
*
* Usage: echo -h give all info's
*
- * $Id: ElemEchoTCPClient.c,v 1.3 2001/09/09 22:45:34 piccardi Exp $
+ * $Id: ElemEchoTCPClient.c,v 1.4 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <sys/socket.h> /* socket library */
#include <stdio.h> /* include standard I/O library */
-#include "wrappers.h"
-
#define MAXLINE 256
void usage(void);
void ClientEcho(FILE * filein, int socket);
*
* Usage: echod -h give all info
*
- * $Id: ElemEchoTCPServer.c,v 1.3 2001/09/09 17:39:15 piccardi Exp $
+ * $Id: ElemEchoTCPServer.c,v 1.4 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <stdio.h> /* include standard I/O library */
#include <time.h>
-#include "wrappers.h"
#define BACKLOG 10
#define MAXLINE 256
*
* Usage: errcode -h give all info's
*
- * $Id: ErrCode.c,v 1.4 2001/10/14 15:05:33 piccardi Exp $
+ * $Id: ErrCode.c,v 1.5 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <unistd.h> /* unix standard library */
#include <stdio.h> /* standard I/O library */
#include <string.h> /* string functions */
+#include <limits.h> /* system limits values */
/* Help printing routine */
void usage(void);
*
* Usage: forktest -h give all info's
*
- * $Id: ForkTest.c,v 1.7 2002/08/18 23:24:44 piccardi Exp $
+ * $Id: ForkTest.c,v 1.8 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <stdio.h> /* standard I/O library */
#include <string.h> /* string functions */
-#include "wrappers.h"
+#include "Gapil.h"
#include "macros.h"
/* Help printing routine */
wait_end = strtol(optarg, NULL, 10); /* convert input */
break;
case 's':
- Signal(SIGCHLD, HandSIGCHLD);
+ Signal(SIGCHLD, HandSigCHLD);
break;
case '?': /* unrecognized options */
printf("Unrecognized options -%c\n",optopt);
*
* Usage: fortuned -h give all info
*
- * $Id: FortuneServer.c,v 1.4 2002/08/19 17:34:23 piccardi Exp $
+ * $Id: FortuneServer.c,v 1.5 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <fcntl.h> /* */
#include "macros.h"
-#include "wrappers.h"
+#include "Gapil.h"
/* Subroutines declaration */
void usage(void);
--- /dev/null
+/*****************************************************************************
+ *
+ * File Gapil.h:
+ * Set of definition for service routines
+ *
+ * Author: S. Piccardi
+ *
+ * $Id: Gapil.h,v 1.1 2002/12/03 11:06:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/sem.h> /* IPC semaphore declarations */
+#include <sys/shm.h> /* IPC shared memory declarations */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h> /* unix standard functions */
+#include <fcntl.h> /* file control (lock) functions */
+#include <signal.h> /* signal handling declarations */
+/*
+ * Definition of semun struct; used to implement a MutexXXXX API To
+ * create a Mutex use an underlaying semaphore and init it; we put
+ * here all the needed data structures
+ */
+/* use this definition, get from the man pages */
+#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+/* union semun is defined by including <sys/sem.h> */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short int *array; /* array for GETALL, SETALL */
+ struct seminfo *__buf; /* buffer for IPC_INFO */
+};
+#endif
+/*
+ * Mutex handling Functions
+ */
+/* Function MutexCreate: create a mutex. See Mutex.c */
+inline int MutexCreate(key_t ipc_key);
+/* Function MutexFind: get the mutex ID given fomr IPC key. See Mutex.c */
+inline int MutexFind(key_t ipc_key);
+/* Function MutexRead: read the current value of the mutex. See Mutex.c */
+inline int MutexRead(int sem_id);
+/* Function MutexLock: to lock a mutex/semaphore. See Mutex.c */
+inline int MutexLock(int sem_id);
+/* Function MutexUnlock: to unlock a mutex/semaphore. See Mutex.c */
+inline int MutexUnlock(int sem_id);
+
+/* Function LockFile: create a lock file. See FileLock.c*/
+inline int LockFile(const char* path_name);
+/* Function UnLockFile: remove a lock file. See FileLock.c*/
+inline int UnlockFile(const char* path_name);
+/*
+ * Signal Handling Functions
+ */
+typedef void SigFunc(int);
+/* Function Signal: Initialize a signal handler. See SigHand.c */
+SigFunc * Signal(int signo, SigFunc *func);
+/* Function HandSigCHLD: to handle SIGCHILD. See SigHand.c */
+void HandSigCHLD(int sig);
+/*
+ * Socket service functions
+ */
+/* Function SockRead: to read from a socket. See SockRead.c */
+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);
+++ /dev/null
-#include <errno.h> /* error simbol definitions */
-#include <signal.h> /* signal handling declarations */
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "macros.h"
-
-void HandSIGCHLD(int sig)
-{
- int errno_save;
- int status;
- pid_t pid;
- /* save errno current value */
- errno_save = errno;
- /* loop until no */
- do {
- errno = 0;
- pid = waitpid(WAIT_ANY, &status, WNOHANG);
- if (pid > 0) {
- debug("child %d terminated with status %x\n", pid, status);
- }
- } while ((pid > 0) && (errno == EINTR));
- /* restore errno value*/
- errno = errno_save;
- /* return */
- return;
-}
--- /dev/null
+/*****************************************************************************
+ *
+ * File LockFile.h:
+ * Function to manipulate lock files.
+ *
+ * Author: S. Piccardi, Dec 2002
+ *
+ * $Id: LockFile.c,v 1.1 2002/12/03 11:06:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h> /* unix standard functions */
+#include <fcntl.h> /* file control (lock) functions */
+/*
+ * Function LockFile:
+ *
+ * Create a lockfile of the given pathname. Fail and exit in case of
+ * error or existence of the same lock file, using unlink do not need
+ * to remove the file.
+ *
+ * Author: Simone Piccardi, Dec. 2002
+ */
+int LockFile(const char* path_name)
+{
+ return open(path_name, O_EXCL|O_CREAT);
+}
+/*
+ * Function UnlockFile:
+ * Remove a lockfile of the given pathname.
+ *
+ * Author: Simone Piccardi, Dec. 2002
+ */
+int UnlockFile(const char* path_name)
+{
+ return unlink(path_name);
+}
*
* Usage: fortune -h give all info
*
- * $Id: MQFortuneClient.c,v 1.1 2002/10/20 22:42:48 piccardi Exp $
+ * $Id: MQFortuneClient.c,v 1.2 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <sys/msg.h>
#include "macros.h"
-#include "wrappers.h"
/* Maximum message size */
#define MSGMAX 8192
*
* Usage: fortuned -h give all info
*
- * $Id: MQFortuneServer.c,v 1.2 2002/10/20 22:40:34 piccardi Exp $
+ * $Id: MQFortuneServer.c,v 1.3 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <sys/msg.h>
#include "macros.h"
-#include "wrappers.h"
+#include "Gapil.h"
/* Maximum message size */
#define MSGMAX 8192
# Simple Makefile to build examples
#
# C flags
-CC=gcc -DDEBUG
-CFLAGS= -Wall -g
-CFLADJ=-c
+CC=gcc
+CFLAGS= -Wall -g -DDEBUG -fPIC
+CFLAGJ= -L./ -lgapil
-OBJ = SockRead.o SockWrite.o
+LIB = libgapil.so
+
+OBJ = SockRead.o SockWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o
FINAL = forktest errcode echo echod daytimed iterdaytimed daytime testfopen \
- testren fortune fortuned
+ testren fortune fortuned mqfortune mqfortuned flock
+
+$(LIB): $(OBJ)
+ gcc -shared $^ -o $@
+
+
+$(OBJ): Gapil.h
+
+all: $(FINAL) $(LIB)
+
flock: Flock.c
- $(CC) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
mqfortune: MQFortuneClient.c
- $(CC) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
mqfortuned: MQFortuneServer.c FortuneParse.c
- $(CC) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
fortune: FortuneClient.c
- $(CC) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
fortuned: FortuneServer.c FortuneParse.c
- $(CC) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
barcode: BarCode.c
- $(CC) $(CFLAGS) $^ -o $@
-
+ $(CC) $(CFLAGJ) $^ -o $@
barcodepage: BarCodePage.c
- $(CC) $(CFLAGS) $^ -o $@
-
+ $(CC) $(CFLAGJ) $^ -o $@
getparam: getparam.c
- $(CC) $(CFLAGS) $^ -o $@
-
-all: $(FINAL)
-
+ $(CC) $(CFLAGJ) $^ -o $@
testfopen: test_fopen.c
- $(CC) $(CFLAGS) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
testren: TestRen.c
- $(CC) $(CFLAGS) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
-forktest: ForkTest.c HandSIGCHLD.c
- $(CC) $(CFLAGS) $^ -o $@
+forktest: ForkTest.c
+ $(CC) $(CFLAGJ) $^ -o $@
errcode: ErrCode.c
- $(CC) $(CFLAGS) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
-echo: SimpleEchoTCPClient.c $(OBJ)
- $(CC) $(CFLAGS) $^ -o $@
+echo: SimpleEchoTCPClient.c
+ $(CC) $(CFLAGJ) $^ -o $@
-echod: SimpleEchoTCPServer.c $(OBJ)
- $(CC) $(CFLAGS) $^ -o $@
+echod: SimpleEchoTCPServer.c
+ $(CC) $(CFLAGJ) $^ -o $@
daytimed: ElemDaytimeTCPCuncServ.c
- $(CC) $(CFLAGS) $^ -o $@
-
-iterdaytimed: SimpleDaytimeTCPServer.c
- $(CC) $(CFLAGS) $^ -o $@
+ $(CC) $(CFLAGJ) $^ -o $@
-daytime: SimpleDaytimeTCPClient.c
- $(CC) $(CFLAGS) $^ -o $@
+iterdaytimed: ElemDaytimeTCPServer.c
+ $(CC) $(CFLAGJ) $^ -o $@
-$(OBJ): wrappers.h
+daytime: ElemDaytimeTCPClient.c
+ $(CC) $(CFLAGJ) $^ -o $@
# Macro per la generazione della tarball dei sorgenti
rm -f $(FINAL)
rm -f *~
rm -f *.o
+ rm -f *.so
rm -f prova*
rm -f output*
--- /dev/null
+/*****************************************************************************
+ *
+ * File Mutex.c: define a set of functions for mutex manipulation
+ *
+ * Author: S. Piccardi Dec. 2002
+ *
+ * $Id: Mutex.c,v 1.1 2002/12/03 11:06:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <sys/sem.h> /* IPC semaphore declarations */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h> /* signal handling declarations */
+
+#include "Gapil.h"
+/*
+ * Function MutexCreate: create a mutex/semaphore
+ *
+ * First call create a semaphore, using the given key.
+ * We want only one semaphore so we set second argument to 1; third
+ * parameter is the flag argument, and is set to create a semaphore
+ * with R/W privilege for the user.
+ * Second call initialize the semaphore to 1 (unlocked)
+ *
+ * Input: an IPC key value (to create an unique semaphore)
+ * Return: the semaphore id# or -1 on error
+ */
+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
+ *
+ * Input: an 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
+ *
+ * Input: a semaphore id #
+ * Return: the semaphore value
+ */
+int MutexRead(int sem_id)
+{
+ return semctl(sem_id, 0, GETVAL);
+}
+/*
+ * Define sembuf structures to lock and unlock the semaphore
+ * (used to implement a mutex)
+ */
+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
+ *
+ * Input: a semaphore id #
+ * Output: semop return code (0 OK, -1 KO)
+ */
+int MutexLock(int sem_id)
+{
+ return semop(sem_id, &sem_lock, 1);
+}
+/*
+ * Function MutexUnlock: to unlock a mutex/semaphore
+ *
+ * Input: a semaphore id #
+ * Return: semop return code (0 OK, -1 KO)
+ */
+int MutexUnlock(int sem_id)
+{
+ return semop(sem_id, &sem_ulock, 1);
+}
--- /dev/null
+/***************************************************************
+ *
+ * File SharedMem.c
+ * Routine for Shared Memory use
+ *
+ * Author: S. Piccardi
+ *
+ * $Id: SharedMem.c,v 1.1 2002/12/03 11:06:05 piccardi Exp $
+ *
+ ***************************************************************/
+#include <sys/shm.h> /* SysV IPC shared memory declarations */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h> /* standard I/O functions */
+#include <fcntl.h>
+#include <signal.h> /* signal handling declarations */
+/*
+ * Function ShmCreate:
+ * Create and attach a SysV shared memory segment to the current process.
+ *
+ * First call get a shared memory segment with KEY key access and size SIZE,
+ * by creating it with R/W privilege for the user (this is the meaning of
+ * the ored flags). The function return an identifier shmid used for any
+ * further reference to the shared memory segment.
+ * Second call attach the shared memory segment to this process and return a
+ * pointer to it (of void * type).
+ * Then initialize shared memory to the given value
+ *
+ * Input: an IPC key value
+ * the shared memory segment size
+ * Return: the address of the segment
+ */
+void * ShmCreate(key_t ipc_key, int shm_size, char fill)
+{
+ void * shptr;
+ int shmid; /* ID of the IPC shared memory segment */
+ shmid = shmget(ipc_key,shm_size,IPC_CREAT|0666); /* get shm ID */
+ if (shmid < 0) {
+ return (void *) shmid;
+ }
+ shptr = shmat(shmid,0,0); /* take the pointer to it */
+ if ( shptr == 0 ){
+ perror("cannot attach shared memory");
+ exit(1);
+ }
+ memset((void *)shptr, fill, shm_size); /* second counter starts from "0" */
+ return shptr;
+}
+/*
+ * Function ShmFind:
+ * Find a shared memory segment
+ * Input: an IPC key value
+ * the shared memory segment size
+ * Return: the address of the segment
+ */
+void * ShmFind(key_t ipc_key, int shm_size)
+{
+ void * shptr;
+ int shmid; /* ID of the IPC shared memory segment */
+ if ( (shmid=shmget(ipc_key,shm_size,0))<0 ){ /* find shared memory ID */
+ perror("cannot find shared memory");
+ exit(1);
+ }
+ if ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */
+ perror("cannot attach shared memory");
+ exit(1);
+ }
+ return shptr;
+}
--- /dev/null
+/*****************************************************************************
+ *
+ * File SigHand.c: define a set of functions for signal manipulation
+ *
+ * Author: S. Piccardi Dec. 2002
+ *
+ * $Id: SigHand.c,v 1.1 2002/12/03 11:06:05 piccardi Exp $
+ *
+ *****************************************************************************/
+#include <errno.h> /* error simbol definitions */
+#include <stdio.h> /* standard I/O functions */
+#include <signal.h> /* signal handling declarations */
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "Gapil.h"
+#include "macros.h"
+
+/*
+ * Function Signal
+ * Initialize a signal handler.
+ * To enable the signal handling a process we need to tell it to
+ * kernel; this is done writing all needed info to a sigaction structure
+ * named sigact, and then callind sigaction() system call passing the
+ * information stored in the sigact structure variable.
+ *
+ * Input: the signal to handle
+ * the signal handler function
+ * Return: the previous sigaction structure
+ */
+inline SigFunc * Signal(int signo, SigFunc *func)
+{
+ struct sigaction new_handl, old_handl;
+ new_handl.sa_handler=func;
+ /* clear signal mask: no signal blocked during execution of func */
+ if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */
+ perror("cannot initializes the signal set to empty"); /* see mess. */
+ exit(1);
+ }
+ new_handl.sa_flags=0; /* init to 0 all flags */
+ /* change action for signo signal */
+ if (sigaction(signo,&new_handl,&old_handl)){
+ perror("sigaction failed on signal action setting");
+ exit(1);
+ }
+ return (old_handl.sa_handler);
+}
+/*
+ * Functions: HandSigCHLD
+ * Generic handler for SIGCHLD signal
+ *
+ * Simone Piccardi Dec. 2002
+ * $Id: SigHand.c,v 1.1 2002/12/03 11:06:05 piccardi Exp $
+ */
+void HandSigCHLD(int sig)
+{
+ int errno_save;
+ int status;
+ pid_t pid;
+ /* save errno current value */
+ errno_save = errno;
+ /* loop until no */
+ do {
+ errno = 0;
+ pid = waitpid(WAIT_ANY, &status, WNOHANG);
+ if (pid > 0) {
+ debug("child %d terminated with status %x\n", pid, status);
+ }
+ } while ((pid > 0) && (errno == EINTR));
+ /* restore errno value*/
+ errno = errno_save;
+ /* return */
+ return;
+}
*
* Usage: echo -h give all info's
*
- * $Id: SimpleEchoTCPClient.c,v 1.4 2001/09/09 22:45:34 piccardi Exp $
+ * $Id: SimpleEchoTCPClient.c,v 1.5 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <sys/socket.h> /* socket library */
#include <stdio.h> /* include standard I/O library */
-#include "wrappers.h"
-
#define MAXLINE 256
void usage(void);
void EchoClient(FILE * filein, int socket);
*
* Usage: echod
*
- * $Id: SimpleEchoTCPServer.c,v 1.4 2001/09/09 22:45:34 piccardi Exp $
+ * $Id: SimpleEchoTCPServer.c,v 1.5 2002/12/03 11:06:05 piccardi Exp $
*
****************************************************************/
/*
#include <stdio.h> /* include standard I/O library */
#include <time.h>
-#include "wrappers.h"
-
#define BACKLOG 10
#define MAXLINE 256
+++ /dev/null
-/***************************************************************
- *
- * File wrappers.h: define a set of macro and inlined
- * functions for signal, shared memory and semaphore handling
- *
- * Author: S. Piccardi
- *
- * $Id: wrappers.h,v 1.5 2002/12/02 23:06:59 piccardi Exp $
- *
- ***************************************************************/
-#include <sys/sem.h> /* IPC semaphore declarations */
-#include <sys/shm.h> /* IPC shared memory declarations */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h> /* signal handling declarations */
-/**
- ** Semaphore definition; used to implement a MutexXXXX API
- ** To create a Mutex use an underlaying semaphore and init it;
- ** we put here all the needed data structires
- **/
-/* put this definition, get from the man pages */
-#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
-/* union semun is defined by including <sys/sem.h> */
-#else
-/* according to X/OPEN we have to define it ourselves */
-union semun {
- int val; /* value for SETVAL */
- struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
- unsigned short int *array; /* array for GETALL, SETALL */
- struct seminfo *__buf; /* buffer for IPC_INFO */
-};
-#endif
-/*
- * Function MutexCreate: create a mutex/semaphore
- *
- * First call create a semaphore, using the given key.
- * We want only one semaphore so we set second argument to 1; third
- * parameter is the flag argument, and is set to create a semaphore
- * with R/W privilege for the user.
- * Second call initialize the semaphore to 1 (unlocked)
- *
- * Input: an IPC key value (to create an unique semaphore)
- * Return: the semaphore id# or -1 on error
- */
-inline 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
- *
- * Input: an IPC key value
- */
-inline int MutexFind(key_t ipc_key)
-{
- return semget(ipc_key,1,0);
-}
-/*
- * Function MutexRead: read the current value of the mutex/semaphore
- *
- * Input: a semaphore id #
- * Return: the semaphore value
- */
-inline int MutexRead(int sem_id)
-{
- return semctl(sem_id, 0, GETVAL);
-}
-/*
- * Define sembuf structures to lock and unlock the semaphore
- * (used to implement a mutex)
- */
-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_UNO}; /* flag (in this case 0) */
-/*
- * Function MutexLock: to lock a mutex/semaphore
- *
- * Input: a semaphore id #
- * Output: semop return code (0 OK, -1 KO)
- */
-inline int MutexLock(int sem_id)
-{
- return semop(sem_id, &sem_lock, 1);
-}
-/*
- * Function MutexUnlock: to unlock a mutex/semaphore
- *
- * Input: a semaphore id #
- * Return: semop return code (0 OK, -1 KO)
- */
-inline int MutexUnlock(int sem_id)
-{
- return semop(sem_id, &sem_ulock, 1);
-}
-/*
- * Function ShmCreate:
- * Allocate a shared memory segment.
- * First call get a shared memory segment with KEY key access and size SIZE,
- * by creating it with R/W privilege for the user (this is the meaning of
- * the ored flags). The function return an identifier shmid used for any
- * further reference to the shared memory segment.
- * Second call attach the shared memory segment to this process and return a
- * pointer to it (of char * type).
- * Then initialize shared memory:
- * Set all to 0x55 (means 0101 un binary notation
- *
- * Input: an IPC key value
- * the shared memory segment size
- * Return: the address of the segment
- */
-inline char * ShmCreate(key_t ipc_key, int shm_size)
-{
- char * shptr;
- int shmid; /* ID of the IPC shared memory segment */
- if ((shmid=shmget(ipc_key,shm_size,IPC_CREAT|0666))<0){ /* get shm ID */
- perror("cannot find shared memory");
- exit(1);
- }
- if ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */
- perror("cannot attach shared memory");
- exit(1);
- }
- memset((void *)shptr,0x55,shm_size); /* second couter starts from "0" */
- return shptr;
-}
-/*
- * Function ShmFind:
- * Find a shared memory segment
- * Input: an IPC key value
- * the shared memory segment size
- * Return: the address of the segment
- */
-inline char * ShmFind(key_t ipc_key, int shm_size)
-{
- char * shptr;
- int shmid; /* ID of the IPC shared memory segment */
- if ( (shmid=shmget(ipc_key,shm_size,0))<0 ){ /* find shared memory ID */
- perror("cannot find shared memory");
- exit(1);
- }
- if ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */
- perror("cannot attach shared memory");
- exit(1);
- }
- return shptr;
-}
-/*
- * Function LockFile & UnlockFile:
- * Create and remove a lockfile of the given pathname.
- * Fail and exit in case of error or existence of the same lock
- * file, using unlink do not need to remove the file,
- */
-inline int LockFile(const char* path_name)
-{
- return open(path_name, O_EXCL|O_CREAT);
-}
-inline int UnlockFile(const char* path_name)
-{
- return unlink(path_name);
-}
-/*
- * Function Signal
- * Initialize a signal handler.
- * To enable the signal handling a process we need to tell it to
- * kernel; this is done writing all needed info to a sigaction structure
- * named sigact, and then callind sigaction() system call passing the
- * information stored in the sigact structure variable.
- *
- * Input: the signal to handle
- * the signal handler function
- * Return: the previous sigaction structure
- */
-typedef void SigFunc(int);
-inline SigFunc * Signal(int signo, SigFunc *func)
-{
- struct sigaction new_handl, old_handl;
- new_handl.sa_handler=func;
- /* clear signal mask: no signal blocked during execution of func */
- if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */
- perror("cannot initializes the signal set to empty"); /* see mess. */
- exit(1);
- }
- new_handl.sa_flags=0; /* init to 0 all flags */
- /* change action for signo signal */
- if (sigaction(signo,&new_handl,&old_handl)){
- perror("sigaction failed on signal action setting");
- exit(1);
- }
- return (old_handl.sa_handler);
-}
-
-/**
- ** Defining prototypes for the all other functions
- **/
-ssize_t SockRead(int fd, void *buf, size_t count);
-ssize_t SockWrite(int fd, const void *buf, size_t count);
-
-void HandSIGCHLD(int sig);