%% fileadv.tex
%%
-%% Copyright (C) 2000-2009 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2010 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
\itindend{epoll}
+\subsection{La notifica di eventi tramite file descriptor}
+\label{sec:sig_signalfd_eventfd}
+
+Abbiamo visto in sez.~\ref{sec:file_select} come il meccanismo classico delle
+notifiche di eventi tramite i segnali, presente da sempre nei sistemi
+unix-like, porti a novevoli problemi nell'interazione con le funzioni per
+l'I/O multiplexing, tanto che per evitare possibili \itindex{race~condition}
+\textit{race condition} sono state introtte estensioni dello standard POSIX e
+funzioni apposite come \func{pselect}, \func{ppoll} e \funcd{epoll\_pwait}.
+
+Benché i segnali siano il meccanismo più usato per effettuare notifiche ai
+processi, la loro interfaccia di programmazione, che comporta l'esecuzione di
+una funzione di gestione in maniera asincrona e totalmente scorrelata
+dall'ordinario flusso di esecuzione del processo, si è però dimostrata quasi
+subito assai problematica. Oltre ai limiti relativi ai limiti al cosa si può
+fare all'interno della funzione del gestore di segnali (quelli illustrati in
+sez.~\ref{sec:sig_signal_handler}), c'è il problema più generale consistente
+nel fatto che questa modalità di funzionamento cozza con le altre interfacce
+di programmazione previste dal sistema in cui invece si opera in maniera
+\textsl{sincrona}, e che porta ai problemi relativi alla interruzione delle
+\index{system~call~lente} system call bloccanti.
+
+In questo caso infatti si aspetta che il processo gestisca gli eventi (che
+causano l'uscita dalla \index{system~call~lente} system call bloccante)
+generando le opportune risposte, mentre con l'arrivo di un segnale ci si trova
+alla possibilità di avere interruzioni asincrone in cui possono essere
+eseguite operazioni fuori dal resto dal flusso ordinario del programma e
+quindi la necessità gestire le interruzioni ed evitare possibili
+\itindex{race~condition} \textit{race conditions}.\footnote{in sostanza se non
+ fosse per i segnali non ci sarebbe da doversi preoccupare, fintanto che si
+ effettuano operazioni all'interno dello stesso, della non atomicità (si
+ ricordi quanto detto in sez.~\ref{sec:proc_atom_oper}) delle
+ \index{system~call~lente} system call lente che vengono interrotte e devono
+ essere riavviate.}
+
+Abbiamo visto però in sez.~\ref{sec:sig_real_time} che insieme ai segnali
+\textit{real-time} sono state introdotte delle interfacce di gestione sincrona
+dei segnali con la funzione \func{sigwait} e le sue affini. Queste funzioni
+consentono di gestire i segnali bloccando un processo fino alla avvenuta
+ricezione e disabilitando l'esecuzione asincrona di un gestore. Questo
+consente di risolvere i problemi di atomicità nella gestione degli eventi
+associati ai segnali, avendo tutto il controllo nel flusso principale del
+programma, ottenendo così una gestione simile a quella dell'I/O multiplexing,
+ma non risolve i problemi delle interazioni con quest'ultimo, perché o si
+aspetta la ricezione di un segnale o si aspetta che un file descriptor sia
+accessibile e nessuna delle rispettive funzioni consente di fare
+contemporaneamente entrambe le cose.
+
+Per risolvere questo problema nello sviluppo del kernel si è pensato di
+introdurre un meccanismo alternativo per la notifica dei segnali (ed anche di
+altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per
+cui tutto è un file, consentisse di eseguirne la notifica con l'uso di
+opportuni file descriptor.\footnote{ovviamente si tratta di una funzionalità
+ specifica di Linux, non presente in altri sistemi unix-like, e non prevista
+ da nessuno standard.}
+
+In sostanza, come per \func{sigwait}, si può disabilitare l'esecuzione di un
+gestore di segnali e rilevare l'avvenuta ricezione leggendone la notifica da
+uno speciale file descriptor. Trattandosi in questo caso di un file descriptor
+questo potrà essere tenuto sotto osservazione con le funzioni dell'I/O
+multiplexing come quelli associati a file o socket, per cui alla fine si potrà
+attendere in contemporanea sia il segnale che la disponibilità di accesso a
+questi ultimi.
+
+La funzione che permette di abilitare la ricezione dei segnali con i
+
+
+% TODO trattare qui eventfd signalfd e timerfd introdotte con il 2.6.22
+% timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25
+% vedi: http://lwn.net/Articles/233462/
+% http://lwn.net/Articles/245533/
+% http://lwn.net/Articles/267331/
+
+
+
\section{L'accesso \textsl{asincrono} ai file}
\label{sec:file_asyncronous_access}
\textit{lease breaker} rimaste bloccate proseguono automaticamente.
-\index{file!dnotify|(}
+\itindbeg{dnotify}
Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da
parte di più processi, l'uso dei \textit{file lease} non consente comunque di
nelle precedenti. Se si vuole rimuovere la notifica si deve invece
specificare un valore nullo.
-\index{file!inotify|(}
+\itindbeg{inotify}
Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
usare un file descriptor per ciascuna directory che si vuole tenere sotto
quella di \textit{dnotify} viene considerata una interfaccia di usabilità
problematica.
-\index{file!dnotify|)}
+\itindend{dnotify}
Per risolvere i problemi appena illustrati è stata introdotta una nuova
interfaccia per l'osservazione delle modifiche a file o directory, chiamata
dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono
raggruppati in un solo evento.
-\index{file!inotify|)}
+\itindend{inotify}
% TODO trattare fanotify, vedi http://lwn.net/Articles/339399/ e
-% http://lwn.net/Articles/343346/
+% http://lwn.net/Articles/343346/ (incluso nel 2.6.36)
\subsection{L'interfaccia POSIX per l'I/O asincrono}
operazioni, usando un vettore di \textit{control block}. Tramite questo campo
si specifica quale è la natura di ciascuna di esse.
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includestruct{listati/sigevent.h}
- \end{minipage}
- \normalsize
- \caption{La struttura \structd{sigevent}, usata per specificare le modalità
- di notifica degli eventi relativi alle operazioni di I/O asincrono.}
- \label{fig:file_sigevent}
-\end{figure}
-
Infine il campo \var{aio\_sigevent} è una struttura di tipo \struct{sigevent}
-che serve a specificare il modo in cui si vuole che venga effettuata la
-notifica del completamento delle operazioni richieste. La struttura è
-riportata in fig.~\ref{fig:file_sigevent}; il campo \var{sigev\_notify} è
-quello che indica le modalità della notifica, esso può assumere i tre valori:
-\begin{basedescript}{\desclabelwidth{2.6cm}}
-\item[\const{SIGEV\_NONE}] Non viene inviata nessuna notifica.
-\item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo
- chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di
- questo è stato installato con \const{SA\_SIGINFO} gli verrà restituito il
- valore di \var{sigev\_value} (la cui definizione è in
- fig.~\ref{fig:sig_sigval}) come valore del campo \var{si\_value} di
- \struct{siginfo\_t}.
-\item[\const{SIGEV\_THREAD}] La notifica viene effettuata creando un nuovo
- \itindex{thread} \textit{thread} che esegue la funzione specificata da
- \var{sigev\_notify\_function} con argomento \var{sigev\_value}, e con gli
- attributi specificati da \var{sigev\_notify\_attribute}.
-\end{basedescript}
+(illustrata in in fig.~\ref{fig:struct_sigevent}) che serve a specificare il
+modo in cui si vuole che venga effettuata la notifica del completamento delle
+operazioni richieste; per la trattazione delle modalità di utilizzo della
+stessa si veda quanto già visto in proposito in sez.~\ref{sec:sig_timer_adv}.
Le due funzioni base dell'interfaccia per l'I/O asincrono sono
\funcd{aio\_read} ed \funcd{aio\_write}. Esse permettono di richiedere una
\begin{figure}[htb]
\centering
- \includegraphics[width=14cm]{img/mmap_layout}
+ \includegraphics[width=12cm]{img/mmap_layout}
\caption{Disposizione della memoria di un processo quando si esegue la
mappatura in memoria di un file.}
\label{fig:file_mmap_layout}
precedenti \func{readv} e \func{writev}.
Con l'uso di queste funzioni si possono evitare eventuali
-\itindex{race~condition} \textit{race conditions} quando si deve eseguire la
+\itindex{race~condition} \textit{race condition} quando si deve eseguire la
una operazione di lettura e scrittura vettorizzata a partire da una certa
posizione su un file, mentre al contempo si possono avere in concorrenza
processi che utilizzano lo stesso file descriptor (si ricordi quanto visto in
}
\end{functions}
-La funzione si assicura che venga allocato sufficiente spazio disco perché sia
+La funzione assicura che venga allocato sufficiente spazio disco perché sia
possibile scrivere sul file indicato dall'argomento \param{fd} nella regione
che inizia dalla posizione \param{offset} e si estende per \param{len} byte;
-se questa si estende oltre la fine del file le dimensioni di quest'ultimo
-saranno incrementate di conseguenza. Dopo aver eseguito con successo la
-funzione è garantito che una scrittura nella regione indicata non fallirà per
-mancanza di spazio disco.
-
-Ci si può chiedere a cosa serva una funzione come \func{posix\_fallocate} dato
-che è sempre possibile ottenere l'effetto voluto eseguendo manualmente sul
-file la scrittura\footnote{usando \funcd{pwrite} per evitare spostamenti della
- posizione corrente sul file.} di una serie di zeri per l'estensione di
-spazio necessaria. In realtà questa è la modalità con cui la funzione veniva
-realizzata nella prima versione fornita dalle \acr{glibc}, e si trattava nel
-caso soltanto di una standardizzazione delle modalità di
-
-% TODO controllare la trattazione della nuova funzionalità di preallocazione
-
-% TODO documentare \func{posix\_fadvise}
-% vedi http://insights.oetiker.ch/linux/fadvise.html
-% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html
-
-% TODO documentare \func{fallocate}, introdotta con il 2.6.23
-% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
-% http://kernelnewbies.org/Linux_2_6_23
-% \func{fallocate} con il 2.6.25 supporta pure XFS
-
-Infine a partire dal kernel 2.6.23 è stata introdotta la nuova system call
-\funcd{fallocate}, che consente di realizzare direttamente all'interno del
-kernel le funzionalità di \func{posix\_fallocate}. Trattandosi di una funzione
-di servizio questa non è stata definita come funzione di libreria e pertanto
-può essere invocata indirettamente con l'ausilio di \func{syscall} (vedi
-sez.~\ref{sec:intro_syscall}; il suo prototipo è:
-
+se questa regione si estende oltre la fine del file le dimensioni di
+quest'ultimo saranno incrementate di conseguenza. Dopo aver eseguito con
+successo la funzione è garantito che una successiva scrittura nella regione
+indicata non fallirà per mancanza di spazio disco. La funzione non ha nessun
+effetto né sul contenuto, né sulla posizione corrente del file.
+
+Ci si può chiedere a cosa possa servire una funzione come
+\func{posix\_fallocate} dato che è sempre possibile ottenere l'effetto voluto
+eseguendo esplicitamente sul file la scrittura\footnote{usando \funcd{pwrite}
+ per evitare spostamenti della posizione corrente sul file.} di una serie di
+zeri per l'estensione di spazio necessaria qualora il \itindex{sparse~file}
+file debba essere esteso o abbia dei \index{file!\textit{hole}}
+buchi.\footnote{si ricordi che occorre scrivere per avere l'allocazione e che
+ l'uso di \func{truncate} per estendere un file creerebbe soltanto uno
+ \itindex{sparse~file} \textit{sparse file} (vedi sez.~\ref{sec:file_lseek})
+ senza una effettiva allocazione dello spazio disco.} In realtà questa è la
+modalità con cui la funzione veniva realizzata nella prima versione fornita
+dalle \acr{glibc}, per cui la funzione costituiva in sostanza soltanto una
+standardizzazione delle modalità di esecuzione di questo tipo di allocazioni.
+
+Questo metodo, anche se funzionante, comporta però l'effettiva esecuzione una
+scrittura su tutto lo spazio disco necessario, da fare al momento della
+richiesta di allocazione, pagandone il conseguente prezzo in termini di
+prestazioni; il tutto quando in realtà servirebbe solo poter riservare lo
+spazio per poi andarci a scrivere, una sola volta, quando il contenuto finale
+diventa effettivamente disponibile.
+
+Per poter fare tutto questo è però necessario il supporto da parte del kernel,
+e questo è divenuto disponibile solo a partire dal kernel 2.6.23 in cui è
+stata introdotta la nuova \textit{system call} \func{fallocate},\footnote{non
+ è detto che la funzione sia disponibile per tutti i filesystem, ad esempio
+ per XFS il supporto è stato introdotto solo a partire dal kernel 2.6.25.}
+che consente di realizzare direttamente all'interno del kernel l'allocazione
+dello spazio disco così da poter realizzare una versione di
+\func{posix\_fallocate} con prestazioni molto più elevate.\footnote{nelle
+ \acr{glibc} la nuova \textit{system call} viene sfruttata per la
+ realizzazione di \func{posix\_fallocate} a partire dalla versione 2.10.}
+
+Trattandosi di una funzione di servizio, ed ovviamente disponibile
+esclusivamente su Linux, inizialmente \funcd{fallocate} non era stata definita
+come funzione di libreria,\footnote{pertanto poteva essere invocata soltanto
+ in maniera indiretta con l'ausilio di \func{syscall}, vedi
+ sez.~\ref{sec:intro_syscall}, come \code{long fallocate(int fd, int mode,
+ loff\_t offset, loff\_t len)}.} ma a partire dalle \acr{glibc} 2.10 è
+ stato fornito un supporto esplicito; il suo prototipo è:
\begin{functions}
- \headdecl{linux/falloc.h}
- \funcdecl{long fallocate(int fd, int mode, loff\_t offset, loff\_t len)}
+ \headdecl{linux/fcntl.h}
+
+ \funcdecl{int fallocate(int fd, int mode, off\_t offset, off\_t len)}
Prealloca dello spazio disco per un file.
}
\end{functions}
+La funzione prende gli stessi argomenti di \func{posix\_fallocate} con lo
+stesso significato, a cui si aggiunge l'argomento \param{mode} che indica le
+modalità di allocazione; al momento quest'ultimo può soltanto essere nullo o
+assumere il valore \const{FALLOC\_FL\_KEEP\_SIZE} che richiede che la
+dimensione del file\footnote{quella ottenuta nel campo \var{st\_size} di una
+ struttura \struct{stat} dopo una chiamata a \texttt{fstat}.} non venga
+modificata anche quando la somma di \param{offset} e \param{len} eccede la
+dimensione corrente.
+
+Se \param{mode} è nullo invece la dimensione totale del file in caso di
+estensione dello stesso viene aggiornata, come richiesto per
+\func{posix\_fallocate}, ed invocata in questo modo si può considerare
+\func{fallocate} come l'implementazione ottimale di \func{posix\_fallocate} a
+livello di kernel.
+
+% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
+% http://kernelnewbies.org/Linux_2_6_23
+
+
%\subsection{L'utilizzo delle porte di I/O}
% LocalWords: only ETXTBSY DENYWRITE ENODEV filesystem EPERM EXEC noexec table
% LocalWords: ENFILE lenght segment violation SIGSEGV FIXED msync munmap copy
% LocalWords: DoS Denial Service EXECUTABLE NORESERVE LOCKED swapping stack fs
-% LocalWords: GROWSDOWN ANON GiB POPULATE prefaulting SIGBUS fifo VME fork old
+% LocalWords: GROWSDOWN ANON POPULATE prefaulting SIGBUS fifo VME fork old
% LocalWords: exec atime ctime mtime mprotect addr EACCESS mremap address new
% LocalWords: long MAYMOVE realloc VMA virtual Ingo Molnar remap pages pgoff
% LocalWords: dall' fault cache linker prelink advisory discrectionary lock fl
% LocalWords: nwrite segs patch readahead posix fadvise TC advice FADV NORMAL
% LocalWords: SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG
% LocalWords: POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs
-% LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head
-% LocalWords: MERGEABLE EOVERFLOW conditions prealloca
+% LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS
+% LocalWords: MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat
+% LocalWords: conditions sigwait
%%% Local Variables: