X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileunix.tex;h=3001194b17762a7e3b4c5d321e6e9e98d873fe28;hp=7ae7ce633e5cd39b040b2c48cbabe2d71147afde;hb=132101028053d47151d1957b925fc5a7631c01e6;hpb=fadbc082a6f07263bc3bdccfbba52d1c9b6d9521 diff --git a/fileunix.tex b/fileunix.tex index 7ae7ce6..3001194 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -297,16 +297,16 @@ cio \footnotetext[3]{Denial of Service, si chiamano così attacchi miranti ad impedire un servizio causando una qualche forma di carico eccessivo per il - sistema, che resta bloccato nelle risposte all'attacco} + sistema, che resta bloccato nelle risposte all'attacco.} \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} + condition, vedi \secref{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 una ambiguità, dato che come vedremo in \secref{sec:file_read} il ritorno di - zero da parte di \func{read} ha il significato di una end-of-file} + zero da parte di \func{read} ha il significato di una end-of-file.} Il nuovo file descriptor non è condiviso con nessun altro processo, (torneremo @@ -465,9 +465,8 @@ Si tenga presente inoltre che usare \macro{SEEK\_END} non assicura affatto che successiva scrittura avvenga alla fine del file, infatti se questo è stato aperto anche da un altro processo che vi ha scritto, la fine del file può essersi spostata, ma noi scriveremo alla posizione settata in precedenza. -Questa è una potenziale sorgente di \textit{race condition}, e quando si vuole -essere sicuri di scrivere alla fine del file questo deve essere posto in -modalità \macro{O\_APPEND}. +(questa è una potenziale sorgente di \textit{race condition}, vedi +\secref{sec:file_atomic}). Non tutti i file supportano la capacità di eseguire una \func{lseek}, in questo caso la funzione ritorna l'errore \macro{EPIPE}. Questo, oltre che per @@ -726,11 +725,43 @@ vengono toccati anche in caso di condivisione della voce della \textit{file Come si è visto in un sistema unix è sempre possibile per più processi accedere in contemporanea allo stesso file, e che le operazioni di lettura e -scrittura saranno fatte in base alla posizione corrente nel file. Ovviamente -senza prevedere opportuni meccanismi di sincronizzazione le operazioni -potranno mescolarsi in maniera imprevedibile. L'unica garanzia è che se si è -in modalità \macro{O\_APPEND} il sistema assicura che si scriva (con il -procedimento appena esposto) sempre alla fine del file. +scrittura possono essere fatte da ogni processo in maniera autonoma in base +ad una posizione corrente nel file che è locale a ciascuno di essi. + +Se dal punto di vista della lettura dei dati questo non comporta nessun +problema, quando si andrà a scrivere le operazioni potranno mescolarsi in +maniera imprevedibile. Il sistema però fornisce in alcuni casi la possibilità +di eseguire alcune operazioni di scrittura in maniera coordinata anche senza +utilizzare meccanismi di sincronizzazione più complessi (come il \textit{file + locking}, che esamineremo in \secref{cha:file_advanced}). + +Un caso tipico di necessità di accesso condiviso in scrittura è quello in cui +vari processi devono scrivere alla fine di un file (ad esempio un file di +log). Come accennato in \secref{sec:file_lseek} settare la posizione alla fine +del file e poi scrivere può condurre ad una \textit{race condition}: infatti +può succedere che un secondo processo scriva alla fine del file fra la +\func{lseek} e la \func{write}; in questo caso, come abbiamo appena visto, il +file sarà esteso, ma il nostro primo processo avrà ancora la posizione +corrente settata con la \func{lseek} che non corrisponde più alla fine del +file, e la successiva \func{write} sovrascriverà i dati del secondo processo. + +Il problema è che usare due system call in successione non è una operazione +atomica; il problema è stato risolto introducendo la modalità +\macro{O\_APPEND}, in questo caso infatti, come abbiamo visto, è 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 una operazione atomica. + +Un altro caso tipico in cui è necessaria l'atomicità è quello in cui si vuole +creare un file di lock, bloccandosi se il file esiste. In questo caso la +sequenza logica porterebbe a verificare prima l'esistenza del file con una +\func{stat} per poi crearlo con una \func{creat}; di nuovo avremmo la +possibilità di una race condition da parte di un altro processo che crea lo +stesso file fra il controllo e la creazione. + +Per questo motivo sono stati introdotti i flag \macro{O\_CREAT} +\macro{O\_EXCL}