richiede che il valore di \param{timeout} non sia modificato.
Rispetto a \func{select} la nuova funzione prende un argomento
-aggiuntivo \param{sigmask}, un puntatore ad una \index{maschera~dei~segnali}
-maschera di segnali (si veda sez.~\ref{sec:sig_sigmask}). Nell'esecuzione la
-maschera dei segnali corrente viene sostituita da quella così indicata
-immediatamente prima di eseguire l'attesa, e viene poi ripristinata al ritorno
-della funzione. L'uso di \param{sigmask} è stato introdotto allo scopo di
-prevenire possibili \textit{race condition} \itindex{race~condition} quando
-oltre alla presenza di dati sui file descriptor come nella \func{select}
-ordinaria, ci si deve porre in attesa anche dell'arrivo di un segnale.
+aggiuntivo \param{sigmask}, un puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}). Nell'esecuzione la maschera dei segnali corrente
+viene sostituita da quella così indicata immediatamente prima di eseguire
+l'attesa, e viene poi ripristinata al ritorno della funzione. L'uso
+di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
+\textit{race condition} \itindex{race~condition} quando oltre alla presenza di
+dati sui file descriptor come nella \func{select} ordinaria, ci si deve porre
+in attesa anche dell'arrivo di un segnale.
Come abbiamo visto in sez.~\ref{sec:sig_example} la tecnica classica per
rilevare l'arrivo di un segnale è quella di utilizzare il gestore per
\func{select}, che è una estensione tipica di BSD, è stata introdotta una
interfaccia completamente diversa, basata sulla funzione di sistema
\funcd{poll},\footnote{la funzione è prevista dallo standard XPG4, ed è stata
- introdotta in Linux come system call a partire dal kernel 2.1.23 ed inserita
- nelle \acr{libc} 5.4.28, originariamente l'argomento \param{nfds} era di
- tipo \ctyp{unsigned int}, la funzione è stata inserita nello standard
+ introdotta in Linux come \textit{system call} a partire dal kernel 2.1.23 ed
+ inserita nelle \acr{libc} 5.4.28, originariamente l'argomento \param{nfds}
+ era di tipo \ctyp{unsigned int}, la funzione è stata inserita nello standard
POSIX.1-2001 in cui è stato introdotto il tipo nativo \type{nfds\_t}.} il
cui prototipo è:
\end{funcproto}
La funzione ha lo stesso comportamento di \func{poll}, solo che si può
-specificare, con l'argomento \param{sigmask}, il puntatore ad una
-\index{maschera~dei~segnali} maschera di segnali; questa sarà la maschera
-utilizzata per tutto il tempo che la funzione resterà in attesa, all'uscita
-viene ripristinata la maschera originale. L'uso di questa funzione è cioè
-equivalente, come illustrato nella pagina di manuale, all'esecuzione atomica
-del seguente codice:
+specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di
+segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione
+resterà in attesa, all'uscita viene ripristinata la maschera originale. L'uso
+di questa funzione è cioè equivalente, come illustrato nella pagina di
+manuale, all'esecuzione atomica del seguente codice:
\includecodesnip{listati/ppoll_means.c}
Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
contemporaneamente. Valgono le osservazioni fatte in
sez.~\ref{sec:file_select}, e per poterlo fare di nuovo è necessaria una
variante della funzione di attesa che consenta di reimpostare all'uscita una
-\index{maschera~dei~segnali} maschera di segnali, analoga alle estensioni
-\func{pselect} e \func{ppoll} che abbiamo visto in precedenza per
-\func{select} e \func{poll}. In questo caso la funzione di sistema si chiama
-\funcd{epoll\_pwait}\footnote{la funzione è stata introdotta a partire dal
- kernel 2.6.19, ed è come tutta l'interfaccia di \textit{epoll}, specifica di
- Linux.} ed il suo prototipo è:
+maschera di segnali, analoga alle estensioni \func{pselect} e \func{ppoll} che
+abbiamo visto in precedenza per \func{select} e \func{poll}. In questo caso la
+funzione di sistema si chiama \funcd{epoll\_pwait}\footnote{la funzione è
+ stata introdotta a partire dal kernel 2.6.19, ed è, come tutta l'interfaccia
+ di \textit{epoll}, specifica di Linux.} ed il suo prototipo è:
\begin{funcproto}{
\fhead{sys/epoll.h}
\end{funcproto}
La funzione è del tutto analoga \funcd{epoll\_wait}, soltanto che alla sua
-uscita viene ripristinata la \index{maschera~dei~segnali} maschera di segnali
-originale, sostituita durante l'esecuzione da quella impostata con
-l'argomento \param{sigmask}; in sostanza la chiamata a questa funzione è
-equivalente al seguente codice, eseguito però in maniera atomica:
+uscita viene ripristinata la maschera di segnali originale, sostituita durante
+l'esecuzione da quella impostata con l'argomento \param{sigmask}; in sostanza
+la chiamata a questa funzione è equivalente al seguente codice, eseguito però
+in maniera atomica:
\includecodesnip{listati/epoll_pwait_means.c}
Si tenga presente che come le precedenti funzioni di \textit{I/O multiplexing}
versione, \funcm{signalfd4}, introdotta con il kernel 2.6.27 e che è quella
che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un
argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della
- \index{maschera~dei~segnali} maschera dei segnali, il cui valore viene
- impostato automaticamente dalle \acr{glibc}.} il cui prototipo è:
+ maschera dei segnali, il cui valore viene impostato automaticamente dalle
+ \acr{glibc}.} il cui prototipo è:
\begin{funcproto}{
\fhead{sys/signalfd.h}
L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere
specificato tramite l'argomento \param{mask}. Questo deve essere passato come
-puntatore ad una \index{maschera~dei~segnali} maschera di segnali creata con
-l'uso delle apposite macro già illustrate in sez.~\ref{sec:sig_sigset}. La
-maschera deve indicare su quali segnali si intende operare con
-\func{signalfd}; l'elenco può essere modificato con una successiva chiamata a
-\func{signalfd}. Dato che \signal{SIGKILL} e \signal{SIGSTOP} non possono
-essere intercettati (e non prevedono neanche la possibilità di un gestore) un
-loro inserimento nella maschera verrà ignorato senza generare errori.
+puntatore ad una maschera di segnali creata con l'uso delle apposite macro già
+illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali
+segnali si intende operare con \func{signalfd}; l'elenco può essere modificato
+con una successiva chiamata a \func{signalfd}. Dato che \signal{SIGKILL} e
+\signal{SIGSTOP} non possono essere intercettati (e non prevedono neanche la
+possibilità di un gestore) un loro inserimento nella maschera verrà ignorato
+senza generare errori.
L'argomento \param{flags} consente di impostare direttamente in fase di
creazione due flag per il file descriptor analoghi a quelli che si possono
quello che useremo per il controllo degli altri. É poi necessario
disabilitare la ricezione dei segnali (nel caso \signal{SIGINT},
\signal{SIGQUIT} e \signal{SIGTERM}) per i quali si vuole la notifica tramite
-file descriptor. Per questo prima li si inseriscono (\texttt{\small 22-25})
-in una \index{maschera~dei~segnali} maschera di segnali \texttt{sigmask} che
-useremo con (\texttt{\small 26}) \func{sigprocmask} per disabilitarli. Con la
-stessa maschera si potrà per passare all'uso (\texttt{\small 28-29}) di
-\func{signalfd} per abilitare la notifica sul file descriptor
-\var{sigfd}. Questo poi (\texttt{\small 30-33}) dovrà essere aggiunto con
-\func{epoll\_ctl} all'elenco di file descriptor controllati con \texttt{epfd}.
+file descriptor. Per questo prima li si inseriscono (\texttt{\small 22-25}) in
+una maschera di segnali \texttt{sigmask} che useremo con (\texttt{\small 26})
+\func{sigprocmask} per disabilitarli. Con la stessa maschera si potrà per
+passare all'uso (\texttt{\small 28-29}) di \func{signalfd} per abilitare la
+notifica sul file descriptor \var{sigfd}. Questo poi (\texttt{\small 30-33})
+dovrà essere aggiunto con \func{epoll\_ctl} all'elenco di file descriptor
+controllati con \texttt{epfd}.
Occorrerà infine (\texttt{\small 35-38}) creare la \textit{named fifo} se
questa non esiste ed aprirla per la lettura (\texttt{\small 39-40}); una
di caricare in memoria solo le parti del file che sono effettivamente usate ad
un dato istante.
-Infatti, dato che l'accesso è fatto direttamente attraverso la
-\index{memoria~virtuale} memoria virtuale, la sezione di memoria mappata su
-cui si opera sarà a sua volta letta o scritta sul file una pagina alla volta e
-solo per le parti effettivamente usate, il tutto in maniera completamente
-trasparente al processo; l'accesso alle pagine non ancora caricate avverrà
-allo stesso modo con cui vengono caricate in memoria le pagine che sono state
-salvate sullo \textit{swap}.
+Infatti, dato che l'accesso è fatto direttamente attraverso la memoria
+virtuale, la sezione di memoria mappata su cui si opera sarà a sua volta letta
+o scritta sul file una pagina alla volta e solo per le parti effettivamente
+usate, il tutto in maniera completamente trasparente al processo; l'accesso
+alle pagine non ancora caricate avverrà allo stesso modo con cui vengono
+caricate in memoria le pagine che sono state salvate sullo \textit{swap}.
Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un file
vengono salvate automaticamente, così come le pagine dei programmi vengono
protezioni delle pagine di memoria; lo standard prevede che essa si applichi
solo ai \textit{memory mapping} creati con \func{mmap}, ma nel caso di Linux
la funzione può essere usata con qualunque pagina valida nella memoria
-virtuale. Questa funzione è \funcd{mprotect} ed il suo prototipo è:
-\begin{functions}
-% \headdecl{unistd.h}
- \headdecl{sys/mman.h}
+virtuale. Questa funzione di sistema è \funcd{mprotect} ed il suo prototipo è:
- \funcdecl{int mprotect(const void *addr, size\_t len, int prot)}
-
- Modifica le protezioni delle pagine di memoria comprese nell'intervallo
- specificato.
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int mprotect(const void *addr, size\_t len, int prot)}
+\fdesc{Modifica le protezioni delle pagine di memoria.}
+}
- \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{EINVAL}] il valore di \param{addr} non è valido o non è un
multiplo di \const{PAGE\_SIZE}.
\item[\errcode{EACCES}] l'operazione non è consentita, ad esempio si è
cercato di marcare con \const{PROT\_WRITE} un segmento di memoria cui si
ha solo accesso in lettura.
-% \item[\errcode{ENOMEM}] non è stato possibile allocare le risorse
-% necessarie all'interno del kernel.
-% \item[\errcode{EFAULT}] si è specificato un indirizzo di memoria non
-% accessibile.
- \end{errlist}
- ed inoltre \errval{ENOMEM} ed \errval{EFAULT}.
- }
-\end{functions}
-
+ \item[\errcode{ENOMEM}] non è stato possibile allocare le risorse
+ necessarie all'interno del kernel o si è specificato un indirizzo di
+ memoria non valido del processo o non corrispondente a pagine mappate
+ (negli ultimi due casi prima del kernel 2.4.19 veniva prodotto,
+ erroneamente, \errcode{EFAULT}).
+ \end{errlist}
+}
+\end{funcproto}
La funzione prende come argomenti un indirizzo di partenza in \param{addr},
allineato alle dimensioni delle pagine di memoria, ed una dimensione
dall'intervallo fra \param{addr} e \param{addr}+\param{size}-1.
Infine Linux supporta alcune operazioni specifiche non disponibili su altri
-kernel unix-like. La prima di queste è la possibilità di modificare un
-precedente \textit{memory mapping}, ad esempio per espanderlo o restringerlo.
-Questo è realizzato dalla funzione \funcd{mremap}, il cui prototipo è:
-\begin{functions}
- \headdecl{unistd.h}
- \headdecl{sys/mman.h}
+kernel unix-like per poter usare le quali occorre però dichiarare
+\macro{\_GNU\_SOURCE} prima dell'inclusione di \texttt{sys/mman.h}. La prima
+di queste è la possibilità di modificare un precedente \textit{memory
+ mapping}, ad esempio per espanderlo o restringerlo. Questo è realizzato
+dalla funzione di sistema \funcd{mremap}, il cui prototipo è:
- \funcdecl{void * mremap(void *old\_address, size\_t old\_size , size\_t
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{void * mremap(void *old\_address, size\_t old\_size , size\_t
new\_size, unsigned long flags)}
-
- Restringe o allarga una mappatura in memoria di un file.
+\fdesc{Restringe o allarga una mappatura in memoria.}
+}
- \bodydesc{La funzione restituisce l'indirizzo alla nuova area di memoria in
- caso di successo od il valore \const{MAP\_FAILED} (pari a \texttt{(void *)
- -1}) in caso di errore, nel qual caso \var{errno} assumerà uno dei
- valori:
- \begin{errlist}
+{La funzione ritorna l'indirizzo alla nuova area di memoria in caso di
+ successo o il valore \const{MAP\_FAILED} (pari a \texttt{(void *) -1}), nel
+ qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
\item[\errcode{EINVAL}] il valore di \param{old\_address} non è un
puntatore valido.
\item[\errcode{EFAULT}] ci sono indirizzi non validi nell'intervallo
è specificato \const{MREMAP\_MAYMOVE} nei flag.
\item[\errcode{EAGAIN}] il segmento di memoria scelto è bloccato e non può
essere rimappato.
- \end{errlist}
- }
-\end{functions}
+ \end{errlist}
+}
+\end{funcproto}
La funzione richiede come argomenti \param{old\_address} (che deve essere
allineato alle dimensioni di una pagina di memoria) che specifica il
indica la dimensione. Con \param{new\_size} si specifica invece la nuova
dimensione che si vuole ottenere. Infine l'argomento \param{flags} è una
maschera binaria per i flag che controllano il comportamento della funzione.
-Il solo valore utilizzato è \const{MREMAP\_MAYMOVE}\footnote{per poter
- utilizzare questa costante occorre aver definito \macro{\_GNU\_SOURCE} prima
- di includere \headfile{sys/mman.h}.} che consente di eseguire l'espansione
-anche quando non è possibile utilizzare il precedente indirizzo. Per questo
-motivo, se si è usato questo flag, la funzione può restituire un indirizzo
-della nuova zona di memoria che non è detto coincida con \param{old\_address}.
-
-La funzione si appoggia al sistema della \index{memoria~virtuale} memoria
-virtuale per modificare l'associazione fra gli indirizzi virtuali del processo
-e le pagine di memoria, modificando i dati direttamente nella
-\itindex{page~table} \textit{page table} del processo. Come per
-\func{mprotect} la funzione può essere usata in generale, anche per pagine di
-memoria non corrispondenti ad un \textit{memory mapping}, e consente così di
-implementare la funzione \func{realloc} in maniera molto efficiente.
+Il solo valore utilizzato è \const{MREMAP\_MAYMOVE} che consente di eseguire
+l'espansione anche quando non è possibile utilizzare il precedente
+indirizzo. Per questo motivo, se si è usato questo flag, la funzione può
+restituire un indirizzo della nuova zona di memoria che non è detto coincida
+con \param{old\_address}.
+
+La funzione si appoggia al sistema della memoria virtuale per modificare
+l'associazione fra gli indirizzi virtuali del processo e le pagine di memoria,
+modificando i dati direttamente nella \textit{page table} del processo. Come
+per \func{mprotect} la funzione può essere usata in generale, anche per pagine
+di memoria non corrispondenti ad un \textit{memory mapping}, e consente così
+di implementare la funzione \func{realloc} in maniera molto efficiente.
Una caratteristica comune a tutti i sistemi unix-like è che la mappatura in
memoria di un file viene eseguita in maniera lineare, cioè parti successive di
un file vengono mappate linearmente su indirizzi successivi in memoria.
-Esistono però delle applicazioni\footnote{in particolare la tecnica è usata
- dai database o dai programmi che realizzano macchine virtuali.} in cui è
-utile poter mappare sezioni diverse di un file su diverse zone di memoria.
+Esistono però delle applicazioni (in particolare la tecnica è usata dai
+database o dai programmi che realizzano macchine virtuali) in cui è utile
+poter mappare sezioni diverse di un file su diverse zone di memoria.
Questo è ovviamente sempre possibile eseguendo ripetutamente la funzione
\func{mmap} per ciascuna delle diverse aree del file che si vogliono mappare
-in sequenza non lineare,\footnote{ed in effetti è quello che veniva fatto
- anche con Linux prima che fossero introdotte queste estensioni.} ma questo
-approccio ha delle conseguenze molto pesanti in termini di prestazioni.
-Infatti per ciascuna mappatura in memoria deve essere definita nella
-\itindex{page~table} \textit{page table} del processo una nuova area di
-memoria virtuale\footnote{quella che nel gergo del kernel viene chiamata VMA
- (\textit{virtual memory area}).} che corrisponda alla mappatura, in modo che
-questa diventi visibile nello spazio degli indirizzi come illustrato in
-fig.~\ref{fig:file_mmap_layout}.
-
-Quando un processo esegue un gran numero di mappature diverse\footnote{si può
- arrivare anche a centinaia di migliaia.} per realizzare a mano una mappatura
-non-lineare si avrà un accrescimento eccessivo della sua \itindex{page~table}
-\textit{page table}, e lo stesso accadrà per tutti gli altri processi che
-utilizzano questa tecnica. In situazioni in cui le applicazioni hanno queste
-esigenze si avranno delle prestazioni ridotte, dato che il kernel dovrà
-impiegare molte risorse\footnote{sia in termini di memoria interna per i dati
- delle \itindex{page~table} \textit{page table}, che di CPU per il loro
- aggiornamento.} solo per mantenere i dati di una gran quantità di
-\textit{memory mapping}.
+in sequenza non lineare (ed in effetti è quello che veniva fatto anche con
+Linux prima che fossero introdotte queste estensioni) ma questo approccio ha
+delle conseguenze molto pesanti in termini di prestazioni. Infatti per
+ciascuna mappatura in memoria deve essere definita nella \textit{page table}
+del processo una nuova area di memoria virtuale, quella che nel gergo del
+kernel viene chiamata VMA (\textit{virtual memory area}, che corrisponda alla
+mappatura, in modo che questa diventi visibile nello spazio degli indirizzi
+come illustrato in fig.~\ref{fig:file_mmap_layout}.
+
+Quando un processo esegue un gran numero di mappature diverse (si può arrivare
+anche a centinaia di migliaia) per realizzare a mano una mappatura non-lineare
+esso vedrà un accrescimento eccessivo della sua \textit{page table}, e lo
+stesso accadrà per tutti gli altri processi che utilizzano questa tecnica. In
+situazioni in cui le applicazioni hanno queste esigenze si avranno delle
+prestazioni ridotte, dato che il kernel dovrà impiegare molte risorse per
+mantenere i dati relativi al \textit{memory mapping}, sia in termini di
+memoria interna per i dati delle \textit{page table}, che di CPU per il loro
+aggiornamento.
Per questo motivo con il kernel 2.5.46 è stato introdotto, ad opera di Ingo
Molnar, un meccanismo che consente la mappatura non-lineare. Anche questa è
una caratteristica specifica di Linux, non presente in altri sistemi
-unix-like. Diventa così possibile utilizzare una sola mappatura
-iniziale\footnote{e quindi una sola \textit{virtual memory area} nella
- \itindex{page~table} \textit{page table} del processo.} e poi rimappare a
-piacere all'interno di questa i dati del file. Ciò è possibile grazie ad una
-nuova \textit{system call}, \funcd{remap\_file\_pages}, il cui prototipo è:
-\begin{functions}
- \headdecl{sys/mman.h}
+unix-like. Diventa così possibile utilizzare una sola mappatura iniziale, e
+quindi una sola \textit{virtual memory area} nella \textit{page table} del
+processo, e poi rimappare a piacere all'interno di questa i dati del file. Ciò
+è possibile grazie ad una nuova \textit{system call},
+\funcd{remap\_file\_pages}, il cui prototipo è:
- \funcdecl{int remap\_file\_pages(void *start, size\_t size, int prot,
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int remap\_file\_pages(void *start, size\_t size, int prot,
ssize\_t pgoff, int flags)}
-
- Permette di rimappare non linearmente un precedente \textit{memory mapping}.
+\fdesc{Rimappa non linearmente un \textit{memory mapping}.}
+}
- \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{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}
- }
-\end{functions}
+ \end{errlist}
+ ed inoltre
+ nel loro significato generico.}
+\end{funcproto}
Per poter utilizzare questa funzione occorre anzitutto effettuare
preliminarmente una chiamata a \func{mmap} con \const{MAP\_SHARED} per
-definire l'area di memoria che poi sarà rimappata non linearmente. Poi di
+definire l'area di memoria che poi sarà rimappata non linearmente. Poi si
chiamerà questa funzione per modificare le corrispondenze fra pagine di
memoria e pagine del file; si tenga presente che \func{remap\_file\_pages}
permette anche di mappare la stessa pagina di un file in più pagine della
\textit{memory mapping}.
Questo vuol dire che il passaggio dei dati dal disco alla memoria avverrà una
-pagina alla volta con un gran numero di \itindex{page~fault} \textit{page
- fault}, chiaramente se si sa in anticipo che il file verrà utilizzato
-immediatamente, è molto più efficiente eseguire un \textit{prefaulting} in cui
-tutte le pagine di memoria interessate alla mappatura vengono
-``\textsl{popolate}'' in una sola volta, questo comportamento viene abilitato
-quando si usa con \func{mmap} il flag \const{MAP\_POPULATE}.
+pagina alla volta con un gran numero di \textit{page fault}, chiaramente se si
+sa in anticipo che il file verrà utilizzato immediatamente, è molto più
+efficiente eseguire un \textit{prefaulting} in cui tutte le pagine di memoria
+interessate alla mappatura vengono ``\textsl{popolate}'' in una sola volta,
+questo comportamento viene abilitato quando si usa con \func{mmap} il flag
+\const{MAP\_POPULATE}.
Dato che l'uso di \const{MAP\_POPULATE} comporta dell'I/O su disco che può
rallentare l'esecuzione di \func{mmap} è stato introdotto anche un secondo
database effettuare accessi ai dati in maniera pressoché casuale, mentre un
riproduttore audio o video eseguirà per lo più letture sequenziali.
+\itindend{memory~mapping}
+
Per migliorare le prestazioni a seconda di queste modalità di accesso è
disponibile una apposita funzione, \funcd{madvise},\footnote{tratteremo in
sez.~\ref{sec:file_fadvise} le funzioni che consentono di ottimizzare
l'accesso ai file con l'interfaccia classica.} che consente di fornire al
-kernel delle indicazioni su dette modalità, così che possano essere adottate
-le opportune strategie di ottimizzazione. Il suo prototipo è:
-\begin{functions}
- \headdecl{sys/mman.h}
+kernel delle indicazioni su come un processo intende accedere ad un segmento
+di memoria, anche al di là delle mappature dei file, così che possano essere
+adottate le opportune strategie di ottimizzazione. Il suo prototipo è:
- \funcdecl{int madvise(void *start, size\_t length, int advice)}
-
- Fornisce indicazioni sull'uso previsto di un \textit{memory mapping}.
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int madvise(void *start, size\_t length, int advice)}
+\fdesc{Fornisce indicazioni sull'uso previsto di un segmento di memoria.}
+}
- \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}] la mappatura esiste ma non corrisponde ad un file.
\item[\errcode{EINVAL}] \param{start} non è allineato alla dimensione di
una pagina, \param{length} ha un valore negativo, o \param{advice} non è
un valore valido, o si è richiesto il rilascio (con
- \const{MADV\_DONTNEED}) di pagine bloccate o condivise.
+ \const{MADV\_DONTNEED}) di pagine bloccate o condivise o si è usato
+ \const{MADV\_MERGEABLE} o \const{MADV\_UNMERGEABLE} ma il kernel non è
+ stato compilato per il relativo supporto.
\item[\errcode{EIO}] la paginazione richiesta eccederebbe i limiti (vedi
sez.~\ref{sec:sys_resource_limit}) sulle pagine residenti in memoria del
processo (solo in caso di \const{MADV\_WILLNEED}).
\item[\errcode{ENOMEM}] gli indirizzi specificati non sono mappati, o, in
caso \const{MADV\_WILLNEED}, non c'è sufficiente memoria per soddisfare
la richiesta.
- \end{errlist}
- ed inoltre \errval{EAGAIN} e \errval{ENOSYS}.
- }
-\end{functions}
+ \end{errlist}
+ ed inoltre \errval{EAGAIN} e \errval{ENOSYS} nel loro significato generico.}
+\end{funcproto}
La sezione di memoria sulla quale si intendono fornire le indicazioni deve
essere indicata con l'indirizzo iniziale \param{start} e l'estensione
\param{length}, il valore di \param{start} deve essere allineato,
-mentre \param{length} deve essere un numero positivo.\footnote{la versione di
- Linux consente anche un valore nullo per \param{length}, inoltre se una
- parte dell'intervallo non è mappato in memoria l'indicazione viene comunque
- applicata alle restanti parti, anche se la funzione ritorna un errore di
- \errval{ENOMEM}.} L'indicazione viene espressa dall'argomento \param{advice}
-che deve essere specificato con uno dei valori\footnote{si tenga presente che
- gli ultimi tre valori sono specifici di Linux (introdotti a partire dal
- kernel 2.6.16) e non previsti dallo standard POSIX.1b.} riportati in
-tab.~\ref{tab:madvise_advice_values}.
+mentre \param{length} deve essere un numero positivo; la versione di Linux
+consente anche un valore nullo per \param{length}, inoltre se una parte
+dell'intervallo non è mappato in memoria l'indicazione viene comunque
+applicata alle restanti parti, anche se la funzione ritorna un errore di
+\errval{ENOMEM}.
+
+L'indicazione viene espressa dall'argomento \param{advice} che deve essere
+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.
-\begin{table}[htb]
+\begin{table}[!htb]
\centering
\footnotesize
\begin{tabular}[c]{|l|p{10 cm}|}
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
+ \const{MADV\_DONTNEED}& non ci si aspetta nessun accesso nell'immediato
+ futuro, pertanto le pagine possono essere
+ liberate dal kernel non appena necessario; l'area
+ di memoria resterà accessibile, ma un accesso
+ richiederà che i dati vengano ricaricati dal file
+ a cui la mappatura fa riferimento.\\
\const{MADV\_NORMAL} & nessuna indicazione specifica, questo è il valore
di default usato quando non si è chiamato
\func{madvise}.\\
\const{MADV\_RANDOM} & ci si aspetta un accesso casuale all'area
indicata, pertanto l'applicazione di una lettura
anticipata con il meccanismo del
- \itindex{read-ahead} \textit{read-ahead} (vedi
+ \textit{read-ahead} (vedi
sez.~\ref{sec:file_fadvise}) è di
scarsa utilità e verrà disabilitata.\\
\const{MADV\_SEQUENTIAL}& ci si aspetta un accesso sequenziale al file,
\const{MADV\_WILLNEED}& ci si aspetta un accesso nell'immediato futuro,
pertanto l'applicazione del \textit{read-ahead}
deve essere incentivata.\\
- \const{MADV\_DONTNEED}& non ci si aspetta nessun accesso nell'immediato
- futuro, pertanto le pagine possono essere
- liberate dal kernel non appena necessario; l'area
- di memoria resterà accessibile, ma un accesso
- richiederà che i dati vengano ricaricati dal file
- a cui la mappatura fa riferimento.\\
\hline
- \const{MADV\_REMOVE} & libera un intervallo di pagine di memoria ed il
- relativo supporto sottostante; è supportato
- soltanto sui filesystem in RAM \textit{tmpfs} e
- \textit{shmfs}.\footnotemark\\
+ \const{MADV\_DONTDUMP}& esclude da un \textit{core dump} (vedi
+ sez.~\ref{sec:sig_standard}) le pagine
+ specificate, viene usato per evitare di scrivere
+ su disco dati relativi a zone di memoria che si sa
+ non essere utili in un \textit{core dump}.\\
+ \const{MADV\_DODUMP} & rimuove l'effetto della precedente
+ \const{MADV\_DONTDUMP} (dal kernel 3.4).\\
\const{MADV\_DONTFORK}& impedisce che l'intervallo specificato venga
ereditato dal processo figlio dopo una
\func{fork}; questo consente di evitare che il
- meccanismo del \itindex{copy~on~write}
- \textit{copy on write} effettui la rilocazione
- delle pagine quando il padre scrive sull'area
- di memoria dopo la \func{fork}, cosa che può
- causare problemi per l'hardware che esegue
- operazioni in DMA su quelle pagine.\\
+ meccanismo del \textit{copy on write} effettui la
+ rilocazione delle pagine quando il padre scrive
+ sull'area di memoria dopo la \func{fork}, cosa che
+ può causare problemi per l'hardware che esegue
+ operazioni in DMA su quelle pagine (dal kernel
+ 2.6.16).\\
\const{MADV\_DOFORK} & rimuove l'effetto della precedente
- \const{MADV\_DONTFORK}.\\
- \const{MADV\_MERGEABLE}& marca la pagina come accorpabile (indicazione
+ \const{MADV\_DONTFORK} (dal kernel 2.6.16).\\
+ \const{MADV\_HUGEPAGE}& abilita il meccanismo delle \textit{Transparent
+ Huge Page} (vedi sez.~\ref{sec:huge_pages})
+ sulla regione indicata; se questa è allineata
+ alle relative dimensioni il kernel alloca
+ direttamente delle \textit{huge page}; è
+ utilizzabile solo con mappature anomime private
+ (dal kernel 2.6.38).\\
+ \const{MADV\_NOHUGEPAGE}& impedisce che la regione indicata venga
+ collassata in eventuali \textit{huge page} (dal
+ kernel 2.6.38).\\
+ \const{MADV\_HWPOISON} &opzione ad uso di debug per verificare codice
+ che debba gestire errori nella gestione della
+ memoria; richiede una apposita opzione di
+ compilazione del kernel, privilegi amministrativi
+ (la capacità \const{CAP\_SYS\_ADMIN}) e provoca
+ l'emissione di un segnale di \const{SIGBUS} dal
+ programma chiamante e rimozione della mappatura
+ (dal kernel 2.6.32).\\
+ \const{MADV\_SOFT\_OFFLINE}&opzione utilizzata per il debug del
+ codice di verifica degli errori di gestione
+ memoria, richiede una apposita opzione di
+ compilazione (dal kernel 2.6.33).\\
+ \const{MADV\_MERGEABLE}& marca la pagina come accorpabile, indicazione
principalmente ad uso dei sistemi di
- virtualizzazione).\footnotemark\\
- \hline
+ virtualizzazione\footnotemark (dal kernel 2.6.32).\\
+ \const{MADV\_REMOVE} & libera un intervallo di pagine di memoria ed il
+ relativo supporto sottostante; è supportato
+ soltanto sui filesystem in RAM \textit{tmpfs} e
+ \textit{shmfs} se usato su altri tipi di
+ filesystem causa un errore di \errcode{ENOSYS}
+ (dal kernel 2.6.16).\\
+ \const{MADV\_UNMERGEABLE}& rimuove l'effetto della precedente
+ \const{MADV\_MERGEABLE} (dal kernel 2.6.32). \\
+ \hline
\end{tabular}
\caption{Valori dell'argomento \param{advice} di \func{madvise}.}
\label{tab:madvise_advice_values}
\end{table}
-\footnotetext{se usato su altri tipi di filesystem causa un errore di
- \errcode{ENOSYS}.}
-
\footnotetext{a partire dal kernel 2.6.32 è stato introdotto un meccanismo che
identifica pagine di memoria identiche e le accorpa in una unica pagina
(soggetta al \textit{copy-on-write} per successive modifiche); per evitare
la loro occupazione di memoria, ma il meccanismo può essere usato anche in
altre applicazioni in cui sian presenti numerosi processi che usano gli
stessi dati; per maggiori dettagli si veda
- \href{http://kernelnewbies.org/Linux_2_6_32\#head-d3f32e41df508090810388a57efce73f52660ccb}{\texttt{http://kernelnewbies.org/Linux\_2\_6\_32}}.}
+ \href{http://kernelnewbies.org/Linux_2_6_32\#head-d3f32e41df508090810388a57efce73f52660ccb}{\texttt{http://kernelnewbies.org/Linux\_2\_6\_32}}
+ e la documentazione nei sorgenti del kernel
+ (\texttt{Documentation/vm/ksm.txt}).}
-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. A differenza da quanto specificato
-nello standard POSIX.1b, per il quale l'uso di \func{madvise} è a scopo
-puramente indicativo, Linux considera queste richieste come imperative, per
-cui ritorna un errore qualora non possa soddisfarle.\footnote{questo
- comportamento differisce da quanto specificato nello standard.}
-\itindend{memory~mapping}
+A differenza da quanto specificato nello standard POSIX.1b, per il quale l'uso
+di \func{madvise} è a scopo puramente indicativo, Linux considera queste
+richieste come imperative, per cui ritorna un errore qualora non possa
+soddisfarle; questo comportamento differisce da quanto specificato nello
+standard.
+
+Nello standard POSIX.1-2001 è prevista una ulteriore funzione
+\funcd{posix\_madvise} che su Linux viene reimplementata utilizzando
+\func{madvise}; il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int posix\_madvise(void *start, size\_t lenght, int advice)}
+\fdesc{Fornisce indicazioni sull'uso previsto di un segmento di memoria.}
+}
+
+{La funzione ritorna $0$ in caso di successo ed un valore positivo per un
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] \param{start} non è allineato alla dimensione di
+ una pagina, \param{length} ha un valore negativo, o \param{advice} non è
+ un valore valido.
+ \item[\errcode{ENOMEM}] gli indirizzi specificati non sono nello spazio di
+ indirizzi del processo.
+ \end{errlist}
+}
+\end{funcproto}
+
+Gli argomenti \param{addr} e \param{len} hanno lo stesso significato degli
+analoghi di \func{madvise}, mentre \param{advice} può assumere solo i valori
+indicati in tab.~\ref{tab:posix_madvise_advice_values}, che riflettono gli
+analoghi di \func{madvise}.
+
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{POSIX\_MADV\_DONTNEED}& analogo a \const{MADV\_DONTNEED}.\\
+ \const{POSIX\_MADV\_NORMAL} & identico a \const{MADV\_NORMAL}.\\
+ \const{POSIX\_MADV\_RANDOM} & identico a \const{MADV\_RANDOM}.\\
+ \const{POSIX\_MADV\_SEQUENTIAL}& identico a \const{MADV\_SEQUENTIAL}.\\
+ \const{POSIX\_MADV\_WILLNEED}& identico a \const{MADV\_WILLNEED}.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{advice} di \func{posix\_madvise}.}
+ \label{tab:posix_madvise_advice_values}
+\end{table}
+
+A differenza di quanto indicato dallo standard su Linux un valore nullo
+di \param{len} è consentito. Inoltre a partire dalle \acr{glibc} 2.6
+\const{POSIX\_MADV\_DONTNEED} viene ignorato, in quanto l'uso del
+corrispondente \const{MADV\_DONTNEED} di \func{madvise} ha, per la semantica
+imperativa, l'effetto immediato di far liberare le pagine da parte del kernel,
+che viene considerato distruttivo.
+
\subsection{I/O vettorizzato: \func{readv} e \func{writev}}
% nel kernel 3.15 (sul secondo vedi http://lwn.net/Articles/589260/), vedi
% anche http://lwn.net/Articles/629965/
+% TODO aggiungere FALLOC_FL_INSERT vedi http://lwn.net/Articles/629965/
+
+
% TODO non so dove trattarli, ma dal 2.6.39 ci sono i file handle, vedi
% http://lwn.net/Articles/432757/
% LocalWords: sigwaitinfo FifoReporter Windows ptr sigqueue named timerfd TFD
% LocalWords: clockid CLOCK MONOTONIC REALTIME itimerspec interval Resource
% LocalWords: ABSTIME gettime temporarily unavailable SIGINT SIGQUIT SIGTERM
+% LocalWords: sigfd fifofd break siginf names starting echo Message from Got
+% LocalWords: message kill received means exit
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "gapil"
%%% End:
-% LocalWords: sigfd fifofd break siginf names starting echo Message from Got
-% LocalWords: message kill received means exit