From: Simone Piccardi Date: Mon, 27 May 2002 16:16:11 +0000 (+0000) Subject: Modifiche fatte in treno X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=d7305d300866c1e6909dd23743060632b3718178;p=gapil.git Modifiche fatte in treno --- diff --git a/signal.tex b/signal.tex index b60b905..411538c 100644 --- a/signal.tex +++ b/signal.tex @@ -1401,7 +1401,7 @@ la creazione di zombie. #include #include "macro.h" -void Hand_CHLD(int sig) +void sigchld_hand(int sig) { int errno_save; int status; diff --git a/simpltcp.tex b/simpltcp.tex index 4da8e81..4c812d3 100644 --- a/simpltcp.tex +++ b/simpltcp.tex @@ -47,8 +47,8 @@ La prima versione del server, \file{ElemEchoTCPServer.c}, si compone di un corpo principale, costituito dalla funzione \code{main}. Questa si incarica di creare il socket, metterlo in ascolto di connessioni in arrivo e creare un processo figlio a cui delegare la gestione di ciascuna connessione. Questa -parte, riportata in \nfig, è analoga a quella vista nel precedente esempio -esaminato in \secref{sec:TCPel_cunc_serv}. +parte, riportata in \figref{fig:TCPsimpl_serv_code}, è analoga a quella vista +nel precedente esempio esaminato in \secref{sec:TCPel_cunc_serv}. \begin{figure}[!htb] \footnotesize @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) int list_fd, conn_fd; pid_t pid; struct sockaddr_in serv_add; - .... + ... /* create socket */ if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket creation error"); @@ -114,9 +114,9 @@ int main(int argc, char *argv[]) La struttura di questa prima versione del server è sostanzialmente identica a quella dell'esempio citato, ed ad esso si applicano le considerazioni fatte in \secref{sec:TCPel_cunc_daytime}. Le uniche differenze rispetto all'esempio in -\figref{fig:TCPel_serv_code} sono che in questo caso per il socket in -ascolto viene usata la porta 7 e tutta la gestione della comunicazione è -delegata alla funzione \code{ServEcho}. +\figref{fig:TCPel_serv_code} sono che in questo caso per il socket in ascolto +viene usata la porta 7 e che tutta la gestione della comunicazione è delegata +alla funzione \code{ServEcho}. % Per ogni connessione viene creato un % processo figlio, il quale si incarica di lanciare la funzione % \texttt{SockEcho}. @@ -125,12 +125,11 @@ Il codice della funzione \code{ServEcho} comunicazione viene gestita all'interno del ciclo (linee \texttt{\small 6--8}). I dati inviati dal client vengono letti dal socket con una semplice \func{read} (che ritorna solo in presenza di dati in arrivo), la riscrittura -viene invece gestita dalla funzione \func{SockWrite} (descritta a suo tempo -in \figref{fig:sock_SockWrite_code}) che si incarica di tenere conto +viene invece gestita dalla funzione \func{SockWrite} (descritta in +\figref{fig:sock_SockWrite_code}) che si incarica di tenere conto automaticamente della possibilità che non tutti i dati di cui è richiesta la scrittura vengano trasmessi con una singola \func{write}. - \begin{figure}[!htb] \footnotesize \begin{lstlisting}{} @@ -159,11 +158,11 @@ del processo figlio. \subsection{Il client} \label{sec:TCPsimp_client_main} -Il codice del client è riportato in \nfig, anche esso ricalca la struttura del -precedente client per il servizio \texttt{daytime} (vedi -\secref{sec:net_cli_sample}) ma, come per il server, lo si è diviso in due -parti, inserendo la parte relativa alle operazioni specifiche previste per il -protocollo \texttt{echo} in una funzione a parte. +Il codice del client è riportato in \figref{fig:TCPsimpl_client_elem}, anche +esso ricalca la struttura del precedente client per il servizio +\texttt{daytime} (vedi \secref{sec:net_cli_sample}) ma, come per il server, lo +si è diviso in due parti, inserendo la parte relativa alle operazioni +specifiche previste per il protocollo \texttt{echo} in una funzione a parte. \begin{figure}[!htb] \footnotesize \begin{lstlisting}{} @@ -210,11 +209,12 @@ in \secref{sec:net_cli_sample}, il client si connette sulla porta 7 all'indirizzo specificato dalla linea di comando (a cui si è aggiunta una elementare gestione delle opzioni non riportata in figura). -Completata la connessione (quando la funzione \func{connect} ritorna) la -funzione \code{ClientEcho}, riportata in \nfig, si preoccupa di gestire la +Completata la connessione, al ritrno fiììdi \func{connect} è ritornata, la +funzione \code{ClientEcho}, riportata in +\figref{fig:TCPsimpl_client_echo_sub}, si preoccupa di gestire la comunicazione, leggendo una riga alla volta dallo \file{stdin}, scrivendola sul socket e ristampando su \file{stdout} quanto ricevuto in risposta dal -server. +server. \begin{figure}[!htb] \footnotesize @@ -266,7 +266,7 @@ nello scrivere un'applicazione di rete. Infatti attraverso l'esame delle sue modalità di funzionamento normali, all'avvio e alla terminazione, e di quello che avviene nelle varie situazioni limite, da una parte potremo approfondire la comprensione del protocollo TCP/IP e dall'altra ricavare le indicazioni -necessarie per essere in gradi di scrivere applicazioni robuste, in grado di +necessarie per essere in grado di scrivere applicazioni robuste, in grado di gestire anche i casi limite. @@ -326,14 +326,16 @@ un risultato del tipo: 2359 pts/0 S 0:00 ./echod \end{verbatim} %$ (dove si sono cancellate le righe inutili) da cui si evidenzia la presenza di -tre processi, tutti in stato di \textit{sleep} (S). +tre processi, tutti in stato di \textit{sleep} (vedi +\tabref{tab:proc_proc_states}). -Se a questo punto si inizia a scrivere qualcosa sul client niente sarà -trasmesso fin tanto che non si prema il ritorno carrello (si ricordi quanto -trattato in \secref{sec:file_line_io}), allora la \func{fgets} ritornerà e a -questo punto il client scriverà quanto immesso sul socket, poi rileggerà -quanto gli viene inviato all'indietro dal server, e questo sarà inviato sullo -standard output, che nel caso ne provoca l'immediatamente stampa a video. +Se a questo punto si inizia a scrivere qualcosa sul client non sarà trasmesso +niente fin tanto che non si prema il tasto di a capo (si ricordi quanto detto +in \secref{sec:file_line_io} a proposito dell'I/O su terminale), solo allora +\func{fgets} ritornerà ed il client scriverà quanto immesso sul socket, per +poi passare a rileggere quanto gli viene inviato all'indietro dal server, che +a sua volta sarà inviato sullo standard output, che nel caso ne provoca +l'immediatamente stampa a video. \subsection{La conclusione normale} @@ -360,13 +362,13 @@ tcp 0 0 localhost:33032 localhost:echo TIME_WAIT con il client che entra in \texttt{TIME\_WAIT}. Esaminiamo allora in dettaglio la sequenza di eventi che porta alla -terminazione normale della connessione, che ci servirà poi da riferimento nei -casi seguenti: +terminazione normale della connessione, che ci servirà poi da riferimento +quando affronteremo il comportamento in caso di conclusioni anomale: \begin{enumerate} \item inviando un carattere di EOF da terminale la \func{fgets} ritorna restituendo un puntatore nullo che causa l'uscita dal ciclo di - while, così la \code{ClientEcho} ritorna. + \code{while}, così la \code{ClientEcho} ritorna. \item al ritorno di \code{ClientEcho} ritorna anche la funzione \code{main}, e come parte del processo terminazione tutti i file descriptor vengono chiusi (si ricordi quanto detto in \secref{sec:proc_term_conclusion}); questo causa @@ -377,14 +379,14 @@ casi seguenti: \secref{sec:TCPel_conn_term}). \item quando il server riceve il FIN la \func{read} del processo figlio che gestisce la connessione ritorna restituendo 0 causando così l'uscita dal - ciclo di while e il ritorno di \code{ServEcho}, a questo punto il processo - figlio termina chiamando \func{exit}. + ciclo e il ritorno di \code{ServEcho}, a questo punto il processo figlio + termina chiamando \func{exit}. \item all'uscita del figlio tutti i file descriptor vengono chiusi, la chiusura del socket connesso fa sì che venga effettuata la sequenza finale di chiusura della connessione, viene emesso un FIN dal server che riceverà un ACK dal client, a questo punto la connessione è conclusa e il client resta nello stato \texttt{TIME\_WAIT}. -\item + \end{enumerate} @@ -412,8 +414,23 @@ processo (si veda \secref{sec:proc_wait}), cosa che faremo utilizzando La prima modifica al nostro server è pertanto quella di inserire la gestione della terminazione dei processi figli attraverso l'uso di un manipolatore. -Per questo usiamo la funzione \code{Signal} illustrata in -\figref{fig:sig_Signal_code}. +Per questo useremo la funzione \code{Signal}, illustrata in +\figref{fig:sig_Signal_code}, per installare il semplice manipolatore che +riceve i segnali dei processi figli terminati già visto in +\figref{fig:sig_sigchld_handl}; aggiungendo il seguente codice: +\begin{lstlisting}{} + ... + /* install SIGCHLD handler */ + Signal(SIGCHLD, sigchld_hand); /* establish handler */ + /* create socket */ + ... +\end{lstlisting} + +\noindent +all'esempio illustrato in \figref{fig:TCPsimpl_serv_code}, e linkando il tutto +alla funzione \code{sigchld\_hand}, si risolverà completamente il problema +degli zombie. + %%% Local Variables: