PDA

View Full Version : [Win32] Scritture concorrenti su file


fero86
16-01-2009, 17:56
salve a tutti, ho una domanda da fare... ho esplorato da cima a fondo nella libreria MSDN tutta la documentazione relativa all'I/O sui files, cioé questa sezione: http://msdn.microsoft.com/en-us/library/aa364229(VS.85).aspx

ma non sono riuscito a capire una cosa fondamentale: nel caso di I/O sincrono (quindi non overlapped) e di scritture concorrenti su uno stesso file da parte di processi diversi, o per meglio dire attraverso HANDLEs diversi, i vari blocchi scritti sono ordinati?? oppure il caching causa un potenziale disordinamento?

quello che mi interessa capire fondamentalmente é se il caching:
1) avviene per file;
2) avviene per HANDLE;
3) avviene per processo;
4) l'interfaccia Win32 non specifica questo dettaglio che viene lasciato quindi all'implementazione sottostante, ad esempio al kernel NT o all'FSD sottostante.

questa differenza é molto importante perché:
nel caso 1) i vari blocchi di dati scritti vengono automaticamente ordinati nella cache, che funziona da coda;
nei casi 2) e 3) i blocchi scritti potrebbero essere disordinati perché ciascuno viene effettivamente scritto sul file solo quando la cache da cui proviene viene flushata, e quindi i blocchi restano ordinati secondo l'ordine in cui vengono flushate le caches;
nel caso 4) é una bella rottura di scatole.

volevo saperlo giusto per sapersi regolare quando si scrive un programma che girerá su piu processi e dovrá accedere concorrentemente agli stessi files in scrittura :)

so bene che Vista introduce il file system transazionale che elimina questo e dozzine di altri problemi, ma spesso e volentieri di questi tempi il target é ancora XP.

grazie a tutti dei vostri pareri, specialmente mi farebbe piacere ricevere eventuali link a pagine di MSDN che mi sono sfuggite!

fero86
16-01-2009, 17:58
aggiungo un dettaglio che ho dimenticato di specificare: tutta questa questione ha senso solamente quando si parla di scritture di buffers la cui dimensione non supera quella di un settore: in caso contrario infatti la WriteFile non é atomica per contratto, e quindi i dati scritti in contemporanea vengono disordinati indipendentemente dal caching.

DanieleC88
16-01-2009, 18:16
http://msdn.microsoft.com/en-us/library/cc644950(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa364218(VS.85).aspx

Ti conviene aprire i file con FILE_FLAG_NO_BUFFERING (eventualmente, anche FILE_FLAG_WRITE_THROUGH). Attento agli accessi non bufferizzati, ci sono restrizioni sulla quantità di byte a cui puoi con una operazione (leggi il primo link).

ciao ;)

fero86
16-01-2009, 18:25
http://msdn.microsoft.com/en-us/library/cc644950(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa364218(VS.85).aspx ti ringrazio, ma quei link sono stati i primi che ho letto quando mi sono posto il problema :D
non mi sembra che rispondano alla mia domanda sul caching; c'é giusto un'affermazione d'interesse secondo la quale il caching viene operato "per file object" e quindi questo cosa significa? esiste un file object in tutto il sistema per ciascun file, oppure uno per processo oppure uno per HANDLE?


Ti conviene aprire i file con FILE_FLAG_NO_BUFFERING (eventualmente, anche FILE_FLAG_WRITE_THROUGH). Attento agli accessi non bufferizzati, ci sono restrizioni sulla quantità di byte a cui puoi con una operazione (leggi il primo link). due domande:
1) e volendo aprirlo invece senza quei due flag per motivi di performance? MSDN spiega che per scritture piccole e frequenti conviene usare il caching.
2) cosa cambia aggiungendo anche FILE_FLAG_WRITE_THROUGH? non sono riuscito a capirlo.

DanieleC88
16-01-2009, 18:39
Non sapevo, nel caso te li ho postati. :Prrr:
Be' sinceramente sono un po' in dubbio anche io su questo "file object" di cui si parla, personalmente l'avevo interpretato come un identificatore del file a cui fanno capo i vari HANDLE... ma è una mia interpretazione. In questo caso ti andrebbe bene ed avresti la risposta al punto 1). Per il punto 2), serve ad evitare che restino i metadati "appesi" e va a scrivere immediatamente tutto su disco.

fero86
25-01-2009, 11:29
Non sapevo, nel caso te li ho postati. :Prrr:
Be' sinceramente sono un po' in dubbio anche io su questo "file object" di cui si parla, personalmente l'avevo interpretato come un identificatore del file a cui fanno capo i vari HANDLE... ma è una mia interpretazione. In questo caso ti andrebbe bene ed avresti la risposta al punto 1). Per il punto 2), serve ad evitare che restino i metadati "appesi" e va a scrivere immediatamente tutto su disco.
riporto su questa discussione per dire che ho trovato la soluzione. si, era come dicevi tu: il file object é unico su tutto il sistema ed é quello a cui fanno capo tutti gli HANDLE aperti su uno stesso file, indipendentemente dal processo che li apre.
questa pagina esplica chiaramente la terminologia:
http://msdn.microsoft.com/en-us/library/ms724485(VS.85).aspx

di conseguenza il buffering avviene per file e la cache funziona da coda che ordina tutti i bytes scritti concorrentemente anche prima di qualsiasi flush; un flush da parte di un processo flusha anche i bytes scritti da altri processi.

mi resta solo da verificare se il file pointer viene tenuto per file object o per HANDLE, ma adesso non mi va :p e comunque sospetto decisamente la prima, che significa che un processo tra una scrittura e un'altra potrebbe ritrovarsi il file pointer magicamente spostato in una posizione che non si aspetta; d'altra parte sarebbe sempre buona pratica aprire un file senza FILE_SHARE_WRITE quando lo si apre con GENERIC_WRITE.