From: Simone Piccardi Date: Sat, 1 Jun 2002 20:33:31 +0000 (+0000) Subject: Deciso, si prosegue con le ipc X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=aa5d63f2af4475ae1188f695a33e4d0bee55f787 Deciso, si prosegue con le ipc --- diff --git a/fileadv.tex b/fileadv.tex index 6737554..fa41648 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1,78 +1,109 @@ -\chapter{I/O avanzato} +\chapter{La gestione avanzata dei file} \label{cha:file_advanced} -In questo capitolo affronteremo le tematiche della gestione avanzata delle -funzioni di input/ouput, prenderemo in esame il \textit{file locking}, la -gestione dell'input/output da più file, per concludere con la gestione dei -file mappati in memoria. +In questo capitolo affronteremo le tematiche relative alla gestione avanzata +dei file, che non sono state trattate in \capref{cha:file_unix_interface}, +dove ci si è limitati ad una panoramica delle funzioni base. In particolare +tratteremo delle funzioni di input/output avanzato e del \textit{file + locking}. -\section{L'I/O avanzato} +\section{Le funzioni di I/O avanzato} \label{sec:file_advanced_io} -Uno dei problemi che ci si trova ad affrontare con le funzioni ordinarie -trattate in \capref{cha:file_unix_interface} è quello in cui si devono -eseguire su più di un file descriptor delle operazioni che possono bloccarsi: -il problema è che mentre si è bloccati su un file su di un'altro potrebbero -essere presenti dati da leggere. - -In questa sezione vedremo come si possono affrontare queste problematiche, -quali sono le soluzioni possibili e quali i meccanismi il kernel e le librerie -ci mettono a disposizione. +In questa sezione esamineremo le funzioni che permettono una gestione più +sofisticata dell'I/O su file, a partire da quelle che permettono di gestire +l'accesso contemporaneo a più file, per concludere con la gestione dell'I/O +mappato in memoria. \subsection{La modalità di I/O \textsl{non-bloccante}} \label{sec:file_noblocking} -Una prima soluzione per evitare di bloccarsi nelle operazioni di I/O è quella -di utilizzare la modalità \textsl{non-bloccante}. Abbiamo visto in -\secref{sec:sig_gen_beha}, affrontando la suddivisione fra \textit{fast} e -\textit{slow} system call, che in certi casi le funzioni di I/O possono -bloccarsi indefinitamente.\footnote{si ricordi però che questo può accadere - solo per le pipe, i socket ed alcuni file di dispositivo; sui file normali - le funzioni di lettura e scrittura ritornano sempre subito.} -In particolare le operazioni di lettura possono bloccarsi quando non ci sono -dati disponibili sul descrittore su cui si sta operando. +Abbiamo visto in \secref{sec:sig_gen_beha}, affrontando la suddivisione fra +\textit{fast} e \textit{slow} system call, che in certi casi le funzioni di +I/O possono bloccarsi indefinitamente.\footnote{si ricordi però che questo può + accadere solo per le pipe, i socket ed alcuni file di dispositivo; sui file + normali le funzioni di lettura e scrittura ritornano sempre subito.} Ad +esempio le operazioni di lettura possono bloccarsi quando non ci sono dati +disponibili sul descrittore su cui si sta operando. + +Uno dei problemi più comuni che ci si trova ad affrontare che non può essere +risolto con le funzioni base trattate in \capref{cha:file_unix_interface} è +quello in cui si devono eseguire su più di un file descriptor delle operazioni +che possono bloccarsi: il problema è che mentre si è bloccati su uno di questi +file su di un'altro potrebbero essere presenti dei dati. Abbiamo già accennato in \secref{sec:file_open} che è possibile prevenire -questo tipo di comportamento aprendo il file in modalità non bloccante, -specificando il flag \macro{O\_NONBLOCK}. In questo caso le funzioni che si -sarebbero bloccate ritornano immediatamente restituendo l'errore +questo tipo di comportamento aprendo un file in modalità +\textsl{non-bloccante}, specificando il flag \macro{O\_NONBLOCK} alla chiamata +di \func{open}. In questo caso le funzioni di input/output che altrimenti si +sarebbero bloccate ritornano immediatamente, restituendo l'errore \macro{EAGAIN}. -L'utilizzo di questa modalità di I/O permette allora di risolvere il problema +L'utilizzo di questa modalità di I/O permette allora di risolvere il problema +controllando a turno i vari file descriptor, in un ciclo in cui si ripete +l'accesso fintanto che esso non viene garantito. Ovviamente questa tecnica, +detta \textit{polling}, è estremamente inefficiente: si tiene costantemente +impiegata la CPU solo per eseguire in continuazione delle system call che +nella gran parte dei casi falliranno. + +Per questo motivo, quando come vedremo in dettaglio in +\secref{sec:file_multiplexing}, il sistema fornisce delle funzioni apposite +che permettono di aggirare questo problema, permettendo di attendere fino alla +disponibilità di un accesso; per usarle però è comunque comunque necessario +utilizzare la modalità di I/O non bloccante. + +\subsection{Le funzioni \func{poll} e \func{select}} +\label{sec:file_multiplexing} %\section{I/O asincrono} %\label{sec:file_asynchronous} %Non supportato in Linux, in BSD e SRv4 c'è, ma usando il segnale \macro{SIGIO} -%per indicare che i dati sono disponibili, può essere usato in maniera semplice -%con un solo file per processo (altrimenti non sarebbe più possibile -%distinguere da quale file proviene l'attività che ha causato l'emissione del -%segnale). +%per indicare che i dati sono disponibili, \subsection{L'I/O asincrono} \label{sec:file_asyncronous_io} +Una modalità alternativa all'uso dell'I/O non bloccante è quella di fare +ricorso all'I/O asincrono. Abbiamo accennato in \secref{sec:file_open} che è +possibile, attraverso l'uso del flag \macro{O\_ASYNC}, aprire un file in +modalità asincrona, così come è possibile settare questo flag attraverso l'uso +di \func{fcntl}. + +In tal caso il sistema genera un segnale \macro{SIGIO} tutte le volte che sono +presenti dei dati in input sul file. -\subsection{Le funzioni \func{poll} e \func{select}} -\label{sec:file_multiplexing} +Un dei problemi che si presentavano con le prime implementazioni di questa +modalità di I/O è che essa poteva essere usata in maniera semplice con un solo +file per processo, dato che altrimenti non sarebbe stato distinguere da quale +file proviene l'attività che ha causato l'emissione del segnale. -\section{File locking} +\subsection{File mappati in memoria} +\label{sec:file_memory_map} + + +\subsection{I/O multiplo} +\label{sec:file_multiple_io} + + + +\section{Il file locking} \label{sec:file_locking} In \secref{sec:file_sharing} abbiamo preso in esame le mosalità in cui un -sistema unix-like gestisce la condivisione dei file. In quell'occasione si è -visto come, con l'eccezione dei file aperti in \textit{append mode}, quando -più processi scrivono contemporaneamente sullo stesso file non è possibile -determinare la sequenza in cui essi opereranno. +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 +stesso file non è possibile determinare la sequenza in cui essi opereranno. Questo causa la possibilità di race condition; in generale le situazioni più comuni sono due: l'interazione fra un processo che scrive e altri che leggono, @@ -82,11 +113,11 @@ in maniera imprevedebile il loro output sul file. In tutti questi casi il \textit{file locking} è la tecnica che permette di evitare le race condition, attraverso una serie di funzioni che permettono di -bloccare l'accesso al file da parte di altri processi così da evitare le +bloccare l'accesso al file da parte di altri processi, così da evitare le sovrapposizioni, e garantire la atomicità delle operazioni di scrittura. -\subsection{Il \textit{advisory locking}} +\subsection{L'\textit{advisory locking}} \label{sec:file_record_locking} La prima modalità di file locking che è stata implementata nei sistemi @@ -100,14 +131,11 @@ esiste una condizione di blocco per l'accesso ai file. \subsection{Il \textit{mandatory locking}} \label{sec:file_mand_locking} -Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVR4, +Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4, -\section{File mappati in memoria} -\label{sec:file_memory_map} - %%% Local Variables: diff --git a/fileunix.tex b/fileunix.tex index 7f970c7..a8a7d78 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -271,9 +271,10 @@ sempre il file descriptor con il valore pi le fifo e per alcuni file di dispositivo. \\ \macro{O\_NDELAY} & in Linux\footnotemark\ è sinonimo di \macro{O\_NONBLOCK}.\\ - \macro{O\_ASYNC} & apre il file per l'input/output in modalità - asincrona. Quando è settato viene generato un segnale di \macro{SIGIO} - tutte le volte che è disponibile dell'input sul file. \\ + \macro{O\_ASYNC} & apre il file per l'I/O in modalità + asincrona (vedi \secref{sec:file_asyncronous_io}). Quando è settato viene + generato il segnale \macro{SIGIO} tutte le volte che sono disponibili + dati in input sul file. \\ \macro{O\_SYNC} & apre il file per l'input/output sincrono, ogni \func{write} bloccherà fino al completamento della scrittura di tutti dati sul sull'hardware sottostante.\\ @@ -1007,11 +1008,13 @@ valori segnali \macro{SIGIO} e \macro{SIGURG} per gli eventi associati al file descriptor \var{fd}. I process group sono settati usando valori negativi. \item[\macro{F\_GETSIG}] restituisce il segnale mandato quando ci sono dati - disponibili in input sul file descriptor. Il valore 0 indica il default (che - è \macro{SIGIO}), un valore diverso da zero indica il segnale richiesto, - (che può essere lo stesso \macro{SIGIO}), nel qual caso al manipolatore del - segnale, se installato con \macro{SA\_SIGINFO}, vengono rese disponibili - informazioni ulteriori informazioni. + disponibili in input su un file descriptor aperto o settato in I/O + asincrono. Il valore 0 indica il default (che è \macro{SIGIO}), un valore + diverso da zero indica il segnale richiesto, (che può essere lo stesso + \macro{SIGIO}).\footnote{in questo caso al manipolatore del segnale, se + installato come \var{sa\_sigaction} con \macro{SA\_SIGINFO}, vengono rese + disponibili informazioni ulteriori informazioni (vedi + \secref{sec:sig_sigaction} e \secref{sec:file_asyncronous_io})}. \item[\macro{F\_SETSIG}] setta il segnale da inviare quando diventa possibile effettuare I/O sul file descriptor. Il valore zero indica il default (\macro{SIGIO}), ogni altro valore permette di rendere disponibile al diff --git a/gapil.tex b/gapil.tex index 06791aa..dc2c43a 100644 --- a/gapil.tex +++ b/gapil.tex @@ -114,9 +114,9 @@ \include{filestd} \include{system} \include{signal} +\include{ipc} \include{fileadv} \include{session} -\include{ipc} \include{network} \include{socket} \include{elemtcp} diff --git a/ipc.tex b/ipc.tex index 6c1041e..24ec8f4 100644 --- a/ipc.tex +++ b/ipc.tex @@ -3,16 +3,17 @@ Uno degli aspetti fondamentali della programmazione in un sistema unix-like è -la comunicazione fra processi. In questo capitolo affronteremo solo alcuni dei +la comunicazione fra processi. In questo capitolo affronteremo solo i meccanismi più elementari che permettono di mettere in comunicazione processi diversi, come quelli tradizionali che coinvolgono \textit{pipe} e \textit{fifo} e i meccanismi di intercomunicazione di System V. -Esistono pure sistemi più complessi ed evoluti come le RPC (\textit{Remote - Procedure Calls}) e CORBA (\textit{Common Object Request Brocker - Architecture}) che non saranno affrontati qui. Inoltre tratteremo nei -capitoli successivi tutta la problematica relativa alla comunicazione -attraverso la rete. +Tralasceremo invece tutte le problematiche relative alla comunicazione +attraverso la rete (e le relative interfacce) che saranno affrontate in gran +dettaglio in un secondo tempo. Non affronteremo invece meccanismi più +complessi ed evoluti come le RPC (\textit{Remote Procedure Calls}) e CORBA +(\textit{Common Object Request Brocker Architecture}) che in genere sono +implementati con un ulteriore livello sopra i meccanismi elementari. @@ -27,18 +28,36 @@ funzioni che ne gestiscono l'uso e le varie forme in cui si \subsection{Le \textit{pipe} standard} \label{sec:ipc_pipes} -Le \textit{pipe} nascono sostanzialmente con Unix, e sono il primo, e più -comunemente usato, meccanismo di comunicazione fra processi. Esse sono un file -speciale in cui un processo scrive ed un altro legge. Si viene così a -costituire un canale di comunicazione fra i due processi, nella forma di un -\textsl{tubo} (da cui il nome) in cui uno immette dati che arriveranno -all'altro. - -Perché questo accada però, e questo è il principale limite nell'uso delle -\textit{pipe}, è necessario che questi processi possano condividere il file -descriptor della \textit{pipe}; per questo essi devono comunque derivare da -uno stesso processo padre, o, più comunemente, essere nella relazione -padre/figlio. +Le \textit{pipe} nascono sostanzialmente con Unix, e sono il primo, ed uno dei +più usati, meccanismi di comunicazione fra processi. Si tratta in sostanza uno +speciale tipo di file\footnote{più precisamente un file descriptor; le pipe + sono create dal kernel e non risiedono su disco.} in cui un processo scrive +ed un altro legge. Si viene così a costituire un canale di comunicazione fra i +due processi, nella forma di un \textsl{tubo} (da cui il nome) in cui uno dei +processi immette dati che poi arriveranno all'altro. + +Perché questo accada però, e questo è il principale\footnote{Stevens riporta + in APUE come limite anche il fatto che la comunicazione è unidirezionale, in + realtà questo è un limite facilemente risolvibile usando una coppia di + \textit{pipe}.} e limite nell'uso delle \textit{pipe}, è necessario che +questi processi possano condividere il file descriptor della \textit{pipe}; +per questo essi devono comunque derivare da uno stesso processo padre, o, più +comunemente, essere nella relazione padre/figlio. + +La funzione che permette di creare una \textit{pipe} è appunto \func{pipe}; il +suo prototipo è: +\begin{prototype}{unistd.h} +{int pipe(int filedes[2])} + +Crea una coppia di file descriptor associati ad una \textit{pipe}. + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, nel qual caso \var{errno} potrà assumere i valori \macro{EMFILE}, + \macro{ENFILE} e \macro{EFAULT}.} +\end{prototype} + +La funzione restituisce una coppia di file descriptor nell'array +\param{filedes}; il primo aperto in lettura ed il secondo in scrittura @@ -58,17 +77,18 @@ per le comunicazioni senza dovere per forza essere in relazione diretta. \label{sec:ipc_sysv} Per ovviare ai vari limiti dei meccanismo tradizionale di comunicazione fra -processi basato sulle \textit{pipe}, nello sviluppo di System V vennero -introdotti una serie di nuovi oggetti che garantissero una maggiore -flessibilità; in questa sezione esamineremo quello che viene ormai chiamato il -\textit{System V Inter Process Comunication system}, più comunemente noto come -\textit{SystemV IPC}. +processi visto in \secref{sec:ipc_unix}, nello sviluppo di System V vennero +introdotti una serie di nuovi oggetti e relative interdacce che garantissero +una maggiore flessibilità; in questa sezione esamineremo quello che viene +ormai chiamato il \textit{System V Inter-Process Comunication System}, più +comunemente noto come \textit{SystemV IPC}. + \subsection{Code di messaggi} \label{sec:ipc_messque} Il primo oggetto introdotto dal \textit{SystemV IPC} è quello delle code di -messaggi. +messaggi. \subsection{Semafori} \label{sec:ipc_semaph} diff --git a/signal.tex b/signal.tex index 411538c..519cf44 100644 --- a/signal.tex +++ b/signal.tex @@ -1801,9 +1801,45 @@ indicate dai campi \var{sa\_handler} e \var{sa\_sigaction}; esse devono essere usate in maniera alternativa (in certe implementazioni questi vengono specificati come \ctyp{union}): la prima è quella classica usata anche con \func{signal}, la seconda permette invece di usare un manipolatore in grado di -ricevere informazioni più dettagliate dal sistema (ad esempio il tipo di -errore in caso di \macro{SIGFPE}), attraverso dei parametri aggiuntivi; per i -dettagli si consulti la man page di \func{sigaction}). +ricevere informazioni più dettagliate dal sistema, attraverso la struttura +\var{siginfo\_t}, riportata in \figref{fig:sig_siginfo_t}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} +siginfo_t { + int si_signo; /* Signal number */ + int si_errno; /* An errno value */ + int si_code; /* Signal code */ + pid_t si_pid; /* Sending process ID */ + uid_t si_uid; /* Real user ID of sending process */ + int si_status; /* Exit value or signal */ + clock_t si_utime; /* User time consumed */ + clock_t si_stime; /* System time consumed */ + sigval_t si_value; /* Signal value */ + int si_int; /* POSIX.1b signal */ + void * si_ptr; /* POSIX.1b signal */ + void * si_addr; /* Memory location which caused fault */ + int si_band; /* Band event */ + int si_fd; /* File descriptor */ +} + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La struttura \var{siginfo\_t}.} + \label{fig:sig_siginfo_t} +\end{figure} + +Installando un manipolatore di tipo \var{sa\_sigaction} diventa allora +possibile accedere al risultato restituito attraverso il puntatore a questa +struttura. Tutti i segnali settano i campi \var{si\_signo}, \var{si\_errno} e +\var{si\_code}, ed il resto della struttura può essere definito come +\ctyp{union} ed i valori eventualmente presenti dipendono dal segnale (ad +esempio può essere il tipo di errore nel caso di \macro{SIGFPE}); vedremo un +esempio di tutto ciò per \macro{SIGIO} in \secref{sec:file_asyncronous_io}, +per i dettagli degli altri segnali si consulti la man page di +\func{sigaction}). Il campo \var{sa\_mask} serve ad indicare l'insieme dei segnali che devono essere bloccati durante l'esecuzione del manipolatore, ad essi viene comunque @@ -2279,26 +2315,6 @@ ripristinata in un successivo \func{siglongjmp}; quest'ultima funzione, a parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a \func{longjmp}. -\begin{prototype}{signal.h} -{int sigaltstack(const stack\_t *ss, stack\_t *oss)} - -Installa un nuovo stack per i segnali. - - \bodydesc{La funzione restituisce zero in caso di successo e -1 per un - errore, nel qual caso \var{errno} assumerà i valori: - - \begin{errlist} - \item[\macro{ENOMEM}] La dimensione specificata per il nuovo stack è minore - di \macro{MINSIGSTKSZ}. - \item[\macro{EPERM}] Uno degli indirizzi non è valido. - \item[\macro{EFAULT}] Si è cercato di cambiare lo stack alternativo mentre - questo è attivo (cioè il processo è in esecuzione su di esso). - \item[\macro{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un - valore diverso da zero che non è \macro{SS\_DISABLE}. - \end{errlist}} -\end{prototype} - - %%% Local Variables: %%% mode: latex