Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra
\textit{fast} e \textit{slow} system call,\index{system~call~lente} 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\index{socket} ed alcuni file di
- dispositivo\index{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.
+ ricordi però che questo può accadere solo per le pipe, i socket ed alcuni
+ file di dispositivo\index{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.
Questo comportamento causa uno dei problemi più comuni che ci si trova ad
affrontare nelle operazioni di I/O, che si verifica quando si deve operare con
Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
multiplexing} è stato BSD,\footnote{la funzione \func{select} è apparsa in
BSD4.2 e standardizzata in BSD4.4, ma è stata portata su tutti i sistemi che
- supportano i \textit{socket}\index{socket}, compreso le varianti di System
- V.} con la funzione \funcd{select}, il cui prototipo è:
+ supportano i socket, compreso le varianti di System V.} con la funzione
+\funcd{select}, il cui prototipo è:
\begin{functions}
\headdecl{sys/time.h}
\headdecl{sys/types.h}
tutti i casi in cui la successiva esecuzione di \func{read} risulti non
bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
\param{writefds}, per verificare la possibilità effettuare una scrittura ed il
-terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i
-messaggi urgenti su un \textit{socket}\index{socket}, vedi
+terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
+urgenti \itindex{out-of-band} su un socket, vedi
sez.~\ref{sec:TCP_urgent_data}).
Dato che in genere non si tengono mai sotto controllo fino a
\const{POLLIN} & È possibile la lettura.\\
\const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\
\const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\
- \const{POLLPRI} & È possibile la lettura di dati urgenti.\\
+ \const{POLLPRI} & È possibile la lettura di \itindex{out-of-band} dati
+ urgenti.\\
\hline
\const{POLLOUT} & È possibile la scrittura immediata.\\
\const{POLLWRNORM}& È possibile la scrittura di dati normali. \\
delle librerie standard del C.} è da questi che derivano i nomi di alcune
costanti, in quanto per essi sono definite tre classi di dati:
\textsl{normali}, \textit{prioritari} ed \textit{urgenti}. In Linux la
-distinzione ha senso solo per i dati \textit{out-of-band} dei socket (vedi
-sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce
-alle varie condizioni dei socket torneremo in sez.~\ref{sec:TCP_serv_poll},
-dove vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le
-costanti relative ai diversi tipi di dati (come \const{POLLRDNORM} e
-\const{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la
-macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in
- testa al file, definirla soltanto prima di includere \file{sys/poll.h} non è
- sufficiente.}
+distinzione ha senso solo per i dati urgenti \itindex{out-of-band} dei socket
+(vedi sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll}
+reagisce alle varie condizioni dei socket torneremo in
+sez.~\ref{sec:TCP_serv_poll}, dove vedremo anche un esempio del suo utilizzo.
+Si tenga conto comunque che le costanti relative ai diversi tipi di dati (come
+\const{POLLRDNORM} e \const{POLLRDBAND}) sono utilizzabili soltanto qualora si
+sia definita la macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di
+ farlo sempre in testa al file, definirla soltanto prima di includere
+ \file{sys/poll.h} non è sufficiente.}
In caso di successo funzione ritorna restituendo il numero di file (un valore
positivo) per i quali si è verificata una delle condizioni di attesa richieste
effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
Benché la modalità di apertura asincrona di un file possa risultare utile in
-varie occasioni (in particolar modo con i socket\index{socket} e gli altri
-file per i quali le funzioni di I/O sono \index{system~call~lente}system call
-lente), essa è comunque limitata alla notifica della disponibilità del file
-descriptor per le operazioni di I/O, e non ad uno svolgimento asincrono delle
-medesime. Lo standard POSIX.1b definisce una interfaccia apposita per l'I/O
-asincrono vero e proprio, che prevede un insieme di funzioni dedicate per la
-lettura e la scrittura dei file, completamente separate rispetto a quelle
-usate normalmente.
+varie occasioni (in particolar modo con i socket e gli altri file per i quali
+le funzioni di I/O sono \index{system~call~lente}system call lente), essa è
+comunque limitata alla notifica della disponibilità del file descriptor per le
+operazioni di I/O, e non ad uno svolgimento asincrono delle medesime. Lo
+standard POSIX.1b definisce una interfaccia apposita per l'I/O asincrono vero
+e proprio, che prevede un insieme di funzioni dedicate per la lettura e la
+scrittura dei file, completamente separate rispetto a quelle usate
+normalmente.
In generale questa interfaccia è completamente astratta e può essere
implementata sia direttamente nel kernel, che in user space attraverso l'uso
La funzione cancella il nome specificato da \param{pathname} nella relativa
directory e decrementa il numero di riferimenti nel relativo
inode\index{inode}. Nel caso di link simbolico cancella il link simbolico; nel
-caso di socket\index{socket}, fifo o file di
-dispositivo\index{file!di~dispositivo} rimuove il nome, ma come per i file i
-processi che hanno aperto uno di questi oggetti possono continuare ad
-utilizzarlo.
+caso di socket, fifo o file di dispositivo\index{file!di~dispositivo} rimuove
+il nome, ma come per i file i processi che hanno aperto uno di questi oggetti
+possono continuare ad utilizzarlo.
Per cancellare una voce in una directory è necessario avere il permesso di
scrittura su di essa, dato che si va a rimuovere una voce dal suo contenuto, e
Finora abbiamo parlato esclusivamente di file, directory e link simbolici; in
sez.~\ref{sec:file_file_types} abbiamo visto però che il sistema prevede pure
degli altri tipi di file speciali, come i file di dispositivo
-\index{file!di~dispositivo} e le fifo (i socket\index{socket} sono un caso a
-parte, che vedremo in cap.~\ref{cha:socket_intro}).
+\index{file!di~dispositivo} e le fifo (i socket sono un caso a parte, che
+tratteremo in cap.~\ref{cha:socket_intro}).
La manipolazione delle caratteristiche di questi file e la loro cancellazione
può essere effettuata con le stesse funzioni che operano sui file regolari; ma
Dato che il valore numerico può variare a seconda delle implementazioni, lo
standard POSIX definisce un insieme di macro per verificare il tipo di file,
queste vengono usate anche da Linux che supporta pure le estensioni allo
-standard per i link simbolici e i socket\index{socket} definite da BSD;
-l'elenco completo delle macro con cui è possibile estrarre l'informazione da
-\var{st\_mode} è riportato in tab.~\ref{tab:file_type_macro}.
+standard per i link simbolici e i socket definite da BSD; l'elenco completo
+delle macro con cui è possibile estrarre l'informazione da \var{st\_mode} è
+riportato in tab.~\ref{tab:file_type_macro}.
\begin{table}[htb]
\centering
\footnotesize
\macro{S\_ISBLK(m)} & dispositivo a blocchi\\
\macro{S\_ISFIFO(m)} & fifo \\
\macro{S\_ISLNK(m)} & link simbolico \\
- \macro{S\_ISSOCK(m)} & socket\index{socket} \\
+ \macro{S\_ISSOCK(m)} & socket \\
\hline
\end{tabular}
\caption{Macro per i tipi di file (definite in \texttt{sys/stat.h}).}
\hline
\hline
\const{S\_IFMT} & 0170000 & maschera per i bit del tipo di file \\
- \const{S\_IFSOCK} & 0140000 & socket\index{socket} \\
+ \const{S\_IFSOCK} & 0140000 & socket \\
\const{S\_IFLNK} & 0120000 & link simbolico \\
\const{S\_IFREG} & 0100000 & file regolare \\
\const{S\_IFBLK} & 0060000 & dispositivo a blocchi \\
\func{ftruncate} si hanno i valori:
\begin{errlist}
\item[\errcode{EBADF}] \param{fd} non è un file descriptor.
- \item[\errcode{EINVAL}] \param{fd} è un riferimento ad un
- socket\index{socket}, non a un file o non è aperto in scrittura.
+ \item[\errcode{EINVAL}] \param{fd} è un riferimento ad un socket, non a un
+ file o non è aperto in scrittura.
\end{errlist}
per \func{truncate} si hanno:
\begin{errlist}
Un file può essere indicato rispetto alla directory corrente semplicemente
specificandone il nome\footnote{Il manuale delle \acr{glibc} chiama i nomi
-contenuti nelle directory \textsl{componenti} (in inglese \textit{file name
-components}), noi li chiameremo più semplicemente \textsl{nomi} o
-\textsl{voci}.} da essa contenuto. All'interno dello stesso albero si
+ contenuti nelle directory \textsl{componenti} (in inglese \textit{file name
+ components}), noi li chiameremo più semplicemente \textsl{nomi} o
+ \textsl{voci}.} da essa contenuto. All'interno dello stesso albero si
potranno poi inserire anche tutti gli altri oggetti visti attraverso
-l'interfaccia che manipola i file come le fifo, i link, i socket\index{socket}
-e gli stessi file di dispositivo \index{file!di~dispositivo} (questi ultimi,
-per convenzione, sono inseriti nella directory \file{/dev}).
+l'interfaccia che manipola i file come le fifo, i link, i socket e gli stessi
+file di dispositivo \index{file!di~dispositivo} (questi ultimi, per
+convenzione, sono inseriti nella directory \file{/dev}).
Il nome completo di un file viene chiamato \textit{pathname} ed il
procedimento con cui si individua il file a cui esso fa riferimento è chiamato
base al loro contenuto, o tipo di accesso. Essa riguarda invece il tipo di
oggetti; in particolare è da notare la presenza dei cosiddetti file speciali.
Alcuni di essi, come le \textit{fifo} (che tratteremo in
-sez.~\ref{sec:ipc_named_pipe}) ed i \textit{socket}\index{socket} (che
-tratteremo in cap.~\ref{cha:socket_intro}) non sono altro che dei riferimenti
-per utilizzare delle funzionalità di comunicazione fornite dal kernel. Gli
-altri sono i \textsl{file di dispositivo}\index{file!di~dispositivo} (o
-\textit{device file}) che costituiscono una interfaccia diretta per leggere e
-scrivere sui dispositivi fisici; essi vengono suddivisi in due grandi
-categorie, \textsl{a blocchi} e \textsl{a caratteri} a seconda delle modalità
-in cui il dispositivo sottostante effettua le operazioni di I/O.\footnote{in
- sostanza i dispositivi a blocchi (ad esempio i dischi) corrispondono a
- periferiche per le quali è richiesto che l'I/O venga effettuato per blocchi
- di dati di dimensioni fissate (ad esempio le dimensioni di un settore),
- mentre nei dispositivi a caratteri l'I/O viene effettuato senza nessuna
- particolare struttura.}
+sez.~\ref{sec:ipc_named_pipe}) ed i \textit{socket} (che tratteremo in
+cap.~\ref{cha:socket_intro}) non sono altro che dei riferimenti per utilizzare
+delle funzionalità di comunicazione fornite dal kernel. Gli altri sono i
+\textsl{file di dispositivo} \index{file!di~dispositivo} (o \textit{device
+ file}) che costituiscono una interfaccia diretta per leggere e scrivere sui
+dispositivi fisici; essi vengono suddivisi in due grandi categorie, \textsl{a
+ blocchi} e \textsl{a caratteri} a seconda delle modalità in cui il
+dispositivo sottostante effettua le operazioni di I/O.\footnote{in sostanza i
+ dispositivi a blocchi (ad esempio i dischi) corrispondono a periferiche per
+ le quali è richiesto che l'I/O venga effettuato per blocchi di dati di
+ dimensioni fissate (ad esempio le dimensioni di un settore), mentre nei
+ dispositivi a caratteri l'I/O viene effettuato senza nessuna particolare
+ struttura.}
\begin{table}[htb]
\footnotesize
\textit{fifo} & ``\textsl{coda}'' &
un file speciale che identifica una linea di comunicazione software
unidirezionale (vedi sez.~\ref{sec:ipc_named_pipe}).\\
- \textit{socket}\index{socket} & ``\textsl{presa}''&
+ \textit{socket} & ``\textsl{presa}''&
un file speciale che identifica una linea di comunicazione software
bidirezionale (vedi cap.~\ref{cha:socket_intro}) \\
\hline
\file{stdio.h}.
Entrambe le interfacce possono essere usate per l'accesso ai file come agli
-altri oggetti del VFS (fifo, socket\index{socket}, dispositivi, sui quali
-torneremo in dettaglio a tempo opportuno), ma per poter accedere alle
-operazioni di controllo (descritte in sez.~\ref{sec:file_fcntl} e
-sez.~\ref{sec:file_ioctl}) su un qualunque tipo di oggetto del VFS occorre
-usare l'interfaccia standard di Unix con i \textit{file descriptor}. Allo
-stesso modo devono essere usati i \textit{file descriptor}
-\index{file!descriptor} se si vuole ricorrere a modalità speciali di I/O come
-il \textit{file locking}\index{file!locking} o l'I/O non-bloccante (vedi
-cap.~\ref{cha:file_advanced}).
+altri oggetti del VFS (fifo, socket, dispositivi, sui quali torneremo in
+dettaglio a tempo opportuno), ma per poter accedere alle operazioni di
+controllo (descritte in sez.~\ref{sec:file_fcntl} e sez.~\ref{sec:file_ioctl})
+su un qualunque tipo di oggetto del VFS occorre usare l'interfaccia standard
+di Unix con i \textit{file descriptor}. Allo stesso modo devono essere usati i
+\textit{file descriptor} \index{file!descriptor} se si vuole ricorrere a
+modalità speciali di I/O come il \textit{file locking}\index{file!locking} o
+l'I/O non-bloccante (vedi cap.~\ref{cha:file_advanced}).
Gli \textit{stream} forniscono un'interfaccia di alto livello costruita sopra
quella dei \textit{file descriptor}, che permette di poter scegliere tra
caratteri) senza sprecare spazio disco.
-
-
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "gapil"
Infine \func{fdopen} viene usata per associare uno stream ad un file
descriptor esistente ottenuto tramite una altra funzione (ad esempio con una
\func{open}, una \func{dup}, o una \func{pipe}) e serve quando si vogliono
-usare gli stream con file come le fifo o i socket\index{socket}, che non
-possono essere aperti con le funzioni delle librerie standard del C.
+usare gli stream con file come le fifo o i socket, che non possono essere
+aperti con le funzioni delle librerie standard del C.
\begin{table}[htb]
\centering
successo e $-1$ in caso di errore nel qual caso \var{errno} assumerà uno
dei valori:
\begin{errlist}
- \item[\errcode{ESPIPE}] \param{fd} è una pipe, un socket\index{socket} o una
- fifo.
+ \item[\errcode{ESPIPE}] \param{fd} è una pipe, un socket o una fifo.
\item[\errcode{EINVAL}] \param{whence} non è un valore valido.
\end{errlist}
ed inoltre \errval{EBADF}.}
di byte richiesti eccede quelli disponibili la funzione ritorna comunque, ma
con un numero di byte inferiore a quelli richiesti.
-Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un
-socket\index{socket}, come vedremo in sez.~\ref{sec:sock_io_behav}), o per la
-lettura da certi file di dispositivo, come le unità a nastro, che
-restituiscono sempre i dati ad un singolo blocco alla volta, o come le linee
-seriali, che restituiscono solo i dati ricevuti fino al momento della lettura.
+Lo stesso comportamento avviene caso di lettura dalla rete (cioè su un socket,
+come vedremo in sez.~\ref{sec:sock_io_behav}), o per la lettura da certi file
+di dispositivo, come le unità a nastro, che restituiscono sempre i dati ad un
+singolo blocco alla volta, o come le linee seriali, che restituiscono solo i
+dati ricevuti fino al momento della lettura.
Infine anche le due condizioni segnalate dagli errori \errcode{EINTR} ed
\errcode{EAGAIN} non sono propriamente degli errori. La prima si verifica
fatto una richiesta, ma prima che la risposta sia inviata (cosa che nel
nostro esempio non è stata fatta).}; 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
-cap.~\ref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione
-diversi, come quelli che esamineremo in seguito.
+affrontati in maniera più semplice ed efficace o usando i socket (che
+tratteremo in dettaglio a partire da cap.~\ref{cha:socket_intro}) o ricorrendo
+a meccanismi di comunicazione diversi, come quelli che esamineremo in seguito.
Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il
problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti
\textsl{socket locali} (o \textit{Unix domain socket}). Tratteremo l'argomento
-dei \textit{socket}\index{socket} in cap.~\ref{cha:socket_intro},\footnote{si
- tratta comunque di oggetti di comunicazione che, come le pipe, sono
- utilizzati attraverso dei file descriptor.} nell'ambito dell'interfaccia
-generale che essi forniscono per la programmazione di rete; e vedremo anche
+dei socket in cap.~\ref{cha:socket_intro},\footnote{si tratta comunque di
+ oggetti di comunicazione che, come le pipe, sono utilizzati attraverso dei
+ file descriptor.} nell'ambito dell'interfaccia generale che essi forniscono
+per la programmazione di rete; e vedremo anche
(in~sez.~\ref{sec:sock_sa_local}) come si possono definire dei file speciali
-(di tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede
-però attraverso quella medesima interfaccia; vale però la pena esaminare qui
-una modalità di uso dei socket locali\footnote{la funzione \func{socketpair} è
+(di tipo socket, analoghi a quello associati alle fifo) cui si accede però
+attraverso quella medesima interfaccia; vale però la pena esaminare qui una
+modalità di uso dei socket locali\footnote{la funzione \func{socketpair} è
stata introdotta in BSD4.4, ma è supportata in genere da qualunque sistema
che fornisca l'interfaccia dei socket.} che li rende sostanzialmente
identici ad una pipe bidirezionale.
La funzione \funcd{socketpair} infatti consente di creare una coppia di file
-descriptor connessi fra di loro (tramite un socket\index{socket}, appunto),
-senza dover ricorrere ad un file speciale sul filesystem, i descrittori sono
-del tutto analoghi a quelli che si avrebbero con una chiamata a \func{pipe},
-con la sola differenza è che in questo caso il flusso dei dati può essere
-effettuato in entrambe le direzioni. Il prototipo della funzione è:
+descriptor connessi fra di loro (tramite un socket, appunto), senza dover
+ricorrere ad un file speciale sul filesystem, i descrittori sono del tutto
+analoghi a quelli che si avrebbero con una chiamata a \func{pipe}, con la sola
+differenza è che in questo caso il flusso dei dati può essere effettuato in
+entrambe le direzioni. Il prototipo della funzione è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/socket.h}
\funcdecl{int socketpair(int domain, int type, int protocol, int sv[2])}
- Crea una coppia di socket\index{socket} connessi fra loro.
+ Crea una coppia di socket connessi fra loro.
\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EAFNOSUPPORT}] I socket\index{socket} locali non sono
- supportati.
+ \item[\errcode{EAFNOSUPPORT}] I socket locali non sono supportati.
\item[\errcode{EPROTONOSUPPORT}] Il protocollo specificato non è supportato.
\item[\errcode{EOPNOTSUPP}] Il protocollo specificato non supporta la
- creazione di coppie di socket\index{socket}.
+ creazione di coppie di socket.
\end{errlist}
ed inoltre \errval{EMFILE}, \errval{EFAULT}.
}
La funzione restituisce in \param{sv} la coppia di descrittori connessi fra di
loro: quello che si scrive su uno di essi sarà ripresentato in input
sull'altro e viceversa. Gli argomenti \param{domain}, \param{type} e
-\param{protocol} derivano dall'interfaccia dei socket\index{socket} (vedi
+\param{protocol} derivano dall'interfaccia dei socket (vedi
sez.~\ref{sec:sock_creation}) che è quella che fornisce il substrato per
connettere i due descrittori, ma in questo caso i soli valori validi che
possono essere specificati sono rispettivamente \const{AF\_UNIX},
\const{SOCK\_STREAM} e \val{0}.
L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe}
-può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei
-socket\index{socket} locali in generale) permette di trasmettere attraverso le
-linea non solo dei dati, ma anche dei file descriptor: si può cioè passare da
-un processo ad un altro un file descriptor, con una sorta di duplicazione
-dello stesso non all'interno di uno stesso processo, ma fra processi distinti
-(torneremo su questa funzionalità in sez.~\ref{sec:sock_fd_passing}).
+può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei socket
+locali in generale) permette di trasmettere attraverso le linea non solo dei
+dati, ma anche dei file descriptor: si può cioè passare da un processo ad un
+altro un file descriptor, con una sorta di duplicazione dello stesso non
+all'interno di uno stesso processo, ma fra processi distinti (torneremo su
+questa funzionalità in sez.~\ref{sec:sock_fd_passing}).
\section{Il sistema di comunicazione fra processi di System V}
In realtà, grazie alla presenza del campo \var{mtype}, le code di messaggi
hanno delle caratteristiche ulteriori, consentendo una classificazione dei
messaggi ed un accesso non rigidamente sequenziale; due caratteristiche che
-sono impossibili da ottenere con le pipe e i socket\index{socket} di
-\func{socketpair}. A queste esigenze però si può comunque ovviare in maniera
-diversa con un uso combinato della memoria condivisa e dei meccanismi di
-sincronizzazione, per cui alla fine l'uso delle code di messaggi classiche è
-relativamente poco diffuso.
+sono impossibili da ottenere con le pipe e i socket di \func{socketpair}. A
+queste esigenze però si può comunque ovviare in maniera diversa con un uso
+combinato della memoria condivisa e dei meccanismi di sincronizzazione, per
+cui alla fine l'uso delle code di messaggi classiche è relativamente poco
+diffuso.
\subsection{I \textsl{file di lock}}
\label{sec:ipc_file_lock}
{\textsf{http://www.mat.uni.torun.pl/\tild{}wrona/posix\_ipc}}, questi sono
stati inseriti nel kernel ufficiale a partire dalla versione 2.6.6-rc1.}. In
generale, come le corrispettive del SysV IPC, le code di messaggi sono poco
-usate, dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono
+usate, dato che i socket, nei casi in cui sono sufficienti, sono
più comodi, e che in casi più complessi la comunicazione può essere gestita
direttamente con mutex e memoria condivisa con tutta la flessibilità che
occorre.
Comment} ed è la procedura attraverso la quale vengono proposti gli
standard per Internet.}).
\item I dati delle applicazioni vengono inviati al livello di trasporto usando
- un'interfaccia opportuna (i \textit{socket}\index{socket}, che esamineremo
- in dettaglio in cap.~\ref{cha:socket_intro}). Qui verranno spezzati in
- pacchetti di dimensione opportuna e inseriti nel protocollo di trasporto,
- aggiungendo ad ogni pacchetto le informazioni necessarie per la sua
- gestione. Questo processo viene svolto direttamente nel kernel, ad esempio
- dallo stack TCP, nel caso il protocollo di trasporto usato sia questo.
+ un'interfaccia opportuna (i \textit{socket}, che esamineremo in dettaglio in
+ cap.~\ref{cha:socket_intro}). Qui verranno spezzati in pacchetti di
+ dimensione opportuna e inseriti nel protocollo di trasporto, aggiungendo ad
+ ogni pacchetto le informazioni necessarie per la sua gestione. Questo
+ processo viene svolto direttamente nel kernel, ad esempio dallo stack TCP,
+ nel caso il protocollo di trasporto usato sia questo.
\item Una volta composto il pacchetto nel formato adatto al protocollo di
trasporto usato questo sarà passato al successivo livello, quello di rete,
che si occupa di inserire le opportune informazioni per poter effettuare
due livelli centrali, e soprattutto quello di trasporto.
La principale interfaccia usata nella programmazione di rete, quella dei
-socket\index{socket}, è infatti un'interfaccia nei confronti di quest'ultimo.
-Questo avviene perché al di sopra del livello di trasporto i programmi hanno a
-che fare solo con dettagli specifici delle applicazioni, mentre al di sotto
-vengono curati tutti i dettagli relativi alla comunicazione. È pertanto
-naturale definire una interfaccia di programmazione su questo confine, tanto
-più che è proprio lì (come evidenziato in fig.~\ref{fig:net_osi_tcpip_comp})
-che nei sistemi Unix (e non solo) viene inserita la divisione fra kernel space
-e user space.
+socket (vedi sez.~\ref{cha:socket_intro}), è infatti un'interfaccia nei
+confronti di quest'ultimo. Questo avviene perché al di sopra del livello di
+trasporto i programmi hanno a che fare solo con dettagli specifici delle
+applicazioni, mentre al di sotto vengono curati tutti i dettagli relativi alla
+comunicazione. È pertanto naturale definire una interfaccia di programmazione
+su questo confine, tanto più che è proprio lì (come evidenziato in
+fig.~\ref{fig:net_osi_tcpip_comp}) che nei sistemi Unix (e non solo) viene
+inserita la divisione fra kernel space e user space.
In realtà in un sistema Unix è possibile accedere anche agli altri livelli
inferiori (e non solo a quello di trasporto) con opportune interfacce di
IGMP); benché sia TCP che UDP siano basati su IP e sia possibile intervenire a
questo livello con i \textit{raw socket} questa tecnica è molto meno diffusa e
a parte applicazioni particolari si preferisce sempre usare i servizi messi a
-disposizione dai due protocolli precedenti. Per questo motivo a parte alcuni
-brevi accenni su IP in questa sezione ci concentreremo sul livello di
+disposizione dai due protocolli precedenti. Per questo, motivo a parte alcuni
+brevi accenni su IP in questa sezione, ci concentreremo sul livello di
trasporto.
\subsection{Internet Protocol (IP)}
contenuta dell'\href{http://www.ietf.org/rfc/rfc0768.txt}{RFC~768}, ma in
sostanza esso è una semplice interfaccia a IP dal livello di trasporto. Quando
un'applicazione usa UDP essa scrive un pacchetto di dati (il cosiddetto
-\textit{datagram} che da il nome al protocollo) su un socket\index{socket}, al
-pacchetto viene aggiunto un header molto semplice (per una descrizione più
-accurata vedi sez.~\ref{sec:udp_protocol}), e poi viene passato al livello
-superiore (IPv4 o IPv6 che sia) che lo spedisce verso la destinazione. Dato
-che né IPv4 né IPv6 garantiscono l'affidabilità niente assicura che il
-pacchetto arrivi a destinazione, né che più pacchetti arrivino nello stesso
-ordine in cui sono stati spediti.
+\textit{datagram} che da il nome al protocollo) su un socket, al pacchetto
+viene aggiunto un header molto semplice (per una descrizione più accurata vedi
+sez.~\ref{sec:udp_protocol}), e poi viene passato al livello superiore (IPv4 o
+IPv6 che sia) che lo spedisce verso la destinazione. Dato che né IPv4 né IPv6
+garantiscono l'affidabilità niente assicura che il pacchetto arrivi a
+destinazione, né che più pacchetti arrivino nello stesso ordine in cui sono
+stati spediti.
Pertanto il problema principale che si affronta quando si usa UDP è la
mancanza di affidabilità, se si vuole essere sicuri che i pacchetti arrivino a
Infine UDP è un protocollo che opera senza connessione
(\textit{connectionless}) in quanto non è necessario stabilire nessun tipo di
relazione tra origine e destinazione dei pacchetti. Si hanno così situazioni
-in cui un client può scrivere su uno stesso socket\index{socket} pacchetti
-destinati a server diversi, o un server ricevere su un socket\index{socket}
-pacchetti provenienti da client diversi. Il modo più semplice di immaginarsi
-il funzionamento di UDP è quello della radio, in cui si può
-\textsl{trasmettere} e \textsl{ricevere} da più stazioni usando la stessa
-frequenza.
+in cui un client può scrivere su uno stesso socket pacchetti destinati a
+server diversi, o un server ricevere su un socket pacchetti provenienti da
+client diversi. Il modo più semplice di immaginarsi il funzionamento di UDP è
+quello della radio, in cui si può \textsl{trasmettere} e \textsl{ricevere} da
+più stazioni usando la stessa frequenza.
Nonostante gli evidenti svantaggi comportati dall'inaffidabilità UDP ha il
grande pregio della velocità, che in certi casi è essenziale; inoltre si
presta bene per le applicazioni in cui la connessione non è necessaria, e
costituirebbe solo un peso in termini di prestazioni, mentre una perdita di
-pacchetti può essere tollerata, ad esempio le applicazioni di streaming e
+pacchetti può essere tollerata: ad esempio le applicazioni di streaming e
quelle che usano il \textit{multicast}. \itindex{multicast}
\subsection{Transport Control Protocol (TCP)}
Inoltre TCP è in grado di preservare l'ordine dei dati assegnando un numero di
sequenza ad ogni byte che trasmette. Ad esempio se un'applicazione scrive 3000
-byte su un socket\index{socket} TCP, questi potranno essere spezzati dal
-protocollo in due segmenti (le unità di dati passate da TCP a IP vengono
-chiamate \textit{segment}) di 1500 byte, di cui il primo conterrà il numero di
-sequenza $1-1500$ e il secondo il numero $1501-3000$. In questo modo anche se
-i segmenti arrivano a destinazione in un ordine diverso, o se alcuni arrivano
+byte su un socket TCP, questi potranno essere spezzati dal protocollo in due
+segmenti (le unità di dati passate da TCP a IP vengono chiamate
+\textit{segment}) di 1500 byte, di cui il primo conterrà il numero di sequenza
+$1-1500$ e il secondo il numero $1501-3000$. In questo modo anche se i
+segmenti arrivano a destinazione in un ordine diverso, o se alcuni arrivano
più volte a causa di ritrasmissioni dovute alla perdita degli
\textit{acknowlegment}, all'arrivo sarà comunque possibile riordinare i dati e
scartare i duplicati.
che possono essere ricevuti.
Questa finestra cambia dinamicamente diminuendo con la ricezione dei dati dal
-socket\index{socket} ed aumentando con la lettura di quest'ultimo da parte
+socket ed aumentando con la lettura di quest'ultimo da parte
dell'applicazione, se diventa nulla il buffer di ricezione è pieno e non
verranno accettati altri dati. Si noti che UDP non provvede niente di tutto
ciò per cui nulla impedisce che vengano trasmessi pacchetti ad un ritmo che il
+\index{socket!locali|(}
+
+
\section{I socket \textit{Unix domain}}
\label{sec:unix_socket}
+\index{socket!locali|)}
\section{I socket \textit{raw}}
\label{sec:socket_raw}
\const{CAP\_SETGID} & la capacità di manipolare i group ID dei
processi, sia il principale che i supplementari,
(vedi sez.~\ref{sec:proc_setgroups} che quelli
- trasmessi tramite i \index{socket} socket
- \textit{unix domain} (vedi
- sez.~\ref{sec:unix_socket}).\\
+ trasmessi tramite i socket \textit{unix domain}
+ (vedi sez.~\ref{sec:unix_socket}).\\
\const{CAP\_SETUID} & la capacità di manipolare gli user ID del
processo (con \func{setuid}, \func{setreuid},
\func{setresuid}, \func{setfsuid}) e di
trasmettere un valore arbitrario
dell'\textsl{uid} nel passaggio delle
- credenziali coi socket unix domain (vedi
+ credenziali coi socket \textit{unix domain} (vedi
sez.~\ref{sec:unix_socket}).\\
%
% Linux specific capabilities
Il servizio prevede vari meccanismi di notifica, e, come ogni altro servizio
in un sistema unix-like, viene gestito attraverso un apposito programma,
\cmd{syslogd}, che è anch'esso un \textsl{demone}. In generale i messaggi di
-errore vengono raccolti dal file speciale \file{/dev/log}, un
-\textit{socket}\index{socket} locale (vedi sez.~\ref{sec:sock_sa_local})
-dedicato a questo scopo, o via rete, con un \textit{socket} UDP, o da un
-apposito demone, \cmd{klogd}, che estrae i messaggi del kernel.\footnote{i
- messaggi del kernel sono tenuti in un buffer circolare e scritti tramite la
- funzione \func{printk}, analoga alla \func{printf} usata in user space; una
- trattazione eccellente dell'argomento si trova in \cite{LinDevDri}, nel
- quarto capitolo.}
+errore vengono raccolti dal file speciale \file{/dev/log}, un \textit{socket}
+locale (vedi sez.~\ref{sec:sock_sa_local}) dedicato a questo scopo, o via
+rete, con un \textit{socket} UDP, o da un apposito demone, \cmd{klogd}, che
+estrae i messaggi del kernel.\footnote{i messaggi del kernel sono tenuti in un
+ buffer circolare e scritti tramite la funzione \func{printk}, analoga alla
+ \func{printf} usata in user space; una trattazione eccellente dell'argomento
+ si trova in \cite{LinDevDri}, nel quarto capitolo.}
Il servizio permette poi di trattare i vari messaggi classificandoli
attraverso due indici; il primo, chiamato \textit{facility}, suddivide in
Le \acr{glibc} definiscono una serie di funzioni standard con cui un processo
può accedere in maniera generica al servizio di \textit{syslog}, che però
funzionano solo localmente; se si vogliono inviare i messaggi ad un altro
-sistema occorre farlo esplicitamente con un socket\index{socket} UDP, o
-utilizzare le capacità di reinvio del servizio.
+sistema occorre farlo esplicitamente con un socket UDP, o utilizzare le
+capacità di reinvio del servizio.
La prima funzione definita dall'interfaccia è \funcd{openlog}, che apre una
connessione al servizio di \textit{syslog}; essa in generale non è necessaria
\const{SIGSYS} &SL & C & Argomento sbagliato per una subroutine (SVID).\\
\const{SIGTRAP} &SL & C & Trappole per un Trace/breakpoint. \\
\const{SIGURG} &SLB& B & Ricezione di una \textit{urgent condition} su
- un socket\index{socket}. \\
+ un socket. \\
\const{SIGVTALRM}&SLB& A & Virtual alarm clock. \\
\const{SIGXCPU} &SLB& C & Ecceduto il limite sul tempo di CPU. \\
\const{SIGXFSZ} &SLB& C & Ecceduto il limite sulla dimensione dei file. \\
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{SIGIO}] Questo segnale viene inviato quando un file descriptor è
pronto per eseguire dell'input/output. In molti sistemi solo i
- socket\index{socket} e i terminali possono generare questo segnale, in Linux
+ socket e i terminali possono generare questo segnale, in Linux
questo può essere usato anche per i file, posto che la \func{fcntl} abbia
avuto successo.
\item[\const{SIGURG}] Questo segnale è inviato quando arrivano dei dati
- urgenti o \textit{out-of-band} su di un socket\index{socket}; per maggiori
- dettagli al proposito si veda sez.~\ref{sec:TCP_urgent_data}.
+ urgenti o \itindex{out-of-band} \textit{out-of-band} su di un
+ socket; per maggiori dettagli al proposito si veda
+ sez.~\ref{sec:TCP_urgent_data}.
\item[\const{SIGPOLL}] Questo segnale è equivalente a \const{SIGIO}, è
definito solo per compatibilità con i sistemi System V.
\begin{itemize*}
\item la lettura da file che possono bloccarsi in attesa di dati non ancora
presenti (come per certi file di dispositivo\index{file!di~dispositivo}, i
- socket\index{socket} o le pipe);
+ socket o le pipe);
\item la scrittura sugli stessi file, nel caso in cui dati non possano essere
accettati immediatamente (di nuovo comune per i socket);
\item l'apertura di un file di dispositivo che richiede operazioni non
\const{SIGSEGV} e \const{SIGBUS} avvalorano \var{si\_addr} con l'indirizzo in
cui è avvenuto l'errore, \const{SIGIO} (vedi
sez.~\ref{sec:file_asyncronous_io}) avvalora \var{si\_fd} con il numero del
-file descriptor e \var{si\_band} per i dati urgenti su un
-socket\index{socket}.
+file descriptor e \var{si\_band} per i \itindex{out-of-band} dati urgenti (vedi
+sez.~\ref{sec:TCP_urgent_data}) su un socket.
Benché sia possibile usare nello stesso programma sia \func{sigaction} che
\func{signal} occorre molta attenzione, in quanto le due funzioni possono
\const{SO\_KEEPALIVE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
controlla l'attività della connessione.\\
\const{SO\_OOBINLINE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
- lascia in linea i dati \textit{out-of-band}.\\
+ lascia in linea i dati \itindex{out-of-band}
+ \textit{out-of-band}.\\
\const{SO\_RCVLOWAT} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
basso livello sul buffer di ricezione.\\
\const{SO\_SNDLOWAT} &$\bullet$&$\bullet$& &\texttt{int}&
forniti in sez.~\ref{sec:sock_options_main}.
\item[\const{SO\_OOBINLINE}] se questa opzione viene abilitata i dati
- \textit{out-of-band} vengono inviati direttamente nel flusso di dati del
- socket (e sono quindi letti con una normale \func{read}) invece che restare
- disponibili solo per l'accesso con l'uso del flag \const{MSG\_OOB} di
- \func{recvmsg}. L'argomento è trattato in dettaglio in
+ \itindex{out-of-band} \textit{out-of-band} vengono inviati direttamente nel
+ flusso di dati del socket (e sono quindi letti con una normale \func{read})
+ invece che restare disponibili solo per l'accesso con l'uso del flag
+ \const{MSG\_OOB} di \func{recvmsg}. L'argomento è trattato in dettaglio in
sez.~\ref{sec:TCP_urgent_data}. L'opzione funziona soltanto con socket che
- supportino i dati \textit{out-of-band} (non ha senso per socket UDP ad
- esempio), ed utilizza per \param{optval} un intero usato come valore logico.
+ supportino i dati \itindex{out-of-band} \textit{out-of-band} (non ha senso
+ per socket UDP ad esempio), ed utilizza per \param{optval} un intero usato
+ come valore logico.
\item[\const{SO\_RCVLOWAT}] questa opzione imposta il valore che indica il
numero minimo di byte che devono essere presenti nel buffer di ricezione
\item[\const{SIOCSPGRP}] imposta il processo o il \itindex{process~group}
\textit{process group} a cui inviare i segnali \const{SIGIO} e
\const{SIGURG} quando viene completata una operazione di I/O asincrono o
- arrivano dei dati urgenti. Il terzo argomento deve essere un puntatore ad una
- variabile di tipo \type{pid\_t}; un valore positivo indica direttamente il
- \acr{pid} del processo, mentre un valore negativo indica (col valore
- assoluto) il \textit{process group}. Senza privilegi di amministratore o la
- capability \const{CAP\_KILL} si può impostare solo se stessi o il proprio
+ arrivano dei dati urgenti \itindex{out-of-band} (\texttt{out-of-band}). Il
+ terzo argomento deve essere un puntatore ad una variabile di tipo
+ \type{pid\_t}; un valore positivo indica direttamente il \acr{pid} del
+ processo, mentre un valore negativo indica (col valore assoluto) il
+ \textit{process group}. Senza privilegi di amministratore o la capability
+ \const{CAP\_KILL} si può impostare solo se stessi o il proprio
\textit{process group}.
\item[\const{SIOCGPGRP}] legge le impostazioni presenti sul socket
\texttt{LISTEN}, altrimenti si avrà un errore di \errval{EINVAL}.
\item[\const{SIOCATMARK}] ritorna un intero non nullo, da intendere come
valore logico, se il flusso di dati è arrivato sulla posizione in cui sono
- stati ricevuti dati urgenti.
+ stati ricevuti \itindex{out-of-band} dati urgenti. Come vedremo in maggior
+ dettaglio in sez.~\ref{sec:TCP_urgent_data} una delle caratteristiche di TCP
+ è quella relativa alla capacità di trasmettere i cosiddetti dati urgenti o
+ \itindex{out-of-band} \textit{out-of-band}. Come già accennato in
+ sez.~\ref{sec:sock_setsockopt} l'opzione \const{SO\_OOBINLINE}
\item[\const{SIOCOUTQ}]
\end{basedescript}
Iniziamo con una descrizione essenziale di cosa sono i \textit{socket} e di
quali sono i concetti fondamentali da tenere presente quando si ha a che fare
con essi.
-\index{socket|(}
+\index{socket!definizione|(}
\subsection{I \textit{socket}}
\label{sec:sock_socket_def}
dovranno essere opportunamente trattati, ecc.
-\section{La creazione di un \textit{socket}}
+\section{La creazione di un socket}
\label{sec:sock_creation}
Come accennato l'interfaccia dei socket è estremamente flessibile e permette
chiamano \textsl{domini}. La scelta di un dominio equivale in sostanza alla
scelta di una famiglia di protocolli, e viene effettuata attraverso
l'argomento \param{domain} della funzione \func{socket}. Ciascun dominio ha un
-suo nome simbolico che convenzionalmente inizia con una costante che inizia
-per \texttt{PF\_}, iniziali di \textit{protocol family}, un altro nome con cui
-si indicano i domini.
+suo nome simbolico che convenzionalmente è indicato da una costante che inizia
+per \texttt{PF\_}, sigla che sta per \textit{protocol family}, altro nome con
+cui si indicano i domini.
A ciascun tipo di dominio corrisponde un analogo nome simbolico, anch'esso
associato ad una costante, che inizia invece per \texttt{AF\_} (da
\const{PF\_BLUETOOTH}&31& Bluetooth socket & \\
\hline
\end{tabular}
- \caption{Famiglie di protocolli definiti in Linux.}
+ \caption{Famiglie di protocolli definiti in Linux.}
\label{tab:net_pf_names}
\end{table}
altro socket. I dati vengono ricevuti e trasmessi come un flusso continuo di
byte (da cui il nome \textit{stream}) e possono essere letti in blocchi di
dimensioni qualunque. Può supportare la trasmissione dei cosiddetti dati
- \itindex{out-of-band} \textit{out-of-band} (vedi
+ urgenti (o \itindex{out-of-band} \textit{out-of-band}, vedi
sez.~\ref{sec:TCP_urgent_data}).
\item[\const{SOCK\_DGRAM}] Viene usato per trasmettere pacchetti di dati
(\textit{datagram}) di lunghezza massima prefissata, indirizzati
\textit{dotted decimal} per IPv4 e quello descritto in
sez.~\ref{sec:IP_ipv6_notation} per IPv6.
-\index{socket|)}
+\index{socket!definizione|)}
Infine c'è una sola condizione che fa si che \func{select} ritorni segnalando
che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una
-condizione di eccezione pendente, e cioè la ricezione sul socket di dati
-\textsl{fuori banda} (o \itindex{out-of-band} \textit{out-of-band}), una
+condizione di eccezione pendente, e cioè la ricezione sul socket di
+\textsl{dati urgenti} (o \itindex{out-of-band} \textit{out-of-band}), una
caratteristica specifica dei socket TCP su cui torneremo in
sez.~\ref{sec:TCP_urgent_data}.
\item i dati inviati su un socket vengono considerati traffico normale,
pertanto vengono rilevati alla loro ricezione sull'altro capo da una
selezione effettuata con \const{POLLIN} o \const{POLLRDNORM};
-\item i dati \itindex{out-of-band} \textit{out-of-band} (vedi
+\item i dati urgenti \itindex{out-of-band} \textit{out-of-band} (vedi
sez.~\ref{sec:TCP_urgent_data}) su un socket TCP vengono considerati
traffico prioritario e vengono rilevati da una condizione \const{POLLIN},
\const{POLLPRI} o \const{POLLRDBAND}.