figlio è zero; in questo modo il programma può identificare se viene eseguito
dal padre o dal figlio.
-Si noti come la funzione \fucn{fork} ritorni \textbf{due} volte: nel padre e
-nel figlio. La sola differenza che si ha nei due processi è il valore di
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <errno.h> /* error definitions and routines */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h> /* unix standard library */
+#include <stdio.h> /* standard I/O library */
+#include <string.h> /* string functions */
+
+/* Help printing routine */
+void usage(void);
+
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int i;
+ int nchild;
+ pid_t pid;
+
+ ... /* handling options */
+
+ /* There must be remaing parameters */
+ if (optind == argc) {
+ usage();
+ }
+ nchild = atoi(argv[optind]);
+ printf("Test for forking %d child\n", nchild);
+ /* loop to fork children */
+ for (i=0; i<nchild; i++) {
+ if ( (pid = fork()) < 0) {
+ printf("Error on %d child creation, %s\n", i, strerror(errno));
+ }
+ if (pid == 0) { /* child */
+ printf("Child %d successfully executing\n", i++);
+ sleep(2);
+ printf("Child %d exiting\n", i);
+ exit(0);
+ } else { /* parent */
+ printf("Spawned %d child, pid %d \n", i, pid);
+ }
+ }
+ /* normal exit */
+ return 0;
+}
+ \end{lstlisting}
+ \caption{Esempio di codice per la creazione di nuovi processi.}
+ \label{fig:proc_fork_code}
+\end{figure}
+
+Si noti come la funzione \func{fork} ritorni \textbf{due} volte: una nel padre
+e una nel figlio. La sola differenza che si ha nei due processi è il valore di
ritorno restituito dalla funzione, che nel padre è il \acr{pid} del figlio
mentre nel figlio è zero; in questo modo il programma può identificare se
-viene eseguito dal padre o dal figlio. La scelta di questi valori comunque non
-è casuale, un processo infatti può avere più figli, ed il valore di ritorno di
-\func{fork} è l'unico modo che permette di idenficare quello appena creato; al
-contrario un figlio ha sempre un solo padre (il cui \acr{pid} può sempre
-essere ottenuto con \func{getppid}, vista in \secref{sec:proc_pid}) e si usa
-il valore nullo, che non può essere il \acr{pid} di nessun processo.
-
-In generale non si può dire se il quale fra il padre ed il figlio venga
-eseguito per primo\footnote{anche se nel kernel 2.4.x è stato introdotto un
+viene eseguito dal padre o dal figlio.
+
+La scelta di questi valori comunque non è casuale, un processo infatti può
+avere più figli, ed il valore di ritorno di \func{fork} è l'unico modo che
+permette di identificare quello appena creato; al contrario un figlio ha
+sempre un solo padre (il cui \acr{pid} può sempre essere ottenuto con
+\func{getppid}, vista in \secref{sec:proc_pid}) e si usa il valore nullo, che
+non può essere il \acr{pid} di nessun processo.
+
+In \curfig\ si è riportato il corpo del codice dell'esempio \cmd{forktest},
+che ci permette di illustrare l'uso della funzione \func{fork}, creando un
+numero di figli specificato a linea di comando; il codice completo, compresa
+la parte che gestisce le opzioni a riga di comando, è disponibile nel file
+\file{ForkTest.c}.
+
+Decifrato il numero di figli da creare il ciclo principale del programma
+(\texttt{\small 28--40}) esegue in successione la creazione dei processi figli
+(\texttt{\small 29--31}) controllando il successo della chiamata a
+\func{fork}; ciascun figlio (\texttt{\small 29--31}) si limita a stampare il
+suo numero di successione, attendere 2 secondi e scrivere un messaggio prima
+di uscire. Il processo padre invece (\texttt{\small 29--31}) stampa un
+messaggio di creazione e procede nell'esecuzione del ciclo.
+
+In generale\footnote{anche se nel kernel 2.4.x è stato introdotto un
meccanismo che metteva in esecuzione sempre il xxx per primo (TODO
- recuperare le informazioni esatte)}, per cui se i due processi devono essere
-sincronizzati occorre ricorrere ad un qualche meccanismo di
-intercomunicazione.
-
-
+ recuperare le informazioni esatte)} non si può dire quale processo fra il
+padre ed il figlio venga eseguito per primo dopo la chiamata a \func{fork},
+per cui se i due processi devono essere sincronizzati occorre ricorrere ad un
+qualche meccanismo di intercomunicazione.
\subsection{Le funzioni \texttt{wait} e \texttt{waitpid}}
\label{fig:sock_SockWrite_code}
\end{figure}
-Come si può notare le funzioni ripetono la lettura/scrittura in un loop fino
+Come si può notare le funzioni ripetono la lettura/scrittura in un ciclo fino
all'esaurimento del numero di bytes richiesti, in caso di errore viene
controllato se questo è \texttt{EINTR} (cioè un'interruzione della system call
dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
-l'errore viene ritornato interrompendo il loop.
+l'errore viene ritornato interrompendo il ciclo.
Nel caso della lettura se il numero di bytes letti è zero significa che è
arrivati alla fine del file e pertanto si ritorna senza aver concluso la
di 26 byte (come avverrà senz'altro nel caso in questione) ma potrebbe anche
arrivare in 26 pacchetti di un byte. Per questo nel caso generale non si può
mai assumere che tutti i dati arrivino con una singola lettura, pertanto
-quest'ultima deve essere effettuata in un loop in cui si continui a leggere
+quest'ultima deve essere effettuata in un ciclo in cui si continui a leggere
fintanto che la funzione \func{read} non ritorni uno zero (che significa che
l'altro capo ha chiuso la connessione) o un numero minore di zero (che
significa un errore nella connessione).
dalla successiva chiamata alla \func{write} per scrivere la risposta al
client, una volta che si è opportunamente (\texttt{\small 48--49}) costruita
la stringa con la data da trasmettere. Completata la trasmissione il nuovo
-socket viene chiuso (\texttt{\small 54}). Il tutto è inserito in un loop
+socket viene chiuso (\texttt{\small 54}). Il tutto è inserito in un ciclo
infinito (\texttt{\small 42--55}) in modo da poter ripetere l'invio della data
ad una successiva connessione.
--- /dev/null
+/* ElemDaytimeTCPClient.c
+ *
+ * Copyright (C) 2001 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Program daytime:
+ * Simple TCP client for daytime service (port 13)
+ *
+ * Author: Simone Piccardi
+ * Apr. 2001
+ *
+ * Usage: daytime -h give all info's
+ *
+ * $Id: ElemDaytimeTCPClient.c,v 1.1 2001/09/09 17:39:15 piccardi Exp $
+ *
+ ****************************************************************/
+/*
+ * Include needed headers
+ */
+#include <sys/types.h> /* predefined types */
+#include <unistd.h> /* include unix standard library */
+#include <arpa/inet.h> /* IP addresses conversion utiliites */
+#include <sys/socket.h> /* socket library */
+#include <stdio.h> /* include standard I/O library */
+
+#define MAXLINE 80
+/* Program begin */
+void usage(void);
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int sock_fd;
+ int i, nread;
+ struct sockaddr_in serv_add;
+ char buffer[MAXLINE];
+ /*
+ * Input section: decode parameters passed in the calling
+ * Use getopt function
+ */
+ opterr = 0; /* don't want writing to stderr */
+ while ( (i = getopt(argc, argv, "h")) != -1) {
+ switch (i) {
+ /*
+ * Handling options
+ */
+ case 'h':
+ printf("Wrong -h option use\n");
+ usage();
+ return(0);
+ break;
+ case '?': /* unrecognized options */
+ printf("Unrecognized options -%c\n",optopt);
+ usage();
+ default: /* should not reached */
+ usage();
+ }
+ }
+ /* ***********************************************************
+ *
+ * Options processing completed
+ *
+ * Main code beginning
+ *
+ * ***********************************************************/
+ /* create socket */
+ if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("Socket creation error");
+ return -1;
+ }
+ /* initialize address */
+ memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */
+ serv_add.sin_family = AF_INET; /* address type is INET */
+ serv_add.sin_port = htons(13); /* daytime port is 13 */
+ /* build address using inet_pton */
+ if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) {
+ perror("Address creation error");
+ return -1;
+ }
+ /* extablish connection */
+ if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
+ perror("Connection error");
+ return -1;
+ }
+ /* read daytime from server */
+ while ( (nread = read(sock_fd, buffer, MAXLINE)) > 0) {
+ buffer[nread]=0;
+ if (fputs(buffer, stdout) == EOF) { /* write daytime */
+ perror("fputs error");
+ return -1;
+ }
+ }
+ /* error on read */
+ if (nread < 0) {
+ perror("Read error");
+ return -1;
+ }
+ /* normal exit */
+ return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+ printf("Take daytime from a remote host \n");
+ printf("Usage:\n");
+ printf(" daytime [-h] [-v] [host in dotted decimal form] \n");
+ printf(" -v set verbosity on\n");
+ printf(" -h print this help\n");
+ exit(1);
+}
+/* ElemDaytimeTCPCuncServ.c
+ *
+ * Copyright (C) 2001 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
/****************************************************************
*
* Program ElemDaytimeTCPCuncServ.c
* Author: Simone Piccardi
* May. 2001
*
- * Usage: daytimed
+ * Usage: daytimed -h give all info
*
- * $Id: ElemDaytimeTCPCuncServ.c,v 1.1 2001/05/19 20:47:03 piccardi Exp $
+ * $Id: ElemDaytimeTCPCuncServ.c,v 1.2 2001/09/09 17:39:15 piccardi Exp $
*
****************************************************************/
/*
-/****************************************************************
+/* ElemDaytimeTCPClient.c
+ *
+ * Copyright (C) 2000 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+//****************************************************************
*
- * Program daytime_tcp_server.c:
+ * Program daytimed:
* Elementary TCP server for daytime service (port 13)
*
* Author: Simone Piccardi
*
* Usage: daytimed
*
- * $Id: ElemDaytimeTCPServer.c,v 1.1 2001/06/18 21:46:14 piccardi Exp $
+ * $Id: ElemDaytimeTCPServer.c,v 1.2 2001/09/09 17:39:15 piccardi Exp $
*
****************************************************************/
/*
+/* ElemEchoTCPServer.c
+ *
+ * Copyright (C) 2001 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
/****************************************************************
*
- * Program echo_tcp_server.c:
+ * Program echod
* Elementary TCP server for echo service (port 7)
*
* Author: Simone Piccardi
* Jun. 2001
*
- * Usage: echod
+ * Usage: echod -h give all info
*
- * $Id: ElemEchoTCPServer.c,v 1.2 2001/06/20 22:03:37 piccardi Exp $
+ * $Id: ElemEchoTCPServer.c,v 1.3 2001/09/09 17:39:15 piccardi Exp $
*
****************************************************************/
/*
* routine to print usage info and exit
*/
void usage(void) {
- printf("Simple daytime server\n");
+ printf("Elementary echo server\n");
printf("Usage:\n");
- printf(" daytimed [-h] \n");
+ printf(" echod [-h] \n");
printf(" -h print this help\n");
exit(1);
}
--- /dev/null
+/****************************************************************
+ *
+ * Program ErrCode.c:
+ * Print error code MACRO and messages
+ *
+ * Author: Simone Piccardi
+ * Sep. 2001
+ *
+ * Usage: errcode -h give all info's
+ *
+ * $Id: ErrCode.c,v 1.1 2001/09/09 17:39:15 piccardi Exp $
+ *
+ ****************************************************************/
+/*
+ * Include needed headers
+ */
+#include <errno.h> /* error definitions and routines */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h> /* unix standard library */
+#include <stdio.h> /* standard I/O library */
+#include <string.h> /* string functions */
+
+/* Help printing routine */
+void usage(void);
+
+/* Array for code number <=> code macro name */
+char * err_code[] = {
+"SUCCESS ", /* 0 Success */
+"EPERM ", /* 1 Operation not permitted */
+"ENOENT ", /* 2 No such file or directory */
+"ESRCH ", /* 3 No such process */
+"EINTR ", /* 4 Interrupted system call */
+"EIO ", /* 5 I/O error */
+"ENXIO ", /* 6 No such device or address */
+"E2BIG ", /* 7 Arg list too long */
+"ENOEXEC ", /* 8 Exec format error */
+"EBADF ", /* 9 Bad file number */
+"ECHILD ", /* 10 No child processes */
+"EAGAIN ", /* 11 Try again */
+"ENOMEM ", /* 12 Out of memory */
+"EACCES ", /* 13 Permission denied */
+"EFAULT ", /* 14 Bad address */
+"ENOTBLK ", /* 15 Block device required */
+"EBUSY ", /* 16 Device or resource busy */
+"EEXIST ", /* 17 File exists */
+"EXDEV ", /* 18 Cross-device link */
+"ENODEV ", /* 19 No such device */
+"ENOTDIR ", /* 20 Not a directory */
+"EISDIR ", /* 21 Is a directory */
+"EINVAL ", /* 22 Invalid argument */
+"ENFILE ", /* 23 File table overflow */
+"EMFILE ", /* 24 Too many open files */
+"ENOTTY ", /* 25 Not a typewriter */
+"ETXTBSY ", /* 26 Text file busy */
+"EFBIG ", /* 27 File too large */
+"ENOSPC ", /* 28 No space left on device */
+"ESPIPE ", /* 29 Illegal seek */
+"EROFS ", /* 30 Read-only file system */
+"EMLINK ", /* 31 Too many links */
+"EPIPE ", /* 32 Broken pipe */
+"EDOM ", /* 33 Math argument out of domain of func */
+"ERANGE ", /* 34 Math result not representable */
+"EDEADLK ", /* 35 Resource deadlock would occur */
+"ENAMETOOLONG ", /* 36 File name too long */
+"ENOLCK ", /* 37 No record locks available */
+"ENOSYS ", /* 38 Function not implemented */
+"ENOTEMPTY ", /* 39 Directory not empty */
+"ELOOP ", /* 40 Too many symbolic links encountered */
+"EWOULDBLOCK ", /* EAGAIN Operation would block */
+"ENOMSG ", /* 42 No message of desired type */
+"EIDRM ", /* 43 Identifier removed */
+"ECHRNG ", /* 44 Channel number out of range */
+"EL2NSYNC ", /* 45 Level 2 not synchronized */
+"EL3HLT ", /* 46 Level 3 halted */
+"EL3RST ", /* 47 Level 3 reset */
+"ELNRNG ", /* 48 Link number out of range */
+"EUNATCH ", /* 49 Protocol driver not attached */
+"ENOCSI ", /* 50 No CSI structure available */
+"EL2HLT ", /* 51 Level 2 halted */
+"EBADE ", /* 52 Invalid exchange */
+"EBADR ", /* 53 Invalid request descriptor */
+"EXFULL ", /* 54 Exchange full */
+"ENOANO ", /* 55 No anode */
+"EBADRQC ", /* 56 Invalid request code */
+"EBADSLT ", /* 57 Invalid slot */
+"EDEADLOCK ", /* EDEADLK */
+"EBFONT ", /* 59 Bad font file format */
+"ENOSTR ", /* 60 Device not a stream */
+"ENODATA ", /* 61 No data available */
+"ETIME ", /* 62 Timer expired */
+"ENOSR ", /* 63 Out of streams resources */
+"ENONET ", /* 64 Machine is not on the network */
+"ENOPKG ", /* 65 Package not installed */
+"EREMOTE ", /* 66 Object is remote */
+"ENOLINK ", /* 67 Link has been severed */
+"EADV ", /* 68 Advertise error */
+"ESRMNT ", /* 69 Srmount error */
+"ECOMM ", /* 70 Communication error on send */
+"EPROTO ", /* 71 Protocol error */
+"EMULTIHOP ", /* 72 Multihop attempted */
+"EDOTDOT ", /* 73 RFS specific error */
+"EBADMSG ", /* 74 Not a data message */
+"EOVERFLOW ", /* 75 Value too large for defined data type */
+"ENOTUNIQ ", /* 76 Name not unique on network */
+"EBADFD ", /* 77 File descriptor in bad state */
+"EREMCHG ", /* 78 Remote address changed */
+"ELIBACC ", /* 79 Can not access a needed shared library */
+"ELIBBAD ", /* 80 Accessing a corrupted shared library */
+"ELIBSCN ", /* 81 .lib section in a.out corrupted */
+"ELIBMAX ", /* 82 Attempting to link in too many shared libraries */
+"ELIBEXEC ", /* 83 Cannot exec a shared library directly */
+"EILSEQ ", /* 84 Illegal byte sequence */
+"ERESTART ", /* 85 Interrupted system call should be restarted */
+"ESTRPIPE ", /* 86 Streams pipe error */
+"EUSERS ", /* 87 Too many users */
+"ENOTSOCK ", /* 88 Socket operation on non-socket */
+"EDESTADDRREQ ", /* 89 Destination address required */
+"EMSGSIZE ", /* 90 Message too long */
+"EPROTOTYPE ", /* 91 Protocol wrong type for socket */
+"ENOPROTOOPT ", /* 92 Protocol not available */
+"EPROTONOSUPPORT", /* 93 Protocol not supported */
+"ESOCKTNOSUPPORT", /* 94 Socket type not supported */
+"EOPNOTSUPP ", /* 95 Operation not supported on transport endpoint */
+"EPFNOSUPPORT ", /* 96 Protocol family not supported */
+"EAFNOSUPPORT ", /* 97 Address family not supported by protocol */
+"EADDRINUSE ", /* 98 Address already in use */
+"EADDRNOTAVAIL ", /* 99 Cannot assign requested address */
+"ENETDOWN ", /* 100 Network is down */
+"ENETUNREACH ", /* 101 Network is unreachable */
+"ENETRESET ", /* 102 Network dropped connection because of reset */
+"ECONNABORTED ", /* 103 Software caused connection abort */
+"ECONNRESET ", /* 104 Connection reset by peer */
+"ENOBUFS ", /* 105 No buffer space available */
+"EISCONN ", /* 106 Transport endpoint is already connected */
+"ENOTCONN ", /* 107 Transport endpoint is not connected */
+"ESHUTDOWN ", /* 108 Cannot send after transport endpoint shutdown */
+"ETOOMANYREFS ", /* 109 Too many references: cannot splice */
+"ETIMEDOUT ", /* 110 Connection timed out */
+"ECONNREFUSED ", /* 111 Connection refused */
+"EHOSTDOWN ", /* 112 Host is down */
+"EHOSTUNREACH ", /* 113 No route to host */
+"EALREADY ", /* 114 Operation already in progress */
+"EINPROGRESS ", /* 115 Operation now in progress */
+"ESTALE ", /* 116 Stale NFS file handle */
+"EUCLEAN ", /* 117 Structure needs cleaning */
+"ENOTNAM ", /* 118 Not a XENIX named type file */
+"ENAVAIL ", /* 119 No XENIX semaphores available */
+"EISNAM ", /* 120 Is a named type file */
+"EREMOTEIO ", /* 121 Remote I/O error */
+"EDQUOT ", /* 122 Quota exceeded */
+"ENOMEDIUM ", /* 123 No medium found */
+"EMEDIUMTYPE " /* 124 Wrong medium type */
+};
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int i, err;
+ int label = 0;
+ int message = 0;
+ /*
+ * Input section: decode parameters passed in the calling
+ * Use getopt function
+ */
+ opterr = 0; /* don't want writing to stderr */
+ while ( (i = getopt(argc, argv, "hlm")) != -1) {
+ switch (i) {
+ /*
+ * Handling options
+ */
+ case 'h':
+ printf("Wrong -h option use\n");
+ usage();
+ return(0);
+ break;
+ case 'l': /* unrecognized options */
+ printf("Label printing\n");
+ label = 1;
+ break;
+ case 'm': /* unrecognized options */
+ printf("Message printing\n");
+ message = 1;
+ break;
+ case '?': /* unrecognized options */
+ printf("Unrecognized options -%c\n",optopt);
+ usage();
+ default: /* should not reached */
+ usage();
+ }
+ }
+ /* ***********************************************************
+ *
+ * Options processing completed
+ *
+ * Main code beginning
+ *
+ * ***********************************************************/
+ if (optind == argc) {
+ usage();
+ }
+ err = atoi(argv[optind]);
+ if (message) {
+ printf("Error message for %d is %s\n", err, strerror(err));
+ }
+ if (label) {
+ printf("Error label for %d is %s\n", err, err_code[err]);
+ }
+ if ( (!label)&&(!message) ) {
+ usage();
+ }
+ /* normal exit */
+ return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+ printf("Print error code message or macro label \n");
+ printf("Usage:\n");
+ printf(" daytime [-h] [-l] [-m] error code \n");
+ printf(" -m print error messages\n");
+ printf(" -l print error code label\n");
+ printf(" -h print this help\n");
+ exit(1);
+}
--- /dev/null
+/****************************************************************
+ *
+ * Program ForkTest.c:
+ * Program to test process creation
+ *
+ * Author: Simone Piccardi
+ * Sep. 2001
+ *
+ * Usage: forktest -h give all info's
+ *
+ * $Id: ForkTest.c,v 1.1 2001/09/09 17:39:15 piccardi Exp $
+ *
+ ****************************************************************/
+/*
+ * Include needed headers
+ */
+#include <errno.h> /* error definitions and routines */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h> /* unix standard library */
+#include <stdio.h> /* standard I/O library */
+#include <string.h> /* string functions */
+
+/* Help printing routine */
+void usage(void);
+
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int i;
+ int nchild;
+ pid_t pid;
+ /*
+ * Input section: decode command line parameters
+ * Use getopt function
+ */
+ opterr = 0; /* don't want writing to stderr */
+ while ( (i = getopt(argc, argv, "h")) != -1) {
+ switch (i) {
+ /*
+ * Handling options
+ */
+ case 'h':
+ printf("Wrong -h option use\n");
+ usage();
+ return(0);
+ break;
+ case '?': /* unrecognized options */
+ printf("Unrecognized options -%c\n",optopt);
+ usage();
+ default: /* should not reached */
+ usage();
+ }
+ }
+ /* ***********************************************************
+ *
+ * Options processing completed
+ *
+ * Main code beginning
+ *
+ * ***********************************************************/
+ /* There must be remaing parameters */
+ if (optind == argc) {
+ usage();
+ }
+ nchild = atoi(argv[optind]);
+ printf("Test for forking %d child\n", nchild);
+ /* loop to fork children */
+ for (i=0; i<nchild; i++) {
+ if ( (pid = fork()) < 0) {
+ printf("Error on %d child creation, %s\n", i, strerror(errno));
+ }
+ if (pid == 0) { /* child */
+ printf("Child %d successfully executing\n", i++);
+ sleep(2);
+ printf("Child %d exiting\n", i);
+ exit(0);
+ } else { /* parent */
+ printf("Spawned %d child, pid %d \n", i, pid);
+ }
+ }
+ /* normal exit */
+ return 0;
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+ printf("Program forktest: fork a given number of child \n");
+ printf("Usage:\n");
+ printf(" forktest [-h] child to fork \n");
+ printf(" -h print this help\n");
+ exit(1);
+}
OBJ = SockRead.o SockWrite.o
+forktest: ForkTest.c
+ $(CC) $(CFLAGS) $^ -o $@
+
+errcode: ErrCode.c
+ $(CC) $(CFLAGS) $^ -o $@
+
echo: SimpleEchoTCPClient.c $(OBJ)
- $(CC) $(CFLAGS) SimpleEchoTCPClient.c $(OBJ) -o echo
+ $(CC) $(CFLAGS) $^ -o $@
echod: SimpleEchoTCPServer.c $(OBJ)
- $(CC) $(CFLAGS) SimpleEchoTCPServer.c $(OBJ) -o echod
+ $(CC) $(CFLAGS) $^ -o $@
daytimed: ElemDaytimeTCPCuncServ.c
- $(CC) $(CFLAGS) ElemDaytimeTCPCuncServ.c -o daytimed
+ $(CC) $(CFLAGS) $^ -o $@
iterdaytimed: SimpleDaytimeTCPServer.c
- $(CC) $(CFLAGS) SimpleDaytimeTCPServer.c -o iterdaytimed
+ $(CC) $(CFLAGS) $^ -o $@
daytime: SimpleDaytimeTCPClient.c
- $(CC) $(CFLAGS) SimpleDaytimeTCPClient.c -o daytime
+ $(CC) $(CFLAGS) $^ -o $@
$(OBJ): wrappers.h
.PHONY : clean
clean:
- rm -f daytime iterdaytimed daytimed echod echo
+ rm -f daytime iterdaytimed daytimed echod echo errcode
rm -f *~
rm -f *.o
- rm -f daytime