\errcode{EINVAL} siano rilevati immediatamente al momento della chiamata,
potrebbero anche emergere nelle fasi successive delle operazioni. Lettura e
scrittura avvengono alla posizione indicata da \var{aio\_offset}, a meno che
-il file non sia stato aperto in \textit{append mode} (vedi
-sez.~\ref{sec:file_open}), nel qual caso le scritture vengono effettuate
+il file non sia stato aperto in \itindex{append~mode} \textit{append mode}
+(vedi sez.~\ref{sec:file_open}), nel qual caso le scritture vengono effettuate
comunque alla fine de file, nell'ordine delle chiamate a \func{aio\_write}.
Si tenga inoltre presente che deallocare la memoria indirizzata da
\label{sec:file_locking}
\index{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
diversi. In quell'occasione si è visto come, con l'eccezione dei file aperti
-in \textit{append mode}, quando più processi scrivono contemporaneamente sullo
-stesso file non è possibile determinare la sequenza in cui essi opereranno.
-
-Questo causa la possibilità di una \textit{race condition}
-\itindex{race~condition}; in generale le situazioni più comuni sono due:
-l'interazione fra un processo che scrive e altri che leggono, in cui questi
-ultimi possono leggere informazioni scritte solo in maniera parziale o
-incompleta; o quella in cui diversi processi scrivono, mescolando in maniera
-imprevedibile il loro output sul file.
+in \itindex{append~mode} \textit{append mode}, quando più processi scrivono
+contemporaneamente sullo stesso file non è possibile determinare la sequenza
+in cui essi opereranno.
+
+Questo causa la possibilità di una \itindex{race~condition} \textit{race
+ condition}; in generale le situazioni più comuni sono due: l'interazione fra
+un processo che scrive e altri che leggono, in cui questi ultimi possono
+leggere informazioni scritte solo in maniera parziale o incompleta; o quella
+in cui diversi processi scrivono, mescolando in maniera imprevedibile il loro
+output sul file.
In tutti questi casi il \textit{file locking} è la tecnica che permette di
evitare le \textit{race condition}\itindex{race~condition}, attraverso una
\hline
\hline
\texttt{r} & Il file viene aperto, l'accesso viene posto in sola
- lettura, lo stream è posizionato all'inizio del file.\\
- \texttt{r+} & Il file viene aperto, l'accesso viene posto in lettura e
- scrittura, lo stream è posizionato all'inizio del file. \\
+ lettura, lo stream è posizionato all'inizio del file.\\
+ \texttt{r+}& Il file viene aperto, l'accesso viene posto in lettura e
+ scrittura, lo stream è posizionato all'inizio del file. \\
% \hline
\texttt{w} & Il file viene aperto e troncato a lunghezza nulla (o
- creato se non esiste), l'accesso viene posto in sola scrittura, lo
- stream è posizionato all'inizio del file.\\
- \texttt{w+} & Il file viene aperto e troncato a lunghezza nulla (o
- creato se non esiste), l'accesso viene posto in scrittura e lettura,
- lo stream è posizionato all'inizio del file.\\
+ creato se non esiste), l'accesso viene posto in sola
+ scrittura, lo stream è posizionato all'inizio del file.\\
+ \texttt{w+}& Il file viene aperto e troncato a lunghezza nulla (o
+ creato se non esiste), l'accesso viene posto in scrittura e
+ lettura, lo stream è posizionato all'inizio del file.\\
% \hline
\texttt{a} & Il file viene aperto (o creato se non esiste) in
- \textit{append mode}, l'accesso viene posto in sola scrittura. \\
- \texttt{a+} & Il file viene aperto (o creato se non esiste) in
- \textit{append mode}, l'accesso viene posto in lettura e scrittura. \\
+ \itindex{append~mode} \textit{append mode}, l'accesso viene
+ posto in sola scrittura.\\
+ \texttt{a+}& Il file viene aperto (o creato se non esiste) in
+ \itindex{append~mode} \textit{append mode}, l'accesso viene
+ posto in lettura e scrittura.\\
\hline
\texttt{b} & specifica che il file è binario, non ha alcun effetto. \\
\texttt{x} & l'apertura fallisce se il file esiste già. \\
a 31 bit. \\
\hline
\hline % modalità di operazione coi file
- \const{O\_APPEND} & Il file viene aperto in append mode. Prima di ciascuna
+ \const{O\_APPEND} & Il file viene aperto in \itindex{append~mode}
+ \textit{append mode}. Prima di ciascuna
scrittura la posizione corrente viene sempre impostata
alla fine del file. Con NFS si può avere una
corruzione del file se più di un processo scrive allo
\label{tab:file_open_flags}
\end{table}
-\footnotetext[4]{il problema è che NFS non supporta la scrittura in append, ed
- il kernel deve simularla, ma questo comporta la possibilità di una race
- condition, vedi sez.~\ref{sec:file_atomic}.}
+\footnotetext[4]{il problema è che NFS non supporta la scrittura in
+ \itindex{append~mode} \textit{append}, ed il kernel deve simularla, ma
+ questo comporta la possibilità di una \itindex{race~condition} \textit{race
+ condition}, vedi sez.~\ref{sec:file_atomic}.}
\footnotetext[5]{l'opzione origina da SVr4, dove però causava il ritorno da
una \func{read} con un valore nullo e non con un errore, questo introduce
lettura e scrittura avvengono a partire da questa posizione che viene
automaticamente spostata in avanti del numero di byte letti o scritti.
-In genere (a meno di non avere richiesto la modalità \const{O\_APPEND}) questa
-posizione viene impostata a zero all'apertura del file. È possibile impostarla
-ad un valore qualsiasi con la funzione \funcd{lseek}, il cui prototipo è:
+In genere (a meno di non avere richiesto la modalità \itindex{append~mode}
+\const{O\_APPEND}) questa posizione viene impostata a zero all'apertura del
+file. È possibile impostarla ad un valore qualsiasi con la funzione
+\funcd{lseek}, il cui prototipo è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{unistd.h}
Come nel caso di \func{read} la funzione tenta di scrivere \param{count} byte
a partire dalla posizione corrente nel file e sposta automaticamente la
posizione in avanti del numero di byte scritti. Se il file è aperto in
-modalità \const{O\_APPEND} i dati vengono sempre scritti alla fine del file.
-Lo standard POSIX richiede che i dati scritti siano immediatamente disponibili
-ad una \func{read} chiamata dopo che la \func{write} che li ha scritti è
-ritornata; ma dati i meccanismi di caching non è detto che tutti i filesystem
-supportino questa capacità.
+modalità \itindex{append~mode} \const{O\_APPEND} i dati vengono sempre scritti
+alla fine del file. Lo standard POSIX richiede che i dati scritti siano
+immediatamente disponibili ad una \func{read} chiamata dopo che la
+\func{write} che li ha scritti è ritornata; ma dati i meccanismi di caching
+non è detto che tutti i filesystem supportino questa capacità.
Se \param{count} è zero la funzione restituisce zero senza fare nient'altro.
Per i file ordinari il numero di byte scritti è sempre uguale a quello
scrittura eccede la dimensione corrente del file questo verrà esteso
automaticamente con l'aggiornamento del campo \var{i\_size}
nell'inode\index{inode}.
-\item se un file è in modalità \const{O\_APPEND} tutte le volte che viene
- effettuata una scrittura la posizione corrente viene prima impostata alla
- dimensione corrente del file letta dall'inode\index{inode}. Dopo la
- scrittura il file viene automaticamente esteso.
+\item se un file è in modalità \itindex{append~mode} \const{O\_APPEND} tutte
+ le volte che viene effettuata una scrittura la posizione corrente viene
+ prima impostata alla dimensione corrente del file letta
+ dall'inode\index{inode}. Dopo la scrittura il file viene automaticamente
+ esteso.
\item l'effetto di \func{lseek} è solo quello di cambiare il campo
\var{f\_pos} nella struttura \struct{file} della \textit{file table}, non
c'è nessuna operazione sul file su disco. Quando la si usa per porsi alla
Il problema è che usare due system call in successione non è un'operazione
atomica; il problema è stato risolto introducendo la modalità
-\const{O\_APPEND}. In questo caso infatti, come abbiamo descritto in
-precedenza, è il kernel che aggiorna automaticamente la posizione alla fine
-del file prima di effettuare la scrittura, e poi estende il file. Tutto questo
-avviene all'interno di una singola system call (la \func{write}) che non
-essendo interrompibile da un altro processo costituisce un'operazione atomica.
+\itindex{append~mode} \const{O\_APPEND}. In questo caso infatti, come abbiamo
+descritto in precedenza, è il kernel che aggiorna automaticamente la posizione
+alla fine del file prima di effettuare la scrittura, e poi estende il file.
+Tutto questo avviene all'interno di una singola system call (la \func{write})
+che non essendo interrompibile da un altro processo costituisce un'operazione
+atomica.
Un altro caso tipico in cui è necessaria l'atomicità è quello in cui si vuole
creare un \textsl{file di lock}\index{file!di lock}, bloccandosi se il file
\var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
il creatore del segmento, oppure l'amministratore. Compiuta l'operazione
aggiorna anche il valore del campo \var{shm\_ctime}.
-\item[\const{SHM\_LOCK}] Abilita il \textit{memory locking}
- \itindex{memory~locking}\footnote{impedisce cioè che la memoria usata per il
- segmento venga salvata su disco dal meccanismo della memoria
- virtuale\index{memoria~virtuale}; si ricordi quanto trattato in
+\item[\const{SHM\_LOCK}] Abilita il \itindex{memory~locking} \textit{memory
+ locking}\footnote{impedisce cioè che la memoria usata per il segmento
+ venga salvata su disco dal meccanismo della \index{memoria~virtuale}
+ memoria virtuale; si ricordi quanto trattato in
sez.~\ref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo
l'amministratore può utilizzare questo comando.
\item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking}
i primi tre comandi sono gli stessi già visti anche per le code di messaggi e
gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche
previste da Linux, che permettono di abilitare e disabilitare il meccanismo
-della memoria virtuale\index{memoria~virtuale} per il segmento.
+della memoria virtuale \index{memoria~virtuale} per il segmento.
L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT}
e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura
chiamante ha nel suo insieme di capacità
permesse) da qualunque processo.\\
\const{CAP\_LINUX\_IMMUTABLE}& la capacità di impostare gli attributi
- \textit{immutable} e \textit{append only} per i
- file su un filesystem che supporta questi
+ \textit{immutable} e \itindex{append~mode}
+ \textit{append only} per i file su un
+ filesystem che supporta questi
attributi estesi.\\
\const{CAP\_NET\_BIND\_SERVICE}& la capacità di porre in ascolto server
su porte riservate (vedi
\textbf{Parametro} & \textbf{Valore}&\textbf{Significato}\\
\hline
\hline
- \const{MS\_RDONLY} & 1 & monta in sola lettura\\
+ \const{MS\_RDONLY} & 1 & monta in sola lettura.\\
\const{MS\_NOSUID} & 2 & ignora i bit \itindex{suid~bit} \acr{suid} e
- \itindex{sgid~bit}\acr{sgid}\\
- \const{MS\_NODEV} & 4 & impedisce l'accesso ai file di dispositivo\\
- \const{MS\_NOEXEC} & 8 & impedisce di eseguire programmi \\
- \const{MS\_SYNCHRONOUS}& 16 & abilita la scrittura sincrona \\
- \const{MS\_REMOUNT} & 32 & rimonta il filesystem cambiando i flag\\
+ \itindex{sgid~bit}\acr{sgid}.\\
+ \const{MS\_NODEV} & 4 & impedisce l'accesso ai file di dispositivo.\\
+ \const{MS\_NOEXEC} & 8 & impedisce di eseguire programmi.\\
+ \const{MS\_SYNCHRONOUS}& 16 & abilita la scrittura sincrona.\\
+ \const{MS\_REMOUNT} & 32 & rimonta il filesystem cambiando i flag.\\
\const{MS\_MANDLOCK} & 64 & consente il \textit{mandatory locking} (vedi
- sez.~\ref{sec:file_mand_locking})\\
- \const{S\_WRITE} & 128 & scrive normalmente \\
- \const{S\_APPEND} & 256 & consente la scrittura solo in \textit{append
- mode} (vedi sez.~\ref{sec:file_sharing})\\
- \const{S\_IMMUTABLE} & 512 & impedisce che si possano modificare i file \\
+ sez.~\ref{sec:file_mand_locking}).\\
+ \const{S\_WRITE} & 128 & scrive normalmente.\\
+ \const{S\_APPEND} & 256 & consente la scrittura solo in
+ \itindex{append~mode} \textit{append mode}
+ (vedi sez.~\ref{sec:file_sharing}).\\
+ \const{S\_IMMUTABLE} & 512 & impedisce che si possano modificare i file.\\
\const{MS\_NOATIME} &1024 & non aggiorna gli \textit{access time} (vedi
- sez.~\ref{sec:file_file_times})\\
+ sez.~\ref{sec:file_file_times}).\\
\const{MS\_NODIRATIME}&2048 & non aggiorna gli \textit{access time} delle
- directory\\
- \const{MS\_BIND} &4096 & monta il filesystem altrove\\
- \const{MS\_MOVE} &8192 & sposta atomicamente il punto di montaggio \\
+ directory.\\
+ \const{MS\_BIND} &4096 & monta il filesystem altrove.\\
+ \const{MS\_MOVE} &8192 & sposta atomicamente il punto di montaggio.\\
\hline
\end{tabular}
\caption{Tabella dei codici dei flag di montaggio di un filesystem.}
Quando si attiva la contabilità, il file che si indica deve esistere; esso
verrà aperto in sola scrittura;\footnote{si applicano al pathname indicato da
\param{filename} tutte le restrizioni viste in cap.~\ref{cha:file_intro}.}
-le informazioni verranno registrate in \textit{append} in coda al file tutte
-le volte che un processo termina. Le informazioni vengono salvate in formato
-binario, e corrispondono al contenuto della apposita struttura dati definita
-all'interno del kernel.
+le informazioni verranno registrate in \itindex{append~mode} \textit{append}
+in coda al file tutte le volte che un processo termina. Le informazioni
+vengono salvate in formato binario, e corrispondono al contenuto della
+apposita struttura dati definita all'interno del kernel.
Il funzionamento di \func{acct} viene inoltre modificato da uno specifico
parametro di sistema, modificabile attraverso \file{/proc/sys/kernel/acct} (o
\textit{time zone} corrente; \func{ctime} è banalmente definita in termini di
\func{asctime} come \code{asctime(localtime(t)}. Dato che l'uso di una stringa
statica rende le funzioni non rientranti POSIX.1c e SUSv2 prevedono due
-sostitute rientranti, il cui nome è al solito ottenuto appendendo un
+sostitute rientranti, il cui nome è al solito ottenuto aggiungendo un
\code{\_r}, che prendono un secondo argomento \code{char *buf}, in cui
l'utente deve specificare il buffer su cui la stringa deve essere copiata
(deve essere di almeno 26 caratteri).
(quello del capo che ha eseguito la chiusura attiva) venga perso, chi esegue
la chiusura passiva non ricevendo risposta rimanderà un ulteriore FIN, per
questo motivo chi esegue la chiusura attiva deve mantenere lo stato della
-connessione per essere in grado di rinviare l'ACK e chiuderla correttamente.
+connessione per essere in grado di reinviare l'ACK e chiuderla correttamente.
Se non fosse così la risposta sarebbe un RST (un altro tipo si segmento) che
verrebbe interpretato come un errore.
handshake} non si è ancora concluso. Questi socket sono tutti nello stato
\texttt{SYN\_RECV}.
\item La coda delle connessioni complete (\textit{complete connection queue}
- che contiene un ingresso per ciascun socket per il quale il \textit{three
- way handshake} è stato completato ma ancora \func{accept} non è ritornata.
- Questi socket sono tutti nello stato \texttt{ESTABLISHED}.
+ che contiene un ingresso per ciascun socket per il quale il
+ \itindex{three~way~handshake} \textit{three way handshake} è stato
+ completato ma ancora \func{accept} non è ritornata. Questi socket sono
+ tutti nello stato \texttt{ESTABLISHED}.
\end{enumerate}
Lo schema di funzionamento è descritto in fig.~\ref{fig:TCP_listen_backlog}:
delle connessioni incomplete, e poi risponde con il SYN$+$ACK. La voce resterà
nella coda delle connessioni incomplete fino al ricevimento dell'ACK dal
client o fino ad un timeout. Nel caso di completamento del
-\itindex{three~way~handshake}\textit{three way handshake} la voce viene
+\itindex{three~way~handshake} \textit{three way handshake} la voce viene
spostata nella coda delle connessioni complete. Quando il processo chiama la
funzione \func{accept} (vedi sez.~\ref{sec:TCP_func_accept}) la prima voce
nella coda delle connessioni complete è passata al programma, o, se la coda è
server è occupato fra chiamate successive alla \func{accept} (per cui la coda
più occupata sarebbe quella delle connessioni completate), ma piuttosto quello
di gestire la presenza di un gran numero di SYN in attesa di concludere il
-\textit{three way handshake}\itindex{three~way~handshake}.
+\itindex{three~way~handshake} \textit{three way handshake}.
Infine va messo in evidenza che, nel caso di socket TCP, quando un SYN arriva
con tutte le code piene, il pacchetto deve essere ignorato. Questo perché la
\textit{three way handshake} la connessione è stabilita; la \func{connect}
ritornerà nel client\footnote{si noti che è sempre la \func{connect} del
client a ritornare per prima, in quanto questo avviene alla ricezione del
- secondo segmento (l'ACK del server) del \textit{three way handshake}, la
- \func{accept} del server ritorna solo dopo un altro mezzo RTT quando il
- terzo segmento (l'ACK del client) viene ricevuto.} e la \func{accept} nel
-server, ed usando di nuovo \cmd{netstat} otterremmo che:
+ secondo segmento (l'ACK del server) del \itindex{three~way~handshake}
+ \textit{three way handshake}, la \func{accept} del server ritorna solo dopo
+ un altro mezzo RTT quando il terzo segmento (l'ACK del client) viene
+ ricevuto.} e la \func{accept} nel server, ed usando di nuovo \cmd{netstat}
+otterremmo che:
\begin{verbatim}
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
con dei server molto occupati. In tal caso, con una struttura del server
simile a quella del nostro esempio, in cui la gestione delle singole
connessioni è demandata a processi figli, può accadere che il \textit{three
- way handshake}\itindex{three~way~handshake} venga completato e la relativa
+ way handshake} \itindex{three~way~handshake} venga completato e la relativa
connessione abortita subito dopo, prima che il padre, per via del carico della
macchina, abbia fatto in tempo ad eseguire la chiamata ad \func{accept}. Di
nuovo si ha una situazione analoga a quella illustrata in
\end{verbatim}
Le prime tre righe vengono prodotte al momento in cui lanciamo il nostro
-client, e corrispondono ai tre pacchetti del
-\itindex{three~way~handshake}\textit{three way handshake}. L'output del
-comando riporta anche i numeri di sequenza iniziali, mentre la lettera
-\texttt{S} indica che per quel pacchetto si aveva il SYN flag attivo. Si noti
-come a partire dal secondo pacchetto sia sempre attivo il campo \texttt{ack},
-seguito dal numero di sequenza per il quale si da il ricevuto; quest'ultimo, a
-partire dal terzo pacchetto, viene espresso in forma relativa per maggiore
-compattezza. Il campo \texttt{win} in ogni riga indica la \textit{advertising
- window} di cui parlavamo in sez.~\ref{sec:TCP_TCP_opt}. Allora si può
-verificare dall'output del comando come venga appunto realizzata la sequenza
-di pacchetti descritta in sez.~\ref{sec:TCP_conn_cre}: prima viene inviato dal
-client un primo pacchetto con il SYN che inizia la connessione, a cui il
-server risponde dando il ricevuto con un secondo pacchetto, che a sua volta
-porta un SYN, cui il client risponde con un il terzo pacchetto di ricevuto.
+client, e corrispondono ai tre pacchetti del \itindex{three~way~handshake}
+\textit{three way handshake}. L'output del comando riporta anche i numeri di
+sequenza iniziali, mentre la lettera \texttt{S} indica che per quel pacchetto
+si aveva il SYN flag attivo. Si noti come a partire dal secondo pacchetto sia
+sempre attivo il campo \texttt{ack}, seguito dal numero di sequenza per il
+quale si da il ricevuto; quest'ultimo, a partire dal terzo pacchetto, viene
+espresso in forma relativa per maggiore compattezza. Il campo \texttt{win} in
+ogni riga indica la \textit{advertising window} di cui parlavamo in
+sez.~\ref{sec:TCP_TCP_opt}. Allora si può verificare dall'output del comando
+come venga appunto realizzata la sequenza di pacchetti descritta in
+sez.~\ref{sec:TCP_conn_cre}: prima viene inviato dal client un primo pacchetto
+con il SYN che inizia la connessione, a cui il server risponde dando il
+ricevuto con un secondo pacchetto, che a sua volta porta un SYN, cui il client
+risponde con un il terzo pacchetto di ricevuto.
Ritorniamo allora alla nostra sessione con il servizio echo: dopo le tre righe
-del \textit{three way handshake}\itindex{three~way~handshake} non avremo nulla
+del \textit{three way handshake} \itindex{three~way~handshake} non avremo nulla
fin tanto che non scriveremo una prima riga sul client; al momento in cui
facciamo questo si genera una sequenza di altri quattro pacchetti. Il primo,
dal client al server, contraddistinto da una lettera \texttt{P} che significa