X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=ade65bcbb9ded2a06945e7553e8111aca86b54e1;hp=29a6eacf974ad6e134850c498cf664822570b53e;hb=4aa6c51696d2b11c572eccd37238db1691785573;hpb=922de35645e21550b70e2e5fe5ced103a0d2e0b4 diff --git a/fileadv.tex b/fileadv.tex index 29a6eac..ade65bc 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1,6 +1,6 @@ %% fileadv.tex %% -%% Copyright (C) 2000-2011 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2012 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", @@ -24,7 +24,7 @@ controllo più dettagliato delle modalità di I/O. \section{Il \textit{file locking}} \label{sec:file_locking} -\index{file!locking|(} +\itindbeg{file~locking} In sez.~\ref{sec:file_sharing} abbiamo preso in esame le modalità in cui un sistema unix-like gestisce la condivisione dei file da parte di processi @@ -385,7 +385,7 @@ riportate in tab.~\ref{tab:file_flock_type}, che permettono di richiedere rispettivamente uno \textit{shared lock}, un \textit{esclusive lock}, e la rimozione di un blocco precedentemente acquisito. Infine il campo \var{l\_pid} viene usato solo in caso di lettura, quando si chiama \func{fcntl} con -\const{F\_GETLK}, e riporta il \acr{pid} del processo che detiene il +\const{F\_GETLK}, e riporta il \ids{PID} del processo che detiene il \textit{file lock}. Oltre a quanto richiesto tramite i campi di \struct{flock}, l'operazione @@ -462,14 +462,14 @@ fig.~\ref{fig:file_posix_lock}; come si vede esso è molto simile all'analogo di fig.~\ref{fig:file_flock_struct}:\footnote{in questo caso nella figura si sono evidenziati solo i campi di \struct{file\_lock} significativi per la semantica POSIX, in particolare adesso ciascuna struttura contiene, oltre al - \acr{pid} del processo in \var{fl\_pid}, la sezione di file che viene + \ids{PID} del processo in \var{fl\_pid}, la sezione di file che viene bloccata grazie ai campi \var{fl\_start} e \var{fl\_end}. La struttura è comunque la stessa, solo che in questo caso nel campo \var{fl\_flags} è impostato il bit \const{FL\_POSIX} ed il campo \var{fl\_file} non viene usato.} il blocco è sempre associato \itindex{inode} all'inode, solo che in questo caso la titolarità non viene identificata con il riferimento ad una voce nella \itindex{file~table} \textit{file table}, ma con il valore del -\acr{pid} del processo. +\ids{PID} del processo. \begin{figure}[!htb] \centering \includegraphics[width=12cm]{img/file_posix_lock} @@ -488,19 +488,19 @@ una già bloccata, in caso affermativo decide in base al tipo di blocco, in caso negativo il nuovo blocco viene comunque acquisito ed aggiunto alla lista. Nel caso di rimozione invece questa viene effettuata controllando che il -\acr{pid} del processo richiedente corrisponda a quello contenuto nel blocco. +\ids{PID} del processo richiedente corrisponda a quello contenuto nel blocco. Questa diversa modalità ha delle conseguenze precise riguardo il comportamento dei \textit{file lock} POSIX. La prima conseguenza è che un \textit{file lock} POSIX non viene mai ereditato attraverso una \func{fork}, dato che il processo -figlio avrà un \acr{pid} diverso, mentre passa indenne attraverso una -\func{exec} in quanto il \acr{pid} resta lo stesso. Questo comporta che, al +figlio avrà un \ids{PID} diverso, mentre passa indenne attraverso una +\func{exec} in quanto il \ids{PID} resta lo stesso. Questo comporta che, al contrario di quanto avveniva con la semantica BSD, quando un processo termina tutti i \textit{file lock} da esso detenuti vengono immediatamente rilasciati. La seconda conseguenza è che qualunque file descriptor che faccia riferimento allo stesso file (che sia stato ottenuto con una \func{dup} o con una \func{open} in questo caso non fa differenza) può essere usato per rimuovere -un blocco, dato che quello che conta è solo il \acr{pid} del processo. Da +un blocco, dato che quello che conta è solo il \ids{PID} del processo. Da questo deriva una ulteriore sottile differenza di comportamento: dato che alla chiusura di un file i blocchi ad esso associati vengono rimossi, nella semantica POSIX basterà chiudere un file descriptor qualunque per cancellare @@ -508,11 +508,11 @@ tutti i blocchi relativi al file cui esso faceva riferimento, anche se questi fossero stati creati usando altri file descriptor che restano aperti. Dato che il controllo sull'accesso ai blocchi viene eseguito sulla base del -\acr{pid} del processo, possiamo anche prendere in considerazione un altro +\ids{PID} del processo, possiamo anche prendere in considerazione un altro degli aspetti meno chiari di questa interfaccia e cioè cosa succede quando si richiedono dei blocchi su regioni che si sovrappongono fra loro all'interno stesso processo. Siccome il controllo, come nel caso della rimozione, si basa -solo sul \acr{pid} del processo che chiama la funzione, queste richieste +solo sul \ids{PID} del processo che chiama la funzione, queste richieste avranno sempre successo. Nel caso della semantica BSD, essendo i lock relativi a tutto un file e non @@ -799,7 +799,7 @@ affatto equivalente a \func{flock}). \subsection{Il \textit{mandatory locking}} \label{sec:file_mand_locking} -\itindbeg{mandatory~locking|(} +\itindbeg{mandatory~locking} Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4, per introdurre un \textit{file locking} che, come dice il nome, fosse @@ -811,7 +811,7 @@ opportune verifiche nei processi, questo verrebbe comunque rispettato. Per poter utilizzare il \textit{mandatory locking} è stato introdotto un utilizzo particolare del bit \itindex{sgid~bit} \acr{sgid}. Se si ricorda quanto esposto in sez.~\ref{sec:file_special_perm}), esso viene di norma -utilizzato per cambiare il group-ID effettivo con cui viene eseguito un +utilizzato per cambiare il \ids{GID} effettivo con cui viene eseguito un programma, ed è pertanto sempre associato alla presenza del permesso di esecuzione per il gruppo. Impostando questo bit su un file senza permesso di esecuzione in un sistema che supporta il \textit{mandatory locking}, fa sì che @@ -835,7 +835,7 @@ bloccare completamente un server NFS richiedendo una lettura su un file su cui è attivo un blocco. Per questo motivo l'abilitazione del \textit{mandatory locking} è di norma disabilitata, e deve essere attivata filesystem per filesystem in fase di montaggio (specificando l'apposita opzione di -\func{mount} riportata in tab.~\ref{tab:sys_mount_flags}, o con l'opzione +\func{mount} riportata in sez.~\ref{sec:sys_file_config}), o con l'opzione \code{-o mand} per il comando omonimo). Si tenga presente inoltre che il \textit{mandatory locking} funziona solo @@ -890,9 +890,9 @@ soltanto quando si chiama \func{mmap} con l'opzione \const{MAP\_SHARED} (nel qual caso la funzione fallisce con il solito \errcode{EAGAIN}) che comporta la possibilità di modificare il file. -\index{file!locking|)} +\itindend{file~locking} -\itindend{mandatory~locking|(} +\itindend{mandatory~locking} \section{L'\textit{I/O multiplexing}} @@ -1521,7 +1521,7 @@ sono: nel sistema. \item[\errcode{EMFILE}] si è raggiunto il limite sul numero massimo di istanze di \textit{epoll} per utente stabilito da - \procfile{/proc/sys/fs/epoll/max\_user\_instances}. + \sysctlfile{fs/epoll/max\_user\_instances}. \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare l'istanza. \end{errlist} @@ -1576,7 +1576,7 @@ controllare, per questo si deve usare la seconda funzione dell'interfaccia, \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}. \item[\errcode{ENOSPC}] si è raggiunto il limite massimo di registrazioni per utente di file descriptor da osservare imposto da - \procfile{/proc/sys/fs/epoll/max\_user\_watches}. + \sysctlfile{fs/epoll/max\_user\_watches}. \end{errlist} } \end{prototype} @@ -2560,8 +2560,8 @@ diventati attivi. L'unico modo per essere sicuri che questo non avvenga è di impostare la lunghezza della coda dei segnali real-time ad una dimensione identica al valore massimo del numero di file descriptor utilizzabili.\footnote{vale a dire impostare il contenuto di - \procfile{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di - \procfile{/proc/sys/fs/file-max}.} + \sysctlfile{kernel/rtsig-max} allo stesso valore del contenuto di + \sysctlfile{fs/file-max}.} % TODO fare esempio che usa O_ASYNC @@ -2613,7 +2613,7 @@ partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}. -\index{file!lease|(} +\itindbeg{file~lease} La prima di queste funzionalità è quella del cosiddetto \textit{file lease}; questo è un meccanismo che consente ad un processo, detto \textit{lease @@ -2677,7 +2677,7 @@ Si tenga presente che un processo può mantenere solo un tipo di \textit{lease} su un file, e che un \textit{lease} può essere ottenuto solo su file di dati (pipe e dispositivi sono quindi esclusi). Inoltre un processo non privilegiato può ottenere un \textit{lease} soltanto per un file appartenente ad un -\acr{uid} corrispondente a quello del processo. Soltanto un processo con +\ids{UID} corrispondente a quello del processo. Soltanto un processo con privilegi di amministratore (cioè con la \itindex{capabilities} capability \const{CAP\_LEASE}, vedi sez.~\ref{sec:proc_capabilities}) può acquisire \textit{lease} su qualunque file. @@ -2711,7 +2711,7 @@ operazione di lettura, declassando il \textit{lease} a lettura con Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro il numero di secondi specificato dal parametro di sistema mantenuto in -\procfile{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o +\sysctlfile{fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per evitare che un processo blocchi indefinitamente l'accesso ad un file acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato @@ -2745,7 +2745,7 @@ come in precedenza, si potrà ottenere nel gestore del segnale il file descriptor che è stato modificato tramite il contenuto della struttura \struct{siginfo\_t}. -\index{file!lease|)} +\itindend{file~lease} \begin{table}[htb] \centering @@ -2857,7 +2857,7 @@ effettuate le operazioni di notifica;\footnote{per evitare abusi delle risorse di sistema è previsto che un utente possa utilizzare un numero limitato di istanze di \textit{inotify}; il valore di default del limite è di 128, ma questo valore può essere cambiato con \func{sysctl} o usando il file - \procfile{/proc/sys/fs/inotify/max\_user\_instances}.} si tratta di un file + \sysctlfile{fs/inotify/max\_user\_instances}.} si tratta di un file descriptor speciale che non è associato a nessun file su disco, e che viene utilizzato solo per notificare gli eventi che sono stati posti in osservazione. Dato che questo file descriptor non è associato a nessun file o @@ -2918,7 +2918,7 @@ modalità della stessa. L'operazione può essere ripetuta per tutti i file e le directory che si vogliono tenere sotto osservazione,\footnote{anche in questo caso c'è un limite massimo che di default è pari a 8192, ed anche questo valore può essere cambiato con \func{sysctl} o usando il file - \procfile{/proc/sys/fs/inotify/max\_user\_watches}.} e si utilizzerà sempre + \sysctlfile{fs/inotify/max\_user\_watches}.} e si utilizzerà sempre un solo file descriptor. Il tipo di evento che si vuole osservare deve essere specificato @@ -3152,7 +3152,7 @@ aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di \end{table} \footnotetext{la coda di notifica ha una dimensione massima specificata dal - parametro di sistema \procfile{/proc/sys/fs/inotify/max\_queued\_events} che + parametro di sistema \sysctlfile{fs/inotify/max\_queued\_events} che indica il numero massimo di eventi che possono essere mantenuti sulla stessa; quando detto valore viene ecceduto gli ulteriori eventi vengono scartati, ma viene comunque generato un evento di tipo @@ -4654,8 +4654,7 @@ significativi delle prestazioni rispetto all'uso in sequenza di \func{read} 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} - {\textsf{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}.} + 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 @@ -4694,18 +4693,18 @@ Il concetto che sta dietro a \func{splice} invece è diverso,\footnote{in 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} - {\textsf{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una -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}''. + dallo stesso Linus Torvalds in \url{http://kerneltrap.org/node/6505}.} si +tratta semplicemente di una 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 (vedi fig.~\ref{fig:ipc_pipe_singular}) dove appoggiare i @@ -5090,12 +5089,12 @@ di dati in realtà nella implementazione di queste system call non è affatto detto che i dati vengono effettivamente spostati o copiati, il kernel infatti realizza le \textit{pipe} come un insieme di puntatori\footnote{per essere precisi si tratta di un semplice buffer circolare, un buon articolo sul tema - si trova su \href{http://lwn.net/Articles/118750/} - {\textsf{http://lwn.net/Articles/118750/}}.} alle pagine di memoria interna -che contengono i dati, per questo una volta che i dati sono presenti nella -memoria del kernel tutto quello che viene fatto è creare i suddetti puntatori -ed aumentare il numero di referenze; questo significa che anche con \func{tee} -non viene mai copiato nessun byte, vengono semplicemente copiati i puntatori. + si trova su \url{http://lwn.net/Articles/118750/}.} alle pagine di memoria +interna che contengono i dati, per questo una volta che i dati sono presenti +nella memoria del kernel tutto quello che viene fatto è creare i suddetti +puntatori ed aumentare il numero di referenze; questo significa che anche con +\func{tee} non viene mai copiato nessun byte, vengono semplicemente copiati i +puntatori. % TODO?? dal 2.6.25 splice ha ottenuto il supporto per la ricezione su rete