riscrivi il file esistente in modo che venga sostituito atomicamente dalla nuova versione, solo una volta completamente scritto


18

Ricordo vagamente di aver letto da qualche parte che in passato c'era, in alcuni Unices, un modo per aprire un file esistente per la scrittura, con un flag che chiedeva al kernel di usare la vecchia versione (per altri processi accedendo a esso per la lettura), fino al "nuovo "la versione è stata completamente scritta (fd chiuso), da cui il file è apparso come la nuova versione.

In altre parole, altri processi hanno visto la vecchia versione o quella nuova, mai scritta in modo incompleto.

Qualcuno può indicarmi un riferimento?


Sembra che cosa potrebbe fare Plan 9 , ma no.
Gilles 'SO- smetti di essere malvagio'

2
Sembra File-11 su OpenVMS: "Ogni volta che un file viene salvato, anziché sovrascrivere la versione esistente, viene creato un nuovo file con lo stesso nome ma con un numero di versione incrementato".
Mat

Perchè hai chiesto? Hai bisogno di quella funzionalità o era solo curiosità?
Nils,

1
Sarei felice di avere quella funzionalità e mi sono ricordato di aver letto da qualche parte che esisteva. Quindi una miscela di necessità e curiosità.
eudoxos,

Tutti i sistemi Unix lo consentono in un altro modo: creare un nuovo file nella stessa directory, riempire con i contenuti modificati ed eseguire la ridenominazione atomica. Questo è molto più costoso per piccole modifiche ma funzionante.
Netch

Risposte:


14

Quello che stai descrivendo suona esattamente come una ridenominazione di base per sovrascrivere un file.

Quando rinomini / sposti un file sopra un altro, il vecchio file viene scollegato. Significa che il file esiste ancora, ma non è più nella struttura del filesystem. Pertanto, le vecchie applicazioni continueranno ad essere in grado di accedere al file finché lo terranno aperto. Una volta che tutte le applicazioni hanno chiuso il vecchio file, in realtà non è allocato sul disco.

La renamechiamata di sistema è un'operazione atomica. Quindi, per fare ciò, creare un nuovo file con un nome diverso e quindi chiamare renameper rinominare il file temporaneo come quello che si desidera sostituire. Poiché l'operazione è atomica, non vi è assolutamente alcun periodo in cui il file è mancante. Passa istantaneamente dal vecchio file al nuovo file.
Si noti tuttavia che il file temporaneo e il file da sostituire devono risiedere sullo stesso punto di montaggio.


Puoi usarlo solo se il tuo programma è stato specificamente scritto pensando alle funzionalità. In questo caso, tuttavia, era una funzionalità del sistema operativo, da cui anche ai programmi regolari veniva assegnata automaticamente questa semantica atomica.
eudoxos,

1
@eudoxos il tuo commento non ha senso. Stai dicendo che i programmi dovrebbero essere scritti appositamente per fare la renamecosa di scambio. Anche se esistesse una "funzionalità del sistema operativo" di cui stai parlando, il programma dovrebbe comunque essere scritto per trarne vantaggio. Qual è la differenza?
Patrick

C'è una differenza se passi un flag (possibilmente non supportato) alla openscala di sistema o se devi fare ciò che descrivi a mano.
eudoxos,

Tieni presente che per mantenere la vecchia o la nuova versione completamente scritta in caso di crash devi sincronizzare ulteriormente il nuovo file su disco con fsync o simile
texthell

@textshell senza la sincronizzazione si ottiene comunque atomicità ... solo non durata ... giusto? In questo caso non capisco l'argomento su goo.gl/qfQQfy . Nel mio caso ho un sistema sotto carico estremo e voglio evitare i flush del file system e non mi interessa se il file sopravvive a un arresto anomalo.
wcochran,

6

Come scrive Patrick , il solito modo per farlo è quello di scrivere la nuova versione in un file separato e, al termine, rinominare la nuova versione con il vecchio nome file, sovrascrivendolo atomicamente. Questa seconda operazione si chiama overwrite-by-rename .

Ora, alcuni riferimenti:


man 3p renamemi dice che renameè davvero atomico, e immagino che sia pensato per tutti i file system Linux. E quando leggo il primo articolo che hai collegato, penso ancora che le operazioni di ridenominazione di Btrfs siano atomiche.
hagello,

1

Questo mi ricorda Allocate On Flush . Quando un filesystem utilizza questa funzione, invece di scrivere i dati direttamente sul disco, sottrae la dimensione dei dati da scrivere dal contatore dello spazio libero del disco e mantiene i dati in memoria fino a quando non viene eseguita una chiamata di sistema di sincronizzazione o il kernel decide per svuotare i buffer sporchi.

In questo caso, se il file viene modificato da un processo e viene aperto da un altro processo, quest'ultimo "vedrà" la versione non modificata ( o "vecchia" se si preferisce ) del file.

Naturalmente, quanto sopra è teorico e dipende da vari fattori, e direi un po 'imprevedibile, dal momento che non sai esattamente quando il kernel sta andando a filo con le pagine sporche. Ad esempio in Linux ( come puoi leggere anche nella sezione 15.3 di Comprensione del kernel Linux ), le pagine sporche vengono scritte su disco nelle seguenti condizioni:

  • La cache delle pagine diventa troppo piena e sono necessarie più pagine oppure il numero di pagine sporche diventa troppo grande.

  • È trascorso troppo tempo da quando una pagina è rimasta sporca.

  • Un processo richiede lo svuotamento di tutte le modifiche in sospeso di un dispositivo a blocchi o di un determinato file; lo fa invocando una chiamata di sistema sync (), fsync () o fdatasync ().

Questa funzione è nota per essere implementata nei filesystem HFS +, XFS, Reiser4, ZFS, Btrfs ed ext4.


2
Ciò che descrivi è una tecnica del filesystem che dovrebbe essere invisibile dallo spazio utente (e quindi non fare ciò che indichi) sui sistemi POSIX (file) (vedi write : "Se una lettura () dei dati dei file può essere dimostrata (con qualsiasi mezzo) che si verificano dopo una scrittura () dei dati, deve riflettere quella scrittura (), anche se le chiamate sono effettuate da processi diversi . "). Altri processi non vedranno i vecchi dati (su POSIX).
Mat

Grazie per la correzione. Immagino che la mia comprensione di questa tecnica del filesystem fosse sbagliata.
dkaragasidis,

Bene, questo sembra qualcos'altro. Ricordo vagamente ora che è stato in un'intervista con RMS che ha menzionato questa caratteristica, forse era un vecchio sistema arcano che non ha mai vissuto al di fuori del mondo accademico ... Grazie comunque.
eudoxos,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.