From: Simone Piccardi Date: Tue, 9 Jul 2002 22:20:26 +0000 (+0000) Subject: Correzioni varie e aggiunte sulle fifo X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=76ddae490a29dac41729cfae51f76e5c9987a484 Correzioni varie e aggiunte sulle fifo --- diff --git a/fileadv.tex b/fileadv.tex index 7442379..b376483 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -28,7 +28,6 @@ I/O possono bloccarsi indefinitamente.\footnote{si ricordi per esempio le operazioni di lettura possono bloccarsi quando non ci sono dati disponibili sul descrittore su cui si sta operando. - Questo comportamento causa uno dei problemi più comuni che ci si trova ad affrontare nelle operazioni di I/O, che è quello che si verifica quando si devono eseguire operazioni che possono bloccarsi su più file descriptor: @@ -59,7 +58,7 @@ bloccante. Per superare il problema di dover usare il \textit{polling} controllare la disponibilità di accesso ad un file aperto in modalità non bloccante, sia BSD -che SysV hanno introdotto delle nuove funzioni in grado di sospendere +che System V hanno introdotto delle nuove funzioni in grado di sospendere l'esecuzione di un processo fino a che l'accesso diventi possibile; il primo ad introdurre questa nuova interfaccia, chiamata usualmente \textit{I/O multiplexing}, è stato BSD, con l'introduzione della funzione \func{select}, @@ -75,7 +74,7 @@ Attende che un certo insieme di file descriptor cambi stato. qual caso \var{errno} viene settata ai valori: \begin{errlist} \item[\macro{EBADF}] Si è specificato un file descriptor sbagliato in uno - degeli insiemi. + degli insiemi. \item[\macro{EINTR}] La funzione è stata interrotta da un segnale. \item[\macro{EINVAL}] Si è specificato per \param{n} un valore negativo. \end{errlist} @@ -115,8 +114,7 @@ In genere un \textit{file descriptor set} pu il limite del numero massimo di file aperti\footnote{ad esempio in Linux, fino alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma quando, come nelle versioni più recenti del kernel, questo limite non c'è un massimo, -esso indica le dimensioni in munero di bit utilizzabili per l'insieme. - +esso indica le dimensioni in numero di bit utilizzabili per l'insieme. La funzione richiede di specificare tre insiemi distinti di file descriptor; il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di @@ -186,7 +184,7 @@ riporta il file descriptor che ha generato il segnale. \section{Il file locking} \label{sec:file_locking} -In \secref{sec:file_sharing} abbiamo preso in esame le mosalità in cui un +In \secref{sec:file_sharing} abbiamo preso in esame le modalità in cui un sistema unix-like gestisce la condivisione dei file da parte di processi diversi. In quell'occasione si è visto come, con l'eccezione dei file aperti in \textit{append mode}, quando più processi scrivono contemporaneamente sullo @@ -196,7 +194,7 @@ Questo causa la possibilit generale le situazioni più comuni sono due: l'interazione fra un processo che scrive e altri che leggono, in cui questi ultimi possono leggere informazioni scritte solo in maniera parziale o incompleta; o quella in cui diversi -processi scrivono, mescolando in maniera imprevedebile il loro output sul +processi scrivono, mescolando in maniera imprevedibile il loro output sul file. In tutti questi casi il \textit{file locking} è la tecnica che permette di diff --git a/ipc.tex b/ipc.tex index c16d5c3..d8703b1 100644 --- a/ipc.tex +++ b/ipc.tex @@ -125,7 +125,7 @@ da altri processi. Per capire meglio il funzionamento di una pipe faremo un esempio di quello che è il loro uso più comune, analogo a quello effettuato della shell, e che consiste nell'inviare l'output di un processo (lo standard output) sull'input -di un'altro. Realizzaremo il programma nella forma di un +di un'altro. Realizzeremo il programma nella forma di un \textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un programma che permette la creazione dinamica di un oggetto da inserire all'interno di una pagina HTML.} per apache, che genera una immagine JPEG di un codice a @@ -168,7 +168,8 @@ file.\footnote{il problema potrebbe essere superato determinando in anticipo un nome appropriato per il file temporaneo, che verrebbe utilizzato dai vari sotto-processi, e cancellato alla fine della loro esecuzione; ma a questo le cose non sarebbero più tanto semplici.} L'uso di una pipe invece permette -di risolvere il problema in maniera semplice ed elegante. +di risolvere il problema in maniera semplice ed elegante, oltre ad essere +molto più efficiente, dato che non si deve scrivere su disco. Il programma ci servirà anche come esempio dell'uso delle funzioni di duplicazione dei file descriptor che abbiamo trattato in @@ -523,8 +524,56 @@ stare molto attenti alla possibili deadlock.\footnote{se si cerca di leggere processo si blocca e non potrà quindi mai eseguire le funzioni di scrittura.} -L'impiego più comune per le fifo è quello che le vede impegnate con un -processo in +Per la loro caratteristica di essere accessibili attraverso il filesystem, è +piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle +situazioni un processo deve ricevere informazioni dagli altri. In questo caso +è fondamentale che le operazioni di scrittura siano atomiche; per questo si +deve sempre tenere presente che questo è vero soltanto fintanto che non si +supera il limite delle dimensioni di \macro{PIPE\_BUF} (si ricordi quanto +detto in \secref{sec:ipc_pipes}). + +A parte il precedente, che resta probabilmente il più comune, Stevens riporta +in \cite{APUE} altre due casistiche principali per l'uso delle fifo: +\begin{itemize} +\item Da parte dei comandi di shell, per evitare la creazione di file + temporanei quando si devono inviare i dati di uscita di un processo + sull'input di parecchi altri (attraverso l'uso del comando \cmd{tee}). + +\item Come canale di comunicazione fra un client ed un server (il modello + \textit{client-server} è illustrato in \secref{sec:net_cliserv}). +\end{itemize} + +Nel primo caso quello che si fa è creare tante pipe quanti sono i processi a +cui i vogliono inviare i dati, da usare come standard input per gli stessi; una +volta che li si saranno posti in esecuzione ridirigendo lo standard input si +potrà eseguire il processo iniziale replicandone, con il comando \cmd{tee}, +l'output sulle pipe. + +Il secondo caso è relativamente semplice qualora si debba comunicare con un +processo alla volta (nel qual caso basta usare due pipe, una per leggere ed +una per scrivere), le cose diventano invece molto più complesse quando si +vuole effettuare una comunicazione fra il server ed un numero imprecisato di +client; se il primo infatti può ricevere le richieste attraverso una fifo +``nota'', per le risposte non si può fare altrettanto, dato che per la +struttura sequenziale delle fifo, i client dovrebbero sapere, prima di +leggerli, quando i dati inviati sono destinati a loro. + +Per risolvere questo problema, si può usare un'architettura come quella +illustrata da Stevens in \cite{APUE}, in cui le risposte vengono inviate su +fifo temporanee identificate dal \acr{pid} dei client, ma in ogni caso il +sistema è macchinoso e continua ad avere vari inconvenienti\footnote{lo stesso + Stevens nota come sia impossibile per il server sapere se un client è andato + in crash, con la possibilità di far restare le fifo temporanee sul + filesystem, come sia necessario intercettare \macro{SIGPIPE} dato che un + client può terminare dopo aver fatto una richiesta, ma prima che la risposta + sia inviata, e come occorra gestire il caso in cui non ci sono client attivi + (e la lettura dalla fifo nota restituisca al serve un end-of-file.}; in +generale infatti l'interfaccia delle fifo non è adatta a risolvere questo tipo +di problemi, che possono essere affrontati in maniera più semplice ed efficace +o usando i \textit{socket}\index{socket} (che tratteremo in dettaglio a +partire da \capref{cha:socket_intro}) o ricorrendo a diversi meccanismi di +comunicazione, come quelli che esamineremo in \secref{sec:ipc_sysv}. + \section{La comunicazione fra processi di System V} @@ -532,11 +581,12 @@ processo in Benché le pipe (e le fifo) siano ancora ampiamente usate, esse presentano numerosi limiti, il principale dei quali è che il meccanismo di comunicazione -è rigidamente sequenziale; una situazione in cui un processo scrive qualcosa -che molti altri devono poter leggere non può essere implementata con una pipe. +è rigidamente sequenziale; per cui una situazione in cui un processo scrive +qualcosa che molti altri devono poter leggere non può essere implementata in +maniera semplice con una pipe. -Per superarne i vari limiti, nello sviluppo di System V vennero introdotti una -serie di nuovi oggetti di comunicazione e relative interfacce id +Per superarne questi limiti nello sviluppo di System V vennero introdotti una +serie di nuovi oggetti di comunicazione e relative interfacce di programmazione che garantissero una maggiore flessibilità; in questa sezione esamineremo quello che viene ormai chiamato il \textsl{Sistema di comunicazione inter-processo} di System V , più comunemente noto come diff --git a/network.tex b/network.tex index 7c0fbc7..49e4eb2 100644 --- a/network.tex +++ b/network.tex @@ -23,9 +23,9 @@ monolitico all'interno del quale vengono eseguite tutte le istruzioni, e presuppone un sistema operativo ``multitasking'' in grado di eseguire processi diversi. -Il concetto fondamentale si basa la programmazione di rete sotto Linux (e -sotto Unix in generale) è il modello \textit{client-server} in cui un -programma di servizio, il \textit{server} riceve un connessione e risponde a +Un concetto fondamentale su cui si basa la programmazione di rete sotto Linux +(e sotto Unix in generale) è il modello \textit{client-server} in cui un +programma di servizio, il \textit{server}, riceve una connessione e risponde a un programma di utilizzo, il \textit{client}, provvedendo a quest'ultimo un definito insieme di servizi. diff --git a/prochand.tex b/prochand.tex index e57e8ca..e3e08e4 100644 --- a/prochand.tex +++ b/prochand.tex @@ -386,9 +386,11 @@ sul numero totale di processi permessi all'utente (vedi L'uso di \func{fork} avviene secondo due modalità principali; la prima è quella in cui all'interno di un programma si creano processi figli cui viene affidata l'esecuzione di una certa sezione di codice, mentre il processo padre -ne esegue un'altra. È il caso tipico dei server di rete in cui il padre riceve -ed accetta le richieste da parte dei client, per ciascuna delle quali pone in -esecuzione un figlio che è incaricato di fornire il servizio. +ne esegue un'altra. È il caso tipico dei server (il modello +\textit{client-server} è illustrato in \secref{sec:net_cliserv}) di rete in +cui il padre riceve ed accetta le richieste da parte dei client, per ciascuna +delle quali pone in esecuzione un figlio che è incaricato di fornire il +servizio. La seconda modalità è quella in cui il processo vuole eseguire un altro programma; questo è ad esempio il caso della shell. In questo caso il processo