From 250b32a55733b307d2eae8afb50b64af1b7c0bc8 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Thu, 16 Aug 2007 23:33:20 +0000 Subject: [PATCH] Correzioni varie alle note (uniformate in stile) e trattazione di {{{splice}}}. --- fileadv.tex | 322 ++++++++++++++++++++++++++++++-------------------- filedir.tex | 36 +++--- fileintro.tex | 2 +- fileunix.tex | 2 +- intro.tex | 2 +- ipc.tex | 8 +- network.tex | 2 +- session.tex | 17 +-- signal.tex | 2 +- sockctrl.tex | 2 +- system.tex | 4 +- tcpsock.tex | 4 +- 12 files changed, 237 insertions(+), 166 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index a7851b6..14e10b8 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1363,7 +1363,7 @@ flag della prima parte. \footnotesize \begin{tabular}[c]{|l|c|p{10cm}|} \hline - \textbf{Flag} & & \textbf{Significato} \\ + \textbf{Valore} & & \textbf{Significato} \\ \hline \hline \const{IN\_ACCESS} &$\bullet$& C'è stato accesso al file in @@ -1403,7 +1403,7 @@ flag della prima parte. possibili.\\ \hline \end{tabular} - \caption{Le costanti che identificano i valori per la maschera binaria + \caption{Le costanti che identificano i bit della maschera binaria dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano il tipo di evento da tenere sotto osservazione.} \label{tab:inotify_event_watch} @@ -1424,7 +1424,7 @@ contrario dei precedenti non vengono mai impostati nei risultati in uscita. \footnotesize \begin{tabular}[c]{|l|p{10cm}|} \hline - \textbf{Flag} & \textbf{Significato} \\ + \textbf{Valore} & \textbf{Significato} \\ \hline \hline \const{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un @@ -1440,7 +1440,7 @@ contrario dei precedenti non vengono mai impostati nei risultati in uscita. quelli per i file che contiene.\\ \hline \end{tabular} - \caption{Le costanti che identificano i valori per la maschera binaria + \caption{Le costanti che identificano i bit della maschera binaria dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano le modalità di osservazione.} \label{tab:inotify_add_watch_flag} @@ -1554,7 +1554,7 @@ aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di \footnotesize \begin{tabular}[c]{|l|p{10cm}|} \hline - \textbf{Flag} & \textbf{Significato} \\ + \textbf{Valore} & \textbf{Significato} \\ \hline \hline \const{IN\_IGNORED} & L'osservatore è stato rimosso, sia in maniera @@ -1574,7 +1574,7 @@ aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di osservazione è stato smontato.\\ \hline \end{tabular} - \caption{Le costanti che identificano i flag aggiuntivi usati nella maschera + \caption{Le costanti che identificano i bit aggiuntivi usati nella maschera binaria del campo \var{mask} di \struct{inotify\_event}.} \label{tab:inotify_read_event_flag} \end{table} @@ -1859,11 +1859,11 @@ appena descritta; i rispettivi prototipi sono: \bodydesc{Le funzioni restituiscono 0 in caso di successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato. - \item[\errcode{ENOSYS}] La funzione non è implementata. - \item[\errcode{EINVAL}] Si è specificato un valore non valido per i campi + \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato. + \item[\errcode{ENOSYS}] la funzione non è implementata. + \item[\errcode{EINVAL}] si è specificato un valore non valido per i campi \var{aio\_offset} o \var{aio\_reqprio} di \param{aiocbp}. - \item[\errcode{EAGAIN}] La coda delle richieste è momentaneamente piena. + \item[\errcode{EAGAIN}] la coda delle richieste è momentaneamente piena. \end{errlist} } \end{functions} @@ -2030,10 +2030,10 @@ specifica operazione; il suo prototipo completate, e -1 in caso di errore nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EAGAIN}] Nessuna operazione è stata completata entro + \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro \param{timeout}. - \item[\errcode{ENOSYS}] La funzione non è implementata. - \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale. + \item[\errcode{ENOSYS}] la funzione non è implementata. + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. \end{errlist} } \end{prototype} @@ -2061,13 +2061,13 @@ lettura o scrittura; il suo prototipo \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{EAGAIN}] Nessuna operazione è stata completata entro + \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro \param{timeout}. - \item[\errcode{EINVAL}] Si è passato un valore di \param{mode} non valido + \item[\errcode{EINVAL}] si è passato un valore di \param{mode} non valido o un numero di operazioni \param{nent} maggiore di \const{AIO\_LISTIO\_MAX}. - \item[\errcode{ENOSYS}] La funzione non è implementata. - \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale. + \item[\errcode{ENOSYS}] la funzione non è implementata. + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. \end{errlist} } \end{prototype} @@ -2177,29 +2177,29 @@ eseguire la mappatura in memoria di un file, in caso di successo, e \const{MAP\_FAILED} (-1) in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EBADF}] Il file descriptor non è valido, e non si è usato + \item[\errcode{EBADF}] il file descriptor non è valido, e non si è usato \const{MAP\_ANONYMOUS}. \item[\errcode{EACCES}] o \param{fd} non si riferisce ad un file regolare, o si è usato \const{MAP\_PRIVATE} ma \param{fd} non è aperto in lettura, o si è usato \const{MAP\_SHARED} e impostato \const{PROT\_WRITE} ed \param{fd} non è aperto in lettura/scrittura, o si è impostato \const{PROT\_WRITE} ed \param{fd} è in \textit{append-only}. - \item[\errcode{EINVAL}] I valori di \param{start}, \param{length} o + \item[\errcode{EINVAL}] i valori di \param{start}, \param{length} o \param{offset} non sono validi (o troppo grandi o non allineati sulla dimensione delle pagine). - \item[\errcode{ETXTBSY}] Si è impostato \const{MAP\_DENYWRITE} ma + \item[\errcode{ETXTBSY}] si è impostato \const{MAP\_DENYWRITE} ma \param{fd} è aperto in scrittura. - \item[\errcode{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria + \item[\errcode{EAGAIN}] il file è bloccato, o si è bloccata troppa memoria rispetto a quanto consentito dai limiti di sistema (vedi sez.~\ref{sec:sys_resource_limit}). - \item[\errcode{ENOMEM}] Non c'è memoria o si è superato il limite sul + \item[\errcode{ENOMEM}] non c'è memoria o si è superato il limite sul numero di mappature possibili. - \item[\errcode{ENODEV}] Il filesystem di \param{fd} non supporta il memory + \item[\errcode{ENODEV}] il filesystem di \param{fd} non supporta il memory mapping. - \item[\errcode{EPERM}] L'argomento \param{prot} ha richiesto + \item[\errcode{EPERM}] l'argomento \param{prot} ha richiesto \const{PROT\_EXEC}, ma il filesystem di \param{fd} è montato con l'opzione \texttt{noexec}. - \item[\errcode{ENFILE}] Si è superato il limite del sistema sul numero di + \item[\errcode{ENFILE}] si è superato il limite del sistema sul numero di file aperti (vedi sez.~\ref{sec:sys_resource_limit}). \end{errlist} } @@ -2230,7 +2230,6 @@ multiplo della dimensione di una pagina di memoria. \label{tab:file_mmap_prot} \end{table} - Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux la memoria reale è divisa in pagine: ogni processo vede la sua memoria attraverso uno o più segmenti lineari di memoria virtuale. Per ciascuno di @@ -2240,7 +2239,7 @@ Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux che si chiama una \textit{segment violation}, e la relativa emissione del segnale \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere specificato come maschera binaria ottenuta dall'OR di uno o più dei valori -riportati in tab.~\ref{tab:file_mmap_flag}; il valore specificato deve essere +riportati in tab.~\ref{tab:file_mmap_prot}; il valore specificato deve essere compatibile con la modalità di accesso con cui si è aperto il file. L'argomento \param{flags} specifica infine qual è il tipo di oggetto mappato, @@ -2343,10 +2342,10 @@ eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una pagina, ed in generale queste potranno non corrispondere alle dimensioni effettive del file o della sezione che si vuole mappare. -\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di +\footnotetext[68]{dato che tutti faranno riferimento alle stesse pagine di memoria.} -\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato +\footnotetext[69]{l'uso di questo flag con \const{MAP\_SHARED} è stato implementato in Linux a partire dai kernel della serie 2.4.x; esso consente di creare segmenti di memoria condivisa e torneremo sul suo utilizzo in sez.~\ref{sec:ipc_mmap_anonymous}.} @@ -2457,10 +2456,10 @@ memoria mappata con il file su disco; il suo prototipo \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{EINVAL}] O \param{start} non è multiplo di + \item[\errcode{EINVAL}] o \param{start} non è multiplo di \const{PAGE\_SIZE}, o si è specificato un valore non valido per \param{flags}. - \item[\errcode{EFAULT}] L'intervallo specificato non ricade in una zona + \item[\errcode{EFAULT}] l'intervallo specificato non ricade in una zona precedentemente mappata. \end{errlist} } @@ -2487,7 +2486,8 @@ del file aggiornato. siano invalidate.\\ \hline \end{tabular} - \caption{Valori dell'argomento \param{flag} di \func{msync}.} + \caption{Le costanti che identificano i bit per la maschera binaria + dell'argomento \param{flag} di \func{msync}.} \label{tab:file_mmap_rsync} \end{table} @@ -2514,7 +2514,7 @@ mappatura della memoria usando la funzione \funcd{munmap}, il suo prototipo \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{EINVAL}] L'intervallo specificato non ricade in una zona + \item[\errcode{EINVAL}] l'intervallo specificato non ricade in una zona precedentemente mappata. \end{errlist} } @@ -2671,7 +2671,7 @@ nuova system call, \funcd{remap\_file\_pages}, il cui prototipo \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{EINVAL}] Si è usato un valore non valido per uno degli + \item[\errcode{EINVAL}] si è usato un valore non valido per uno degli argomenti o \param{start} non fa riferimento ad un \textit{memory mapping} valido creato con \const{MAP\_SHARED}. \end{errlist} @@ -2842,7 +2842,7 @@ questo tipo di situazioni. La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei dati fra due file descriptor è \funcd{sendfile};\footnote{la funzione è stata introdotta con i kernel della serie 2.2, e disponibile dalle \acr{glibc} - 2.1..} la funzione è presente in diverse versioni di Unix,\footnote{la si + 2.1.} la funzione è presente in diverse versioni di Unix,\footnote{la si ritrova ad esempio in FreeBSD, HPUX ed altri Unix.} ma non è presente né in POSIX.1-2001 né in altri standard,\footnote{pertanto si eviti di utilizzarla se si devono scrivere programmi portabili.} per cui per essa vengono @@ -2882,101 +2882,111 @@ funzione ritorna il numero di byte effettivamente copiati da \param{in\_fd} a Se il puntatore \param{offset} è nullo la funzione legge i dati a partire dalla posizione corrente su \param{in\_fd}, altrimenti verrà usata la -posizione indicata dal valore puntato da \param{offset}. In questo caso detto +posizione indicata dal valore puntato da \param{offset}; in questo caso detto valore sarà aggiornato, come \textit{value result argument}, per indicare la posizione del byte successivo all'ultimo che è stato letto, mentre la -posizione corrente sul file non sarà modificata. Se invece \param{offset} è +posizione corrente sul file non sarà modificata. Se invece \param{offset} è nullo la posizione corrente sul file sarà aggiornata tenendo conto dei byte letti da \param{in\_fd}. Fino ai kernel della serie 2.4 la funzione è utilizzabile su un qualunque file descriptor, e permette di sostituire la invocazione successiva di una -\func{read} ed una \func{write} (e l'allocazione del relativo buffer) con una +\func{read} e una \func{write} (e l'allocazione del relativo buffer) con una sola chiamata a \funcd{sendfile}. In questo modo si può diminuire il numero di chiamate al sistema e risparmiare in trasferimenti di dati da kernel space a user space e viceversa. La massima utilità della funzione si ha comunque per -il trasferimento di dati da un file su disco ad socket di rete,\footnote{il - caso classico del lavoro un server web, ed infatti Apache ha una opzione per - il supporto esplicito di questa funzione.} dato che in questo caso diventa -possibile effettuare il trasferimento diretto via DMA dal controller del disco -alla scheda di rete, senza neanche allocare un buffer nel kernel.\footnote{il - meccanismo è detto \textit{zerocopy} in quanto i dati non vengono mai - copiati dal kernel, che si limita a programmare solo le operazioni di - lettura e scrittura via DMA.} - -Con i kernel della serie 2.6 ci si è accorti però che, a parte quest'ultimo -caso, l'uso di \func{sendfile} non sempre portava significativi miglioramenti -delle prestazioni rispetto all'uso in sequenza di \func{read} e \func{write}, -\footnote{nel caso generico infatti il kernel deve comunque allocare un buffer - ed effettuare la copia dei dati, e in tal caso spesso il guadagno ottenibile - nel ridurre il numero di chiamate al sistema non compensa le ottimizzazioni - che possono essere fatte da una applicazione in user space che ha una - maggiore conoscenza su come questi sono strutturati.} e che anzi in certi -casi si avevano dei peggioramenti, questo ha portato alla -decisione\footnote{per alcune motivazioni di questa scelta si può fare - riferimento a quanto illustrato da Linus Torvalds in - \href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html} +il trasferimento di dati da un file su disco ad un socket di +rete,\footnote{questo è il caso classico del lavoro eseguito da un server web, + ed infatti Apache ha una opzione per il supporto esplicito di questa + funzione.} dato che in questo caso diventa possibile effettuare il +trasferimento diretto via DMA dal controller del disco alla scheda di rete, +senza neanche allocare un buffer nel kernel,\footnote{il meccanismo è detto + \textit{zerocopy} in quanto i dati non vengono mai copiati dal kernel, che + si limita a programmare solo le operazioni di lettura e scrittura via DMA.} +ottenendo la massima efficienza possibile senza pesare neanche sul processore. + +In seguito però ci si è accorti che, fatta eccezione per il trasferimento +diretto da file a socket, non sempre \func{sendfile} comportava miglioramenti +significativi delle prestazioni rispetto all'uso in sequenza di \func{read} e +\func{write},\footnote{nel caso generico infatti il kernel deve comunque + allocare un buffer ed effettuare la copia dei dati, e in tal caso spesso il + guadagno ottenibile nel ridurre il numero di chiamate al sistema non + compensa le ottimizzazioni che possono essere fatte da una applicazione in + user space che ha una conoscenza diretta su come questi sono strutturati.} e +che anzi in certi casi si potevano avere anche dei peggioramenti. Questo ha +portato, per i kernel della serie 2.6,\footnote{per alcune motivazioni di + questa scelta si può fare riferimento a quanto illustrato da Linus Torvalds + in \href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html} {\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}.} -di consentire l'uso della funzione soltanto quando il file da cui si legge -supporta le operazioni di \textit{memory mapping} (vale a dire non è un -socket) e quello su cui si scrive è un socket; in tutti gli altri casi si avrà -un errore di \errcode{EINVAL}. - -Nonostante i limiti illustrati resta comunque il dubbio se la scelta di -disabilitare \func{sendfile} per il trasferimento di dati fra file di dati sia -davvero corretta; la funzione infatti se non altro consentirebbe di -semplificare l'interfaccia per la copia dei dati, evitando di dover gestire -l'allocazione di un buffer temporaneo per il loro trasferimento in tutti quei -casi in cui non c'è necessità di fare controlli sugli stessi. Inoltre essa -avrebbe comunque il vantaggio di evitare trasferimenti di dati da e verso -l'user space. - -Il dubbio è stato rimosso con l'introduzione della system call -\func{splice},\footnote{avvenuto a partire dal kernel 2.6.17.} il cui scopo è -appunto quello di fornire un meccanismo generico per il trasferimento di dati -da o verso un file utilizzando un buffer intermedio gestito direttamente dal -kernel. Lo scopo della funzione può sembrare lo stesso di \func{sendfile}, ma -in realtà esse sono profondamente diverse nel loro meccanismo di -funzionamento; \func{sendfile} infatti, come accennato, non necessita affatto -(anzi nel caso di Linux viene sostanzialmente usata solo in questo caso) di -avere a disposizione un buffer interno, perché esegue un trasferimento diretto -di dati; questo la rende in generale molto più efficiente, ma anche limitata -nelle sue applicazioni. +alla decisione di consentire l'uso della funzione soltanto quando il file da +cui si legge supporta le operazioni di \textit{memory mapping} (vale a dire +non è un socket) e quello su cui si scrive è un socket; in tutti gli altri +casi l'uso di \func{sendfile} darà luogo ad un errore di \errcode{EINVAL}. + +Nonostante ci possano essere casi in cui \func{sendfile} non migliora le +prestazioni, le motivazioni addotte non convincono del tutto e resta il dubbio +se la scelta di disabilitarla sempre per il trasferimento di dati fra file di +dati sia davvero corretta. Se ci sono peggioramenti di prestazioni infatti si +può sempre fare ricorso all'uso successivo di, ma lasciare a disposizione la +funzione consentirebbe se non altro, anche in assenza di guadagni di +prestazioni, di semplificare la gestione della copia dei dati fra file, +evitando di dover gestire l'allocazione di un buffer temporaneo per il loro +trasferimento; inoltre si avrebbe comunque il vantaggio di evitare inutili +trasferimenti di dati da kernel space a user space e viceversa. + +Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuto a +partire dal kernel 2.6.17, della nuova system call \func{splice}. Lo scopo di +questa funzione è quello di fornire un meccanismo generico per il +trasferimento di dati da o verso un file utilizzando un buffer gestito +internamente dal kernel. Descritta in questi termini \func{splice} sembra +semplicemente un ``\textsl{dimezzamento}'' di \func{sendfile}.\footnote{nel + senso che un trasferimento di dati fra due file con \func{sendfile} non + sarebbe altro che la lettura degli stessi su un buffer seguita dalla + relativa scrittura, cosa che in questo caso si dovrebbe eseguire con due + chiamate a \func{splice}.} In realtà le due system call sono profondamente +diverse nel loro meccanismo di funzionamento; \func{sendfile} infatti, come +accennato, non necessita affatto di avere a disposizione un buffer interno, +perché esegue un trasferimento diretto di dati; questo la rende in generale +molto più efficiente, ma anche limitata nelle sue applicazioni, dato che +questo tipo di trasferimento è possibile solo in casi specifici.\footnote{e + nel caso di Linux questi sono anche solo quelli in cui essa può essere + effettivamente utilizzata.} Il concetto che sta dietro a \func{splice} invece è diverso,\footnote{in - realtà la proposta originale di Larry Mc Voy non ne differisce poi tanto, - quello che la rende davvero diversa è stata la reinterpretazione che ne è - stata fatta nell'implementazione su Linux realizzata da Jens Anxboe, di cui - si può trovare un buon riassunto in \href{http://kerneltrap.org/node/6505} + realtà la proposta originale di Larry Mc Voy non differisce poi tanto negli + scopi da \func{sendfile}, quello che rende \func{splice} davvero diversa è + stata la reinterpretazione che ne è stata fatta nell'implementazione su + Linux realizzata da Jens Anxboe, concetti che sono esposti sinteticamente + dallo stesso Linus Torvalds in \href{http://kerneltrap.org/node/6505} {\texttt{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una -funzione che consente di fare delle operazioni di trasferimento dati da e -verso un buffer interamente gestito in kernel space, in maniera del tutto -generica. In questo caso il cuore della funzione (e delle affini -\func{vmsplice} e \func{tee}, che tratteremo più avanti) è appunto il buffer -in kernel space; questo è anche quello che ne ha semplificato -l'adozione,\footnote{la funzione infatti non è definita in nessuno standard, - e, allo stato attuale è disponibile soltanto su Linux.} perché -l'infrastruttura per la gestione di un buffer in kernel space è presente fin -dagli albori di Unix per la realizzazione delle \textit{pipe} (tratteremo -l'argomento in sez.~\ref{sec:ipc_unix}). Dal punto di vista concettuale allora -\func{splice} non è che un'altra interfaccia con cui esporre in userspace -l'oggetto \textsl{buffer in kernel space}. +funzione che consente di fare in maniera del tutto generica delle operazioni +di trasferimento di dati fra un file e un buffer gestito interamente in kernel +space. In questo caso il cuore della funzione (e delle affini \func{vmsplice} +e \func{tee}, che tratteremo più avanti) è appunto l'uso di un buffer in +kernel space, e questo è anche quello che ne ha semplificato l'adozione, +perché l'infrastruttura per la gestione di un tale buffer è presente fin dagli +albori di Unix per la realizzazione delle \textit{pipe} (vedi +sez.~\ref{sec:ipc_unix}). Dal punto di vista concettuale allora \func{splice} +non è altro che una diversa interfaccia (rispetto alle \textit{pipe}) con cui +utilizzare in user space l'oggetto ``\textsl{buffer in kernel space}''. Così se per una \textit{pipe} o una \textit{fifo} il buffer viene utilizzato -come area di memoria dove appoggiare i dati che vengono trasferiti da un capo -all'altro della stessa (vedi fig.~\ref{fig:ipc_pipe_singular}) per creare un -meccanismo di comunicazione fra processi, nel caso di \funcd{splice} il buffer +come area di memoria (vedi fig.~\ref{fig:ipc_pipe_singular}) dove appoggiare i +dati che vengono trasferiti da un capo all'altro della stessa per creare un +meccanismo di comunicazione fra processi, nel caso di \func{splice} il buffer viene usato o come fonte dei dati che saranno scritti su un file, o come -destinazione dei dati che vengono letti da un file. La funzione infatti è una -interfaccia generica che consente di trasferire dati da un buffer ad un file o -viceversa; il suo prototipo, accessibile solo avendo definito -\macro{\_GNU\_SOURCE},\footnote{ovviamente, essendo come detto la funzione - totalmente specifica di Linux, essa non è prevista da nessuno standard e - deve essere evitata se si vogliono scrivere programmi portabili.} è: +destinazione dei dati che vengono letti da un file. La funzione \funcd{splice} +fornisce quindi una interfaccia generica che consente di trasferire dati da un +buffer ad un file o viceversa; il suo prototipo, accessibile solo dopo aver +definito la macro \macro{\_GNU\_SOURCE},\footnote{si ricordi che questa + funzione non è contemplata da nessuno standard, è presente solo su Linux, e + pertanto deve essere evitata se si vogliono scrivere programmi portabili.} +è il seguente: \begin{functions} \headdecl{fcntl.h} - \funcdecl{} + \funcdecl{long splice(int fd\_in, off\_t *off\_in, int fd\_out, off\_t + *off\_out, size\_t len, unsigned int flags)} Trasferisce dati da un file verso una pipe o viceversa. @@ -2984,19 +2994,79 @@ viceversa; il suo prototipo, accessibile solo avendo definito successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{EAGAIN}] si è impostata la modalità non bloccante su - \param{out\_fd} e la scrittura si bloccherebbe. - \item[\errcode{EINVAL}] i file descriptor non sono validi, o sono bloccati - (vedi sez.~\ref{sec:file_locking}), o \func{mmap} non è disponibile per - \param{in\_fd}. - \item[\errcode{EIO}] si è avuto un errore di lettura da \param{in\_fd}. - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per la lettura da - \param{in\_fd}. + \item[\errcode{EBADF}] uno o entrambi fra \param{fd\_in} e \param{fd\_out} + non sono file descriptor validi o, rispettivamente, non sono stati + aperti in lettura o scrittura. + \item[\errcode{EINVAL}] il filesystem su cui si opera non supporta + \func{splice}, oppure nessuno dei file descriptor è una pipe, oppure si + è dato un valore a \param{off\_in} o \param{off\_out} ma il + corrispondente file è un dispositivo che non supporta la funzione + \func{seek}. + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione + richiesta. + \item[\errcode{ESPIPE}] o \param{off\_in} o \param{off\_out} non sono + \const{NULL} ma il corrispondente file descriptor è una \textit{pipe}. \end{errlist} - ed inoltre \errcode{EBADF} e \errcode{EFAULT}. } \end{functions} +La funzione esegue un trasferimento di \param{count} byte dal file descriptor +\param{fd\_in} al file descriptor \param{fd\_out}, uno dei quali deve essere +una \textit{pipe}; l'altro file descriptor può essere +qualunque.\footnote{questo significa che può essere, oltre che un file di + dati, anche un altra \textit{pipe}, o un socket.} Come accennato una +\textit{pipe} non è altro che un buffer in kernel space, per cui a seconda che +essa sia usata per \param{fd\_in} o \param{fd\_out} si avrà rispettivamente la +copia dei dati dal buffer al file o viceversa. + +In caso di successo la funzione ritorna il numero di byte trasferiti, che può +essere, come per le normali funzioni di lettura e scrittura su file, inferiore +a quelli richiesti; un valore negativo indicherà un errore mentre un valore +nullo indicherà che non ci sono dati da trasferire (ad esempio si è giunti +alla fine del file in lettura). Si tenga presente che, a seconda del verso del +trasferimento dei dati, la funzione si comporta nei confronti del file +descriptor che fa riferimento al file ordinario, come \func{read} o +\func{write}, e pertanto potrà anche bloccarsi (a meno che non si sia aperto +il suddetto file in modalità non bloccante). + +I due argomenti \param{off\_in} e \param{off\_out} consentono di specificare, +come per l'analogo \param{offset} di \func{sendfile}, la posizione all'interno +del file da cui partire per il trasferimento dei dati. Come per +\func{sendfile} un valore nullo indica di usare la posizione corrente sul +file, ed essa sarà aggiornata automaticamente secondo il numero di byte +trasferiti. Un valore non nullo invece deve essere un puntatore ad una +variabile intera che indica la posizione da usare; questa verrà aggiornata, al +ritorno della funzione, al byte successivo all'ultimo byte trasferito. +Ovviamente soltanto uno di questi due argomenti, e più precisamente quello che +fa riferimento al file descriptor non associato alla \textit{pipe}, può essere +specificato come valore non nullo. + +Infine l'argomento \param{flag} consente di controllare alcune caratteristiche +del funzionamento della funzione; il contenuto è una maschera binaria e deve +essere specificato come OR aritmetico dei valori riportati in +tab.~\ref{tab:splice_flag}. + + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{SPLICE\_F\_MOVE} & .\\ + \const{SPLICE\_F\_NONBLOCK}& .\\ + \const{SPLICE\_F\_MORE} & .\\ + \const{SPLICE\_F\_GIFT} & .\\ + \hline + \end{tabular} + \caption{Le costanti che identificano i bit della maschera binaria + dell'argomento \param{flag} di \func{slice}, \func{vmslice} e \func{tee}.} + \label{tab:splice_flag} +\end{table} + + % TODO documentare le funzioni tee e splice @@ -3177,7 +3247,7 @@ rimuovere un \textit{file lock} \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{EWOULDBLOCK}] Il file ha già un blocco attivo, e si è + \item[\errcode{EWOULDBLOCK}] il file ha già un blocco attivo, e si è specificato \const{LOCK\_NB}. \end{errlist} } @@ -3313,17 +3383,17 @@ essa viene usata solo secondo il prototipo: \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{EACCES}] L'operazione è proibita per la presenza di + \item[\errcode{EACCES}] l'operazione è proibita per la presenza di \textit{file lock} da parte di altri processi. - \item[\errcode{ENOLCK}] Il sistema non ha le risorse per il locking: ci + \item[\errcode{ENOLCK}] il sistema non ha le risorse per il locking: ci sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock, o il protocollo per il locking remoto è fallito. - \item[\errcode{EDEADLK}] Si è richiesto un lock su una regione bloccata da + \item[\errcode{EDEADLK}] si è richiesto un lock su una regione bloccata da un altro processo che è a sua volta in attesa dello sblocco di un lock mantenuto dal processo corrente; si avrebbe pertanto un \itindex{deadlock} \textit{deadlock}. Non è garantito che il sistema riconosca sempre questa situazione. - \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale prima + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di poter acquisire un lock. \end{errlist} ed inoltre \errval{EBADF}, \errval{EFAULT}. @@ -3755,10 +3825,10 @@ che utilizza la funzione \funcd{lockf}, il cui prototipo \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{EWOULDBLOCK}] Non è possibile acquisire il lock, e si è + \item[\errcode{EWOULDBLOCK}] non è possibile acquisire il lock, e si è selezionato \const{LOCK\_NB}, oppure l'operazione è proibita perché il file è mappato in memoria. - \item[\errcode{ENOLCK}] Il sistema non ha le risorse per il locking: ci + \item[\errcode{ENOLCK}] il sistema non ha le risorse per il locking: ci sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock. \end{errlist} ed inoltre \errval{EBADF}, \errval{EINVAL}. diff --git a/filedir.tex b/filedir.tex index f30fee5..1415649 100644 --- a/filedir.tex +++ b/filedir.tex @@ -775,16 +775,16 @@ struttura precedentemente allocata e specificata dall'argomento \param{entry} (anche se non è assicurato che la funzione usi lo spazio fornito dall'utente). I vari campi di \struct{dirent} contengono le informazioni relative alle voci -presenti nella directory; sia BSD che SVr4\footnote{POSIX prevede invece solo - la presenza del campo \var{d\_fileno}, identico \var{d\_ino}, che in Linux è - definito come alias di quest'ultimo. Il campo \var{d\_name} è considerato - dipendente dall'implementazione.} prevedono che siano sempre presenti il -campo \var{d\_name}, che contiene il nome del file nella forma di una stringa -terminata da uno zero,\footnote{lo standard POSIX non specifica una lunghezza, - ma solo un limite \const{NAME\_MAX}; in SVr4 la lunghezza del campo è - definita come \code{NAME\_MAX+1} che di norma porta al valore di 256 byte - usato anche in Linux.} ed il campo \var{d\_ino}, che contiene il numero di -\index{inode} inode cui il file è associato (di solito corrisponde al campo +presenti nella directory; sia BSD che SVr4\footnote{lo standard POSIX prevede + invece solo la presenza del campo \var{d\_fileno}, identico \var{d\_ino}, + che in Linux è definito come alias di quest'ultimo. Il campo \var{d\_name} è + considerato dipendente dall'implementazione.} prevedono che siano sempre +presenti il campo \var{d\_name}, che contiene il nome del file nella forma di +una stringa terminata da uno zero,\footnote{lo standard POSIX non specifica + una lunghezza, ma solo un limite \const{NAME\_MAX}; in SVr4 la lunghezza del + campo è definita come \code{NAME\_MAX+1} che di norma porta al valore di 256 + byte usato anche in Linux.} ed il campo \var{d\_ino}, che contiene il numero +di \index{inode} inode cui il file è associato (di solito corrisponde al campo \var{st\_ino} di \struct{stat}). \begin{figure}[!htb] @@ -1777,7 +1777,7 @@ realizzare. Una delle caratteristiche fondamentali di tutti i sistemi unix-like è quella del controllo di accesso ai file, che viene implementato per qualunque filesystem standard.\footnote{per standard si intende che implementa le - caratteristiche previste dallo standard POSIX. In Linux sono disponibili + caratteristiche previste dallo standard POSIX; in Linux sono disponibili anche una serie di altri filesystem, come quelli di Windows e del Mac, che non supportano queste caratteristiche.} In questa sezione ne esamineremo i concetti essenziali e le funzioni usate per gestirne i vari aspetti. @@ -1791,7 +1791,7 @@ cosiddetto \textit{owner}) ed un gruppo di appartenenza, secondo il meccanismo degli identificatori di utente e gruppo (\acr{uid} e \acr{gid}). Questi valori sono accessibili da programma tramite la funzione \func{stat}, e sono mantenuti nei campi \var{st\_uid} e \var{st\_gid} della struttura -\struct{stat} (si veda sez.~\ref{sec:file_stat}).\footnote{Questo è vero solo +\struct{stat} (si veda sez.~\ref{sec:file_stat}).\footnote{questo è vero solo per filesystem di tipo Unix, ad esempio non è vero per il filesystem vfat di Windows, che non fornisce nessun supporto per l'accesso multiutente, e per il quale i permessi vengono assegnati in maniera fissa con un opzione in @@ -1800,12 +1800,12 @@ mantenuti nei campi \var{st\_uid} e \var{st\_gid} della struttura Il controllo di accesso ai file segue un modello abbastanza semplice che prevede tre permessi fondamentali strutturati su tre livelli di accesso. Esistono varie estensioni a questo modello,\footnote{come le \textit{Access - Control List} che possono essere aggiunte al filesystem standard con - opportune patch, la cui introduzione nei kernel ufficiali è iniziata con la - serie 2.5.x. per arrivare a meccanismi di controllo ancora più sofisticati - come il \textit{mandatory access control} di SE-Linux.} ma nella maggior -parte dei casi il meccanismo standard è più che sufficiente a soddisfare tutte -le necessità più comuni. I tre permessi di base associati ad ogni file sono: + Control List} che sono state aggiunte ai filesystem standard con opportune + estensioni (vedi sez.~\ref{sec:file_ACL}) per arrivare a meccanismi di + controllo ancora più sofisticati come il \textit{mandatory access control} + di SE-Linux.} ma nella maggior parte dei casi il meccanismo standard è più +che sufficiente a soddisfare tutte le necessità più comuni. I tre permessi di +base associati ad ogni file sono: \begin{itemize*} \item il permesso di lettura (indicato con la lettera \texttt{r}, dall'inglese \textit{read}). diff --git a/fileintro.tex b/fileintro.tex index f5c46c6..cee6e9a 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -91,7 +91,7 @@ oggetto del filesystem, compresa un'altra directory, si ottiene naturalmente un'organizzazione ad albero inserendo nomi di directory in altre directory. Un file può essere indicato rispetto alla directory corrente semplicemente -specificandone il nome\footnote{Il manuale delle \acr{glibc} chiama i nomi +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 diff --git a/fileunix.tex b/fileunix.tex index 8f02459..bf476ee 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -638,7 +638,7 @@ rieseguire la funzione. Torneremo in dettaglio sull'argomento in sez.~\ref{sec:sig_gen_beha}. La seconda si verifica quando il file è aperto in modalità non bloccante (vedi sez.~\ref{sec:file_noblocking}) e non ci sono dati in ingresso: la funzione allora ritorna immediatamente con un errore -\errcode{EAGAIN}\footnote{BSD usa per questo errore la costante +\errcode{EAGAIN}\footnote{in BSD si usa per questo errore la costante \errcode{EWOULDBLOCK}, in Linux, con le \acr{glibc}, questa è sinonima di \errcode{EAGAIN}.} che indica soltanto che non essendoci al momento dati disponibili occorre provare a ripetere la lettura in un secondo tempo. diff --git a/intro.tex b/intro.tex index aff48b7..378dd84 100644 --- a/intro.tex +++ b/intro.tex @@ -237,7 +237,7 @@ viene richiesto all'ingresso nel sistema dalla procedura di \textit{login} (descritta in dettaglio in sez.~\ref{sec:sess_login}). Questa procedura si incarica di verificare l'identità dell'utente, in genere attraverso la richiesta di una parola d'ordine (la \textit{password}), anche se sono -possibili meccanismi diversi.\footnote{Ad esempio usando la libreria PAM +possibili meccanismi diversi.\footnote{ad esempio usando la libreria PAM (\textit{Pluggable Autentication Methods}) è possibile astrarre completamente dai meccanismi di autenticazione e sostituire ad esempio l'uso delle password con meccanismi di identificazione biometrica.} diff --git a/ipc.tex b/ipc.tex index 75e8849..0b4bd7a 100644 --- a/ipc.tex +++ b/ipc.tex @@ -134,7 +134,7 @@ Per capire meglio il funzionamento delle 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. Realizzeremo il programma di esempio nella forma di un -\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è 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 barre, specificato come argomento in ingresso. @@ -569,7 +569,7 @@ ricevuta la risposta, uscir A questo punto il server resta (se non ci sono altri client che stanno effettuando richieste) con la fifo chiusa sul lato in lettura, ed in questo stato la funzione \func{read} non si bloccherà in attesa di input, ma -ritornerà in continuazione, restituendo un end-of-file.\footnote{Si è usata +ritornerà in continuazione, restituendo un end-of-file.\footnote{si è usata questa tecnica per compatibilità, Linux infatti supporta l'apertura delle fifo in lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura con \const{O\_RDWR}, la doppia apertura comunque ha il vantaggio @@ -2573,9 +2573,9 @@ stato marcato per la cancellazione. \label{fig:ipc_shmem_layout} \end{figure} -L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{Lo standard +L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{lo standard SVID prevede che l'argomento \param{shmaddr} sia di tipo \ctyp{char *}, così - come il valore di ritorno della funzione. In Linux è stato così con le + come il valore di ritorno della funzione; in Linux è stato così con le \acr{libc4} e le \acr{libc5}, con il passaggio alle \acr{glibc} il tipo di \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di ritorno un \ctyp{void *}.} deve essere associato il segmento, se il valore diff --git a/network.tex b/network.tex index d7d6e8c..96462f9 100644 --- a/network.tex +++ b/network.tex @@ -317,7 +317,7 @@ la procedura si pu pagine web, viene di solito definito ed implementato quello che viene chiamato un protocollo di applicazione (esempi possono essere HTTP, POP, SMTP, ecc.), ciascuno dei quali è descritto in un opportuno standard (di - solito attraverso un RFC\footnote{L'acronimo RFC sta per \textit{Request For + solito attraverso un RFC\footnote{l'acronimo RFC sta per \textit{Request For 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 diff --git a/session.tex b/session.tex index da7aff4..b254579 100644 --- a/session.tex +++ b/session.tex @@ -298,7 +298,7 @@ dal quale ricevono gli eventuali segnali da tastiera. A tale scopo lo standard POSIX.1 prevede che ad ogni sessione possa essere associato un terminale di controllo; in Linux questo viene realizzato mantenendo fra gli attributi di ciascun processo anche qual'è il suo terminale -di controllo.\footnote{Lo standard POSIX.1 non specifica nulla riguardo +di controllo.\footnote{lo standard POSIX.1 non specifica nulla riguardo l'implementazione; in Linux anch'esso viene mantenuto nella solita struttura \struct{task\_struct}, nel campo \var{tty}.} In generale ogni processo eredita dal padre, insieme al \acr{pgid} e al \acr{sid} anche il terminale di @@ -601,9 +601,10 @@ niente a che fare con la gestione diretta dei comandi dell'utente. Questi programmi, che devono essere eseguiti in modalità non interattiva e senza nessun intervento dell'utente, sono normalmente chiamati \textsl{demoni}, (o \textit{daemons}), nome ispirato dagli omonimi spiritelli -che svolgevano compiti vari, di cui parlava Socrate (che sosteneva di averne -uno al suo servizio).\footnote{NdT. ricontrollare, i miei ricordi di filosofia - sono piuttosto datati.} +della mitologia greca che svolgevano compiti che gli dei trovavano noiosi, di +cui parla anche Socrate (che sosteneva di averne uno al suo servizio). + +%TODO ricontrollare, i miei ricordi di filosofia sono piuttosto datati. Se però si lancia un programma demone dalla riga di comando in un sistema che supporta, come Linux, il \textit{job control} esso verrà comunque associato ad @@ -1784,7 +1785,6 @@ i terminali hanno un insieme di funzionalit di code di ingresso ed uscita; in generale si fa riferimento ad esse con il nome di \textsl{discipline di linea}. - Lo standard POSIX prevede alcune funzioni che permettono di intervenire direttamente sulla gestione di quest'ultime e sull'interazione fra i dati in ingresso ed uscita e le relative code. In generale tutte queste funzioni @@ -1814,9 +1814,9 @@ La funzione invia un flusso di bit nulli (che genera una condizione di break) sul terminale associato a \param{fd}; un valore nullo di \param{duration} implica una durata del flusso fra 0.25 e 0.5 secondi, un valore diverso da zero implica una durata pari a \code{duration*T} dove \code{T} è un valore -compreso fra 0.25 e 0.5.\footnote{POSIX specifica il comportamento solo nel - caso si sia impostato un valore nullo per \param{duration}; il comportamento - negli altri casi può dipendere dalla implementazione.} +compreso fra 0.25 e 0.5.\footnote{lo standard POSIX specifica il comportamento + solo nel caso si sia impostato un valore nullo per \param{duration}; il + comportamento negli altri casi può dipendere dalla implementazione.} Le altre funzioni previste da POSIX servono a controllare il comportamento dell'interazione fra le code associate al terminale e l'utente; la prima è @@ -1922,6 +1922,7 @@ riportati in tab.~\ref{tab:sess_tcflow_action}. \end{table} + \subsection{Operare in \textsl{modo non canonico}} \label{sec:term_non_canonical} diff --git a/signal.tex b/signal.tex index f2dd09b..e86d9d2 100644 --- a/signal.tex +++ b/signal.tex @@ -1794,7 +1794,7 @@ tab.~\ref{tab:sig_sa_flag}. % TODO con il 2.6 sono stati aggiunti SA_NOCLDWAIT e altro, documentare Come si può notare in fig.~\ref{fig:sig_sigaction} \func{sigaction} permette -di utilizzare due forme diverse di gestore,\footnote{La possibilità è prevista +di utilizzare due forme diverse di gestore,\footnote{la possibilità è prevista dallo standard POSIX.1b, ed è stata aggiunta nei kernel della serie 2.1.x con l'introduzione dei segnali real-time (vedi sez.~\ref{sec:sig_real_time}); in precedenza era possibile ottenere alcune diff --git a/sockctrl.tex b/sockctrl.tex index bfdfcd9..7bce251 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -2605,7 +2605,7 @@ esiste, ma il comportamento di \const{SO\_REUSEADDR} possibile effettuare un \textit{completely duplicate binding} ed ottenere il successo di \func{bind} su un socket legato allo stesso indirizzo e porta solo se il programma che ha eseguito per primo \func{bind} su di essi ha impostato -questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto +questa opzione.\footnote{questa restrizione permette di evitare il cosiddetto \textit{port stealing}, in cui un programma, usando \const{SO\_REUSEADDR}, può collegarsi ad una porta già in uso e ricevere i pacchetti destinati ad un altro programma; con questa caratteristica ciò è possibile soltanto se il diff --git a/system.tex b/system.tex index 8142546..ddd77b8 100644 --- a/system.tex +++ b/system.tex @@ -533,7 +533,7 @@ il manuale delle \acr{glibc} indica due diverse dimensioni, \const{\_UTSNAME\_LENGTH} per i campi standard e \const{\_UTSNAME\_DOMAIN\_LENGTH} per quello specifico per il nome di dominio; altri sistemi usano nomi diversi come \const{SYS\_NMLN} o \const{\_SYS\_NMLN} -o \const{UTSLEN} che possono avere valori diversi.\footnote{Nel caso di Linux +o \const{UTSLEN} che possono avere valori diversi.\footnote{nel caso di Linux \func{uname} corrisponde in realtà a 3 system call diverse, le prime due usano rispettivamente delle lunghezze delle stringhe di 9 e 65 byte; la terza usa anch'essa 65 byte, ma restituisce anche l'ultimo campo, @@ -2434,7 +2434,7 @@ costante \val{EOF} (a seconda della funzione); ma questo valore segnala solo che c'è stato un errore, non il tipo di errore. Per riportare il tipo di errore il sistema usa la variabile globale -\var{errno},\footnote{L'uso di una variabile globale può comportare alcuni +\var{errno},\footnote{l'uso di una variabile globale può comportare alcuni problemi (ad esempio nel caso dei thread) ma lo standard ISO C consente anche di definire \var{errno} come un \textit{modifiable lvalue}, quindi si può anche usare una macro, e questo è infatti il modo usato da Linux per diff --git a/tcpsock.tex b/tcpsock.tex index 485f36f..724b402 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -42,7 +42,7 @@ significato di alcuni dei vari \textsl{stati} ad essa associati. \itindbeg{three~way~handshake} Il processo che porta a creare una connessione TCP è chiamato \textit{three way handshake}; la successione tipica degli eventi (e dei -\textsl{segmenti}\footnote{Si ricordi che il segmento è l'unità elementare di +\textsl{segmenti}\footnote{si ricordi che il segmento è l'unità elementare di dati trasmessa dal protocollo TCP al livello successivo; tutti i segmenti hanno un header che contiene le informazioni che servono allo \textit{stack TCP} (così viene di solito chiamata la parte del kernel che implementa il @@ -149,7 +149,7 @@ connessione. Normalmente vengono usate le seguenti opzioni: sez.~\ref{sec:tcp_protocol_xxx}) con la quale ciascun capo della comunicazione dichiara quanto spazio disponibile ha in memoria per i dati. Questo è un numero a 16 bit dell'header, che così può indicare un massimo di - 65535 byte;\footnote{Linux usa come massimo 32767 per evitare problemi con + 65535 byte;\footnote{in Linux il massimo è 32767 per evitare problemi con alcune implementazioni che usano l'aritmetica con segno per implementare lo stack TCP.} ma alcuni tipi di connessione come quelle ad alta velocità (sopra i 45Mbit/sec) e quelle che hanno grandi ritardi nel cammino dei -- 2.30.2