Ho bisogno di una ridimensionazione senza copia di un file mmap di grandi dimensioni pur consentendo l'accesso simultaneo ai thread del lettore.Ridimensionamento rapido di un file mmap
Il modo semplice è utilizzare due mapping MAP_SHARED (far crescere il file, quindi creare una seconda mappatura che include la regione di sviluppo) nello stesso processo sullo stesso file e quindi rimuovere la mappatura precedente una volta che tutti i lettori che potevano accedervi sono finiti. Tuttavia, sono curioso di sapere se lo schema qui sotto potrebbe funzionare, e se è così, c'è qualche vantaggio ad esso.
- mmap un file con MAP_PRIVATE
- do accesso in sola lettura a questa memoria in più thread
- o acquisire un mutex per il file, scrivere alla memoria (assumere questo è fatto in modo che il i lettori, che possono leggere quella memoria, non ne sono incasinati)
- o acquisire il mutex, ma aumentare la dimensione del file e usare mremap per spostarlo in un nuovo indirizzo (ridimensionare la mappatura senza copiare o file non necessario IO.)
La parte pazza arriva a (4). Se si sposta la memoria, i vecchi indirizzi non sono più validi e i lettori, che stanno ancora leggendo, potrebbero improvvisamente avere una violazione di accesso. Cosa succede se modifichiamo i lettori per intercettare questa violazione di accesso e quindi riavviare l'operazione (cioè non rileggere l'indirizzo errato, ricalcolare l'indirizzo dato l'offset e il nuovo indirizzo di base da mremap.) Sì, lo so che è malvagio , ma a mio avviso i lettori possono solo leggere correttamente i dati al vecchio indirizzo o fallire con una violazione di accesso e riprovare. Se si presta sufficiente attenzione, che dovrebbe essere sicuro. Dal momento che il ridimensionamento non accadrebbe spesso, i lettori alla fine riuscirebbero e non rimanere bloccati in un ciclo di tentativi.
Un problema può verificarsi se tale vecchio spazio indirizzo viene riutilizzato mentre un lettore ha ancora un puntatore ad esso. Quindi non ci saranno violazioni dell'accesso, ma i dati non saranno corretti e il programma entrerà nell'unicorno e nella terra piena di caramelle di comportamento indefinito (in cui di solito non vi sono né unicorni né caramelle.)
Ma se hai controllato completamente le allocazioni e potresti assicurarsi che tutte le allocazioni che si verificano durante questo periodo non riutilizzino mai quel vecchio spazio indirizzo, quindi questo non dovrebbe essere un problema e il comportamento non dovrebbe essere indefinito.
Ho ragione? Potrebbe funzionare? C'è qualche vantaggio su questo usando due mappature MAP_SHARED?
Si potrebbe semplicemente usare un blocco di lettura/scrittura e proteggere il remapping sotto il blocco di scrittura, no? – fge
Direi che il collo di bottiglia è il disco. Sei sicuro che ne valga la pena? copiare file enormi da disco richiede sempre tempo, perché i dischi sono dispositivi meccanici lenti. –
fge, sì ma il blocco sui thread di lettura è fuori questione in questo caso – Eloff