POD2-IT
view release on metacpan or search on metacpan
IT/perlfaq5.pod view on Meta::CPAN
=item 1
Produce un errore fatale se non esiste alcuna delle tre chiamate di sistema
(o loro strette equivalenti).
=item 2
lockf(3) non prevede il locking condiviso e richiede che il filehandle sia
aperto per la scrittura (o per l'append, o per la lettura/scrittura).
=item 3
Alcune versioni di flock() non possono fare il lock di file in rete (ad
esempio su file system NFS) dunque si dovrebbe forzare l'uso di fcntl(2)
quando si fa il build del Perl. Ma persino questo E<egrave> dubbio, nel
migliore dei casi. Vedete la voce flock in L<perlfunc> e il file F<INSTALL>
nella distribuzione sorgente per le informazioni su come fare il build del
Perl per farlo.
Due sematiche di flock potenzialmente non ovvie ma tradizionali, sono il
fatto che esso aspetta indefinitamente fino a che il lock non venga assegnato
e che i suoi lock siano I<soltanto consultivi>. Tali lock discrezionali
sono piE<ugrave> flessibili, ma offrono poche garanzie. Questo significa
che i file su cui E<egrave> stato fatto un lock con flock() possono essere
modificati anche da programmi che non usano flock(). Le automobili che si
fermano con il semaforo rosso vanno d'accordo tra loro ma non con le
automobili che non si fermano con il semaforo rosso. Per i dettagli vedete
perlport, la specifica documentazione del vostro port oppure le vostre
manpage locali, specifiche per il sistema. E<Egrave> meglio che si assuma
un comportamento tradizionale se si stanno scrivendo programmi portabili
(Se non lo si sta facendo, ci si dovrebbe sentire, come sempre, perfettamente
liberi di scriversi le proprie idiosincrasie di sistema (a volte chiamate
"caratteristiche"). L'aderenza alle faccende di portabilitE<agrave> senza
originalitE<agrave> non dovrebbe influenzare la maniera con cui portate a
termine il vostro lavoro).
Per maggiori informazioni sul lock dei file vedete anche
L<perlopentut/"File Locking"> se ce l'avete (nuovo per il 5.6).
=back
=head2 PerchE<eacute> non si puE<ograve> fare solamente open(FH, ">file.lock")?
X<lock, lockfile race condition>
Una parte comune di codice B<DA NON USARE> E<egrave> questa:
sleep(3) while -e "file.lock"; # PER FAVORE NON SI USI
open(LCK, "> file.lock"); # QUESTO CODICE NON CORRETTO
Questa E<egrave> una classica race condition: si impiegano due passi per
fare qualcosa che deve essere fatto in uno. Questo E<egrave> il motivo
per cui l'hardware dei computer fornisce una istruzione atomica di
test-and-set. In teoria, questo "dovrebbe" funzionare:
sysopen(FH, "file.lock", O_WRONLY|O_EXCL|O_CREAT)
or die "non posso aprire file.lock: $!":
eccetto che, deplorevolmente, la creazione di file (e la cancellazione)
non E<egrave> atomica su NFS, dunque questo non funzionerE<agrave> (non
tutte le volte, almeno) in rete. Sono stati suggeriti vari schemi che
coinvolgono link(), ma questi tendono a implicare del busy-wait, anch'esso
poco desiderabile.
=head2 Non riesco ancora ad ottenere il lock. Voglio solo incrementare un numero nel file. Come faccio?
X<contatore> X<file, contatore>
Non vi ha mai detto nessuno che i contatori di accesso sulle pagine web
sono inutili? Non contano gli accessi reali, sono una perdita di tempo e
servono solo ad alimentare la vanitE<agrave> di chi li utilizza. Meglio
prendere un numero casuale. E<Egrave> piE<ugrave> realistico.
Ad ogni modo, questo E<egrave> quello che potete fare se proprio non potete
farne a meno:
use Fcntl qw(:DEFAULT :flock);
sysopen(FH, "numfile", O_RDWR|O_CREAT) or die "impossibile aprire numfile: $!";
flock(FH, LOCK_EX) or die "impossibile eseguire flock su numfile: $!";
$num = <FH> || 0;
seek(FH, 0, 0) or die "impossibile tornare all'inizio di numfile: $!";
truncate(FH, 0) or die "impossibile troncare numfile: $!";
(print FH $num+1, "\n") or die "impossibile scrivere numfile: $!";
close FH or die "impossibile chiudere numfile: $!";
Ecco un contatore di accessi alla pagina decisamente migliore :
$accessi = int( (time() - 850_000_000) / rand(1_000) );
Se il numero di accessi non fa colpo sui vostri amici, potete provare ad
impressionarli con il codice. :-)
=head2 Tutto ciE<ograve> che voglio fare E<egrave> aggiungere un po' di testo alla fine di un file. Devo comunque usare i lock?
X<append> X<file, append>
Se vi trovate su un sistema che implementa correttamente flock() ed
utilizzate il codice di esempio per aggiungere dati ad un file da
"perldoc -f flock", andrE<agrave> tutto bene anche se il sistema operativo
su cui siete non implementa l'aggiunta ai file in maniera corretta
(ponendo che un tale sistema esista.) Dunque, se vi va bene limitarvi a
sistemi operativi che implementano flock() (e non si tratta poi di una
grande restrizione), allora quanto detto E<egrave> ciE<ograve> che dovete fare.
Se sapete che utilizzerete solamente un sistema che implementa l'aggiunta
ai file correttamente (ad es. non Win32), allora potete omettere seek()
dal codice sopra indicato.
Se sapete che state scrivendo codice che girerE<agrave> solamente su un
sistema operativo e su un filesystem che implementano l'aggiunta ai file
correttamente (ad esempio un filesystem locale su un moderno Unix), e
tenete il file in modo block-buffered e scrivete una quantitE<agrave>
inferiore alla grandezza di un buffer tra ogni flush [completamento
delle operaziono di I/O, NdT] manuale, allora ciascun contenuto del buffer
E<egrave> garantito che verrE<agrave> scritto alla fine del file in una volta sola,
senza che l'output di qualcun altro possa interferire. Potete anche
utilizzare la funzione syswrite(), che altro non E<egrave> che un wrapper
attorno alla chiamata di sistema write() del vostro sistema.
Teoreticamente, rimane comunque una piccola possibilitE<agrave> che un
segnale interrompa l'operazione di write() a livello di sistema prima che
essa sia completata. C'E<egrave> anche la possibilitE<agrave> che alcune
implementazioni di STDIO chiamino piE<ugrave> di una write() a livello di
sistema anche se il buffer iniziale era vuoto. Ci potrebbero essere alcuni
( run in 1.783 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )