all'origine di Unix i soli programmi che potevano avere una tale esigenza
erano i demoni, attenendosi a uno dei criteri base della progettazione, che
era di far fare al kernel solo le operazioni strettamente necessarie e
-lasciare tutto il resto a processi in user space, non era stata prevista
-nessuna funzionalità di notifica.
+lasciare tutto il resto a processi in \textit{user space}, non era stata
+prevista nessuna funzionalità di notifica.
Visto però il crescente interesse nei confronti di una funzionalità di questo
tipo, che è molto richiesta specialmente nello sviluppo dei programmi ad
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 di
-\itindex{thread} \textit{thread}. Per le versioni del kernel meno recenti
-esiste una implementazione di questa interfaccia fornita completamente delle
-\acr{glibc} a partire dalla versione 2.1, che è realizzata completamente in
-user space, ed è accessibile linkando i programmi con la libreria
+implementata sia direttamente nel kernel che in \textit{user space} attraverso
+l'uso di \itindex{thread} \textit{thread}. Per le versioni del kernel meno
+recenti esiste una implementazione di questa interfaccia fornita completamente
+delle \acr{glibc} a partire dalla versione 2.1, che è realizzata completamente
+in \textit{user space}, ed è accessibile linkando i programmi con la libreria
\file{librt}. A partire dalla versione 2.5.32 è stato introdotto nel kernel
una nuova infrastruttura per l'I/O asincrono, ma ancora il supporto è parziale
ed insufficiente ad implementare tutto l'AIO POSIX.
specificato con uno dei valori riportati in
tab.~\ref{tab:madvise_advice_values}; si tenga presente che i valori indicati
nella seconda parte della tabella sono specifici di Linux e non sono previsti
-dallo standard POSIX.1b.
-La funzione non ha, tranne il caso di \const{MADV\_DONTFORK}, nessun effetto
-sul comportamento di un programma, ma può influenzarne le prestazioni fornendo
-al kernel indicazioni sulle esigenze dello stesso, così che sia possibile
-scegliere le opportune strategie per la gestione del \itindex{read-ahead}
-\textit{read-ahead} e del caching dei dati.
+dallo standard POSIX.1b. La funzione non ha, tranne il caso di
+\const{MADV\_DONTFORK}, nessun effetto sul comportamento di un programma, ma
+può influenzarne le prestazioni fornendo al kernel indicazioni sulle esigenze
+dello stesso, così che sia possibile scegliere le opportune strategie per la
+gestione del \textit{read-ahead} (vedi sez.~\ref{sec:file_fadvise}) e del
+caching dei dati.
\begin{table}[!htb]
\centering
file descriptor, e permetteva di sostituire la invocazione successiva di una
\func{read} e una \func{write} (e l'allocazione del relativo buffer) con una
sola chiamata a \funcd{sendfile}. In questo modo si poteva 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 ottiene
-comunque per 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 (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)
+di chiamate al sistema e risparmiare in trasferimenti di dati da
+\textit{kernel space} a \textit{user space} e viceversa. La massima utilità
+della funzione si ottiene comunque per 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 (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 accorse che, fatta eccezione per il trasferimento
\func{write}. 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, per cui 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
- \url{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}.} 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} da luogo ad un errore di \errcode{EINVAL}.
+ottimizzazioni che possono essere fatte da una applicazione in \textit{user
+ space} che ha una conoscenza diretta su come questi sono strutturati, per
+cui 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 \url{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}.}
+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} da luogo ad un errore di \errcode{EINVAL}.
Nonostante ci possano essere casi in cui \func{sendfile} non migliora le
prestazioni, resta il dubbio se la scelta di disabilitarla sempre per il
In realtà le due \textit{system call} sono profondamente diverse nel loro
meccanismo di funzionamento;\footnote{questo fino al kernel 2.6.23, dove
\func{sendfile} è stata reimplementata in termini di \func{splice}, pur
- mantenendo disponibile la stessa interfaccia verso l'user space.}
+ mantenendo disponibile la stessa interfaccia verso l'\textit{user space}.}
\func{sendfile} infatti, come accennato, non necessita di avere a disposizione
un buffer interno, perché esegue un trasferimento diretto di dati; questo la
rende in generale più efficiente, ma anche limitata nelle sue applicazioni,
generica delle operazioni di trasferimento di dati fra un file e un buffer
gestito interamente in \textit{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 \textit{user space} l'oggetto
-``\textsl{buffer in kernel space}''.
+avanti) è appunto l'uso di un buffer in \textit{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 \textit{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 (vedi fig.~\ref{fig:ipc_pipe_singular}) dove appoggiare i
\begin{funcproto}{
\fhead{fcntl.h}
\fdecl{long splice(int fd\_in, off\_t *off\_in, int fd\_out, off\_t
- *off\_out, size\_t len, unsigned int flags)}
+ *off\_out, size\_t len, \\
+\phantom{long splice(}unsigned int flags)}
\fdesc{Trasferisce dati da un file verso una \textit{pipe} o viceversa.}
}
copiarle: per una maggiore efficienza
\func{splice} usa quando possibile i
meccanismi della memoria virtuale per
- eseguire i trasferimenti di dati; in maniera
+ eseguire i trasferimenti di dati. In maniera
analoga a \func{mmap}), qualora le pagine non
possano essere spostate dalla \textit{pipe} o
il buffer non corrisponda a pagine intere
Per capire meglio il funzionamento di \func{splice} vediamo un esempio con un
semplice programma che usa questa funzione per effettuare la copia di un file
-su un altro senza utilizzare buffer in user space. Lo scopo del programma è
-quello di eseguire la copia dei dati con \func{splice}, questo significa che
-si dovrà usare la funzione due volte, prima per leggere i dati dal file di
-ingresso e poi per scriverli su quello di uscita, appoggiandosi ad una
-\textit{pipe}: lo schema del flusso dei dati è illustrato in
+su un altro senza utilizzare buffer in \textit{user space}. Lo scopo del
+programma è quello di eseguire la copia dei dati con \func{splice}, questo
+significa che si dovrà usare la funzione due volte, prima per leggere i dati
+dal file di ingresso e poi per scriverli su quello di uscita, appoggiandosi ad
+una \textit{pipe}: lo schema del flusso dei dati è illustrato in
fig.~\ref{fig:splicecp_data_flux}.
\begin{figure}[htb]
\centering
- \includegraphics[height=4cm]{img/splice_copy}
+ \includegraphics[height=3.5cm]{img/splice_copy}
\caption{Struttura del flusso di dati usato dal programma \texttt{splicecp}.}
\label{fig:splicecp_data_flux}
\end{figure}
Si noti come il programma sia concettualmente identico a quello che si sarebbe
scritto usando \func{read} al posto della prima \func{splice} e \func{write}
-al posto della seconda, utilizzando un buffer in user space per eseguire la
-copia dei dati, solo che in questo caso non è stato necessario allocare nessun
-buffer e non si è trasferito nessun dato in user space.
-
-Si noti anche come si sia usata la combinazione \texttt{SPLICE\_F\_MOVE |
- SPLICE\_F\_MORE } per l'argomento \param{flags} di \func{splice}, infatti
-anche se un valore nullo avrebbe dato gli stessi risultati, l'uso di questi
-flag, che si ricordi servono solo a dare suggerimenti al kernel, permette in
-genere di migliorare le prestazioni.
+al posto della seconda, utilizzando un buffer in \textit{user space} per
+eseguire la copia dei dati, solo che in questo caso non è stato necessario
+allocare nessun buffer e non si è trasferito nessun dato in \textit{user
+ space}. Si noti anche come si sia usata la combinazione
+\texttt{SPLICE\_F\_MOVE | SPLICE\_F\_MORE } per l'argomento \param{flags} di
+\func{splice}, infatti anche se un valore nullo avrebbe dato gli stessi
+risultati, l'uso di questi flag, che si ricordi servono solo a dare
+suggerimenti al kernel, permette in genere di migliorare le prestazioni.
Come accennato con l'introduzione di \func{splice} sono state realizzate anche
altre due \textit{system call}, \func{vmsplice} e \func{tee}, che utilizzano
la stessa infrastruttura e si basano sullo stesso concetto di manipolazione e
-trasferimento di dati attraverso un buffer in kernel space; benché queste non
-attengono strettamente ad operazioni di trasferimento dati fra file
+trasferimento di dati attraverso un buffer in \textit{kernel space}; benché
+queste non attengono strettamente ad operazioni di trasferimento dati fra file
descriptor, le tratteremo qui, essendo strettamente correlate fra loro.
La prima funzione, \funcd{vmsplice}, è la più simile a \func{splice} e come
indica il suo nome consente di trasferire i dati dalla memoria virtuale di un
processo (ad esempio per un file mappato in memoria) verso una \textit{pipe};
il suo prototipo è:
-\begin{functions}
- \headdecl{fcntl.h}
- \headdecl{sys/uio.h}
- \funcdecl{long vmsplice(int fd, const struct iovec *iov, unsigned long
- nr\_segs, unsigned int flags)}
-
- Trasferisce dati dalla memoria di un processo verso una \textit{pipe}.
+\begin{funcproto}{
+\fhead{fcntl.h}
+\fhead{sys/uio.h}
+\fdecl{long vmsplice(int fd, const struct iovec *iov, unsigned long nr\_segs,\\
+\phantom{long vmsplice(}unsigned int flags)}
+\fdesc{Trasferisce dati dalla memoria di un processo verso una \textit{pipe}.}
+}
- \bodydesc{La funzione restituisce il numero di byte trasferiti in caso di
- successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
- dei valori:
- \begin{errlist}
+{La funzione ritorna il numero di byte trasferiti in caso di successo e $-1$
+ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\item[\errcode{EBADF}] o \param{fd} non è un file descriptor valido o non
fa riferimento ad una \textit{pipe}.
\item[\errcode{EINVAL}] si è usato un valore nullo per \param{nr\_segs}
oppure si è usato \const{SPLICE\_F\_GIFT} ma la memoria non è allineata.
\item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione
richiesta.
- \end{errlist}
- }
-\end{functions}
+ \end{errlist}
+}
+\end{funcproto}
La \textit{pipe} indicata da \param{fd} dovrà essere specificata tramite il
file descriptor corrispondente al suo capo aperto in scrittura (di nuovo si
eseguire una copia dei dati che contengono.
La seconda funzione aggiunta insieme a \func{splice} è \func{tee}, che deve il
-suo nome all'omonimo comando in user space, perché in analogia con questo
-permette di duplicare i dati in ingresso su una \textit{pipe} su un'altra
-\textit{pipe}. In sostanza, sempre nell'ottica della manipolazione dei dati su
-dei buffer in kernel space, la funzione consente di eseguire una copia del
-contenuto del buffer stesso. Il prototipo di \funcd{tee} è il seguente:
-\begin{functions}
- \headdecl{fcntl.h}
+suo nome all'omonimo comando in \textit{user space}, perché in analogia con
+questo permette di duplicare i dati in ingresso su una \textit{pipe} su
+un'altra \textit{pipe}. In sostanza, sempre nell'ottica della manipolazione
+dei dati su dei buffer in \textit{kernel space}, la funzione consente di
+eseguire una copia del contenuto del buffer stesso. Il prototipo di
+\funcd{tee} è il seguente:
- \funcdecl{long tee(int fd\_in, int fd\_out, size\_t len, unsigned int
+\begin{funcproto}{
+\fhead{fcntl.h}
+\fdecl{long tee(int fd\_in, int fd\_out, size\_t len, unsigned int
flags)}
-
- Duplica \param{len} byte da una \textit{pipe} ad un'altra.
+\fdesc{Duplica i dati da una \textit{pipe} ad un'altra.}
+}
- \bodydesc{La funzione restituisce il numero di byte copiati in caso di
- successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
- dei valori:
- \begin{errlist}
+{La funzione ritorna restituisce il numero di byte copiati in caso di successo
+ e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\item[\errcode{EINVAL}] o uno fra \param{fd\_in} e \param{fd\_out} non fa
riferimento ad una \textit{pipe} o entrambi fanno riferimento alla
stessa \textit{pipe}.
\item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione
richiesta.
- \end{errlist}
- }
-\end{functions}
+ \end{errlist}
+}
+\end{funcproto}
La funzione copia \param{len} byte del contenuto di una \textit{pipe} su di
un'altra; \param{fd\_in} deve essere il capo in lettura della \textit{pipe}
La funzione restituisce il numero di byte copiati da una \textit{pipe}
all'altra (o $-1$ in caso di errore), un valore nullo indica che non ci sono
byte disponibili da copiare e che il capo in scrittura della \textit{pipe} è
-stato chiuso.\footnote{si tenga presente però che questo non avviene se si è
- impostato il flag \const{SPLICE\_F\_NONBLOCK}, in tal caso infatti si
- avrebbe un errore di \errcode{EAGAIN}.} Un esempio di realizzazione del
-comando \texttt{tee} usando questa funzione, ripreso da quello fornito nella
-pagina di manuale e dall'esempio allegato al patch originale, è riportato in
+stato chiuso; si tenga presente però che questo non avviene se si è impostato
+il flag \const{SPLICE\_F\_NONBLOCK}, in tal caso infatti si avrebbe un errore
+di \errcode{EAGAIN}. Un esempio di realizzazione del comando \texttt{tee}
+usando questa funzione, ripreso da quello fornito nella pagina di manuale e
+dall'esempio allegato al patch originale, è riportato in
fig.~\ref{fig:tee_example}. Il programma consente di copiare il contenuto
-dello standard input sullo standard output e su un file specificato come
-argomento, il codice completo si trova nel file \texttt{tee.c} dei sorgenti
-allegati alla guida.
+dello \textit{standard input} sullo \textit{standard output} e su un file
+specificato come argomento, il codice completo si trova nel file
+\texttt{tee.c} dei sorgenti allegati alla guida.
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{\codesamplewidth}
\includecodesample{listati/tee.c}
\label{fig:tee_example}
\end{figure}
-La prima parte del programma (\texttt{\small 10-35}) si cura semplicemente di
-controllare (\texttt{\small 11-14}) che sia stato fornito almeno un argomento
-(il nome del file su cui scrivere), di aprirlo ({\small 15-19}) e che sia lo
-standard input (\texttt{\small 20-27}) che lo standard output (\texttt{\small
- 28-35}) corrispondano ad una \textit{pipe}.
+La prima parte del programma, che si è omessa per brevità, si cura
+semplicemente di controllare che sia stato fornito almeno un argomento (il
+nome del file su cui scrivere), di aprirlo e che sia lo standard input che lo
+standard output corrispondano ad una \textit{pipe}.
-Il ciclo principale (\texttt{\small 37-58}) inizia con la chiamata a
+Il ciclo principale (\texttt{\small 11-32}) inizia con la chiamata a
\func{tee} che duplica il contenuto dello standard input sullo standard output
-(\texttt{\small 39}), questa parte è del tutto analoga ad una lettura ed
+(\texttt{\small 13}), questa parte è del tutto analoga ad una lettura ed
infatti come nell'esempio di fig.~\ref{fig:splice_example} si controlla il
valore di ritorno della funzione in \var{len}; se questo è nullo significa che
-non ci sono più dati da leggere e si chiude il ciclo (\texttt{\small 40}), se
+non ci sono più dati da leggere e si chiude il ciclo (\texttt{\small 14}), se
è negativo c'è stato un errore, ed allora si ripete la chiamata se questo è
-dovuto ad una interruzione (\texttt{\small 42-44}) o si stampa un messaggio
-di errore e si esce negli altri casi (\texttt{\small 44-47}).
-
-Una volta completata la copia dei dati sullo standard output si possono
-estrarre dalla standard input e scrivere sul file, di nuovo su usa un ciclo di
-scrittura (\texttt{\small 50-58}) in cui si ripete una chiamata a
-\func{splice} (\texttt{\small 51}) fintanto che non si sono scritti tutti i
-\var{len} byte copiati in precedenza con \func{tee} (il funzionamento è
-identico all'analogo ciclo di scrittura del precedente esempio di
+dovuto ad una interruzione (\texttt{\small 15-48}) o si stampa un messaggio
+di errore e si esce negli altri casi (\texttt{\small 18-21}).
+
+Una volta completata la copia dei dati sullo \textit{standard output} si
+possono estrarre dallo \textit{standard input} e scrivere sul file, di nuovo
+su usa un ciclo di scrittura (\texttt{\small 24-31}) in cui si ripete una
+chiamata a \func{splice} (\texttt{\small 25}) fintanto che non si sono scritti
+tutti i \var{len} byte copiati in precedenza con \func{tee} (il funzionamento
+è identico all'analogo ciclo di scrittura del precedente esempio di
fig.~\ref{fig:splice_example}).
Infine una nota finale riguardo \func{splice}, \func{vmsplice} e \func{tee}:
\itindbeg{read-ahead}
Una prima funzione che può essere utilizzata per modificare la gestione
-ordinaria dell'I/O su un file è \funcd{readahead},\footnote{questa è una
- funzione specifica di Linux, introdotta con il kernel 2.4.13, e non deve
- essere usata se si vogliono scrivere programmi portabili.} che consente di
-richiedere una lettura anticipata del contenuto dello stesso in cache, così
-che le seguenti operazioni di lettura non debbano subire il ritardo dovuto
-all'accesso al disco; il suo prototipo è:
-\begin{functions}
- \headdecl{fcntl.h}
+ordinaria dell'I/O su un file è \funcd{readahead} (questa è una funzione
+specifica di Linux, introdotta con il kernel 2.4.13, e non deve essere usata
+se si vogliono scrivere programmi portabili), che consente di richiedere una
+lettura anticipata del contenuto dello stesso in cache, così che le seguenti
+operazioni di lettura non debbano subire il ritardo dovuto all'accesso al
+disco; il suo prototipo è:
- \funcdecl{ssize\_t readahead(int fd, off64\_t *offset, size\_t count)}
-
- Esegue una lettura preventiva del contenuto di un file in cache.
+\begin{funcproto}{
+\fhead{fcntl.h}
+\fdecl{ssize\_t readahead(int fd, off64\_t *offset, size\_t count)}
+\fdesc{Esegue una lettura preventiva del contenuto di un file in cache.}
+}
- \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}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\item[\errcode{EBADF}] l'argomento \param{fd} non è un file descriptor
valido o non è aperto in lettura.
\item[\errcode{EINVAL}] l'argomento \param{fd} si riferisce ad un tipo di
file che non supporta l'operazione (come una \textit{pipe} o un socket).
- \end{errlist}
- }
-\end{functions}
+ \end{errlist}
+}
+\end{funcproto}
La funzione richiede che venga letto in anticipo il contenuto del file
\param{fd} a partire dalla posizione \param{offset} e per un ammontare di
in blocchi corrispondenti alle dimensioni delle pagine di memoria, ed i valori
di \param{offset} e \param{count} vengono arrotondati di conseguenza.
-La funzione estende quello che è un comportamento normale del kernel che
+La funzione estende quello che è un comportamento normale del kernel che,
quando si legge un file, aspettandosi che l'accesso prosegua, esegue sempre
una lettura preventiva di una certa quantità di dati; questo meccanismo di
lettura anticipata viene chiamato \textit{read-ahead}, da cui deriva il nome
\itindend{read-ahead}
Il concetto di \func{readahead} viene generalizzato nello standard
-POSIX.1-2001 dalla funzione \func{posix\_fadvise},\footnote{anche se
- l'argomento \param{len} è stato modificato da \type{size\_t} a \type{off\_t}
- nella revisione POSIX.1-2003 TC5.} che consente di ``\textsl{avvisare}'' il
+POSIX.1-2001 dalla funzione \func{posix\_fadvise} (anche se
+l'argomento \param{len} è stato modificato da \type{size\_t} a \type{off\_t}
+nella revisione POSIX.1-2003 TC5) che consente di ``\textsl{avvisare}'' il
kernel sulle modalità con cui si intende accedere nel futuro ad una certa
-porzione di un file,\footnote{la funzione però è stata introdotta su Linux
- solo a partire dal kernel 2.5.60.} così che esso possa provvedere le
-opportune ottimizzazioni; il prototipo di \funcd{posix\_fadvise}, che è
-disponibile soltanto se è stata definita la macro \macro{\_XOPEN\_SOURCE} ad
-valore di almeno 600, è:
-\begin{functions}
- \headdecl{fcntl.h}
+porzione di un file, così che esso possa provvedere le opportune
+ottimizzazioni; il prototipo di \funcd{posix\_fadvise}\footnote{la funzione è
+ stata introdotta su Linux solo a partire dal kernel 2.5.60, ed è disponibile
+ soltanto se è stata definita la macro \macro{\_XOPEN\_SOURCE} ad valore di
+ almeno \texttt{600} o la macro \macro{\_POSIX\_C\_SOURCE} ad valore di
+ almeno \texttt{200112L}.} è:
- \funcdecl{int posix\_fadvise(int fd, off\_t offset, off\_t len, int advice)}
-
- Dichiara al kernel le future modalità di accesso ad un file.
- \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}
+\begin{funcproto}{
+\fhead{fcntl.h}
+\fdecl{int posix\_fadvise(int fd, off\_t offset, off\_t len, int advice)}
+\fdesc{Dichiara al kernel le future modalità di accesso ad un file.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\item[\errcode{EBADF}] l'argomento \param{fd} non è un file descriptor
valido.
\item[\errcode{EINVAL}] il valore di \param{advice} non è valido o
\param{fd} si riferisce ad un tipo di file che non supporta l'operazione
(come una \textit{pipe} o un socket).
- \item[\errcode{ESPIPE}] previsto dallo standard se \param{fd} è una \textit{pipe} o
- un socket (ma su Linux viene restituito \errcode{EINVAL}).
- \end{errlist}
- }
-\end{functions}
+ \item[\errcode{ESPIPE}] previsto dallo standard se \param{fd} è una
+ \textit{pipe} o un socket (ma su Linux viene restituito
+ \errcode{EINVAL}).
+ \end{errlist}
+}
+\end{funcproto}
La funzione dichiara al kernel le modalità con cui intende accedere alla
regione del file indicato da \param{fd} che inizia alla posizione