2012-10-29 2 views
7
  • shm_open()
  • mmap() con predefiniti grandi length
  • fork() (più volte)
  • ftruncate() a volontà

Il punto di questo è quello di fare in modo che ogni processo generato da fork() hanno un segmento condiviso allo stesso indirizzo. Tuttavia, non voglio mantenere la RAM sempre occupata, ma ridimensionarla dinamicamente (con dimensioni che spaziano da 0 a grande length).è sicuro eseguire il fobraggio di un oggetto di memoria condivisa dopo averlo cancellato?

Può funzionare? C'è UB?

risposta

8

No, va bene. È possibile troncare il file sottostante in qualsiasi momento, ma è possibile ricevere SIGBUS se si accede alla memoria oltre i limiti del file. Quindi, dovrai stare estremamente attento a non toccare la memoria oltre la lunghezza corrente del file (o prendere lo SIGBUS e gestirlo).

Da man 2 mmap:

Uso di una regione mappata può provocare questi segnali:

SIGBUS tentativo di accesso ad una porzione del buffer che non corrisponde al il file (ad esempio, oltre la fine del file, incluso il caso in cui un altro processo ha troncato il file).

+0

Questo è quello che supponevo, ma l'attivatore 'munmap' può scrivere su pagine sporche che potrebbero attivare un' SIGBUS'? –

+0

Contrassegnare questo come accettato, perché risponde alla mia domanda. Ma il metodo di Damon è meglio gestibile (posso scaricare le pagine nel mezzo dell'intervallo 'mmap'ed). –

+0

@nneonneo Non penso che sia giusto. Credo che sia necessario eseguire un 'mremap' dopo il' ftruncate' per aggiornare la mappatura. Ciononostante, dovresti comunque allocare una grande dimensione in origine per evitare che 'mremap' fallisca con 'ENOMEM'. – jleahy

1

Non ridimensionarlo.

Non voglio mantenere la RAM occupato tutto il tempo

Questo è ciò che il kernel farà per voi con la memoria virtuale. Sarà impaginato secondo necessità/appropriato fino a quando non si utilizza mlock() o MAP_LOCKED.

+0

bene, RAM e swap. Potrei usare qualcosa nel mezzo dell'area mappata in un dato momento (costringendo il kernel a commetterlo), ma poi potrei dimenticarlo per il resto del runtime. Quindi penso di aver bisogno di un modo per dire esplicitamente che non sto più usando quella parte dello spazio degli indirizzi. –

+0

Puoi usare 'madvise()', ma sappi che non ci sono garanzie sul comportamento. –

+0

Suppongo che userò 'MADV_REMOVE'. Ma allora cosa dovrei fare se avessi bisogno di recuperare quello spazio? –

1

Crea mappature di dimensioni sufficienti, non "manterrà la RAM occupata" a meno che non venga effettivamente utilizzata.

Se siete preoccupati per mantenere RAM occupata dopo aver terminato usarlo, chiamare madvise(MADV_DONTNEED) - questo sarà eliminare le pagine e si restituire nuove pagine dal pool zero se vi si accede di nuovo.

+0

Non c'è nessuna operazione che devo eseguire prima di scrivere in un intervallo che è stato contrassegnato come 'MADV_DONTNEED', giusto? –

+0

Si noti che il comportamento di riempimento zero è solo nei casi in cui il backing store non ha più quelle pagine (come potrebbe essere nella domanda in cui alcuni dei dati potrebbero essere stati scartati da 'ftruncate'). –

+0

@LorenzoPistone: non c'è niente che devi fare, no. 'MADV_DONTNEED' eliminerà le pagine e (se supportato da un file) ricaricherà le pagine dal disco in modo trasparente, se necessario, o (anon mapping) semplicemente tirando una pagina zero su di te. Si noti che quest'ultimo è - almeno a mio avviso - un comportamento "errato", poiché POSIX afferma che la semantica non è cambiata (il che è il caso!). È proprio quello che vuoi, però. – Damon

Problemi correlati