Quando dovrei usare /dev/shm/ e quando dovrei usare /tmp/?
Quando dovrei usare /dev/shm/
e quando dovrei usare /tmp/
? Posso sempre contare sul fatto che ci siano entrambi su Unices?
Quando dovrei usare /dev/shm/
e quando dovrei usare /tmp/
? Posso sempre contare sul fatto che ci siano entrambi su Unices?
In ordine decrescente di probabilità:
┌───────────┬──────────────┬────────────────┐
│ /dev/shm │ always tmpfs │ Linux specific │
├───────────┼──────────────┼────────────────┤
│ /tmp │ can be tmpfs │ FHS 1.0 │
├───────────┼──────────────┼────────────────┤
│ /var/tmp │ never tmpfs │ FHS 1.0 │
└───────────┴──────────────┴────────────────┘
Poiché stai chiedendo di un punto di montaggio tmpfs specifico per Linux rispetto a una directory definita in modo portabile che può essere tmpfs (a seconda del tuo amministratore di sistema e di ciò che è predefinito per la tua distro), la tua domanda ha due aspetti, che altre risposte hanno sottolineato diversamente:
Edizione conservativa (mix di convenzioni da FHS e uso comune):
tmpfs
. /tmp
per dati grandi che potrebbero non entrare facilmente nella ram. /var/tmp
per dati che è utile mantenere attraverso i riavvii (come una cache). /var/tmp
come effetto collaterale della chiamata a /dev/shm
. Il pubblico previsto è costituito da buffer delimitati che sono sovrascritti all'infinito. Quindi questo è per file di lunga durata il cui contenuto è volatile e non terribilmente grande. shm_open()
onora la variabile d'ambiente mktemp
. Edizione pragmatica:
Usa TMPDIR
quando è importante usare tmpfs, /dev/shm
quando è importante non farlo, altrimenti /var/tmp
.
/tmp
è un no-op su tmpfs. Questa syscall è il nemico numero uno delle prestazioni (IO) (e della longevità di flash, se vi interessa), sebbene se vi trovate ad usare tmpfs (o eatmydata ) solo per sconfiggere fsync, allora voi (o qualche altro sviluppatore nella catena) state facendo qualcosa di sbagliato. Significa che le transazioni verso il dispositivo di archiviazione sono inutilmente a grana fine per il vostro scopo - siete chiaramente disposti a saltare alcuni savepoints per le prestazioni, dato che ora siete arrivati all'estremo di sabotarli tutti - raramente il miglior compromesso. Inoltre, è qui, nella terra delle prestazioni delle transazioni, che si trovano alcuni dei maggiori vantaggi di avere un SSD - qualsiasi SSD decente ha prestazioni fuori dal mondo rispetto a ciò che un disco rotante può sopportare (7200 rpm = 120 Hz, se nient'altro vi accede), per non parlare delle schede di memoria flash, che variano ampiamente su questa metrica (anche perché è un compromesso con le prestazioni sequenziali, che è ciò per cui sono classificate, ad esempio la classe delle schede SD). Quindi attenzione, sviluppatori con SSD superveloci, a non forzare i vostri utenti in questo caso d'uso!
Vuoi sentire una storia ridicola? La mia prima lezione fsync
: avevo un lavoro che comportava “l'aggiornamento” di routine di un mucchio di database Sqlite (tenuti come testcases) a un formato corrente sempre diverso. Il framework di “aggiornamento” eseguiva un mucchio di script, facendo almeno una transazione ciascuno, per aggiornare un database. Naturalmente, aggiornavo i miei database in parallelo (8 in parallelo, dato che ero benedetto da una potente CPU a 8 core). Ma come ho scoperto, non c'era alcun tipo di accelerazione della parallelizzazione (piuttosto un leggero hit) perché il processo era interamente legato all'IO. Curiosamente, avvolgendo il framework di aggiornamento in uno script che copiava ogni database in fsync
, lo aggiornava lì, e lo ricopiava su disco era tipo 100 volte più veloce (sempre con 8 in parallelo). Come bonus, anche il PC era usabile, mentre aggiornava i database.
L'uso appropriato di tmpfs è quello di evitare la scrittura non necessaria di dati volatili. Disabilitando effettivamente writeback, come impostare /dev/shm
all'infinito su un normale filesystem.
Questo ha molto poco a che fare con le prestazioni, e fallire è una preoccupazione molto minore che abusare di fsync: Il timeout di writeback determina quanto pigramente il contenuto del disco viene aggiornato dopo il contenuto della pagecache, e il valore predefinito di 5 secondi è un tempo lungo per un computer - un'applicazione può sovrascrivere un file quanto spesso vuole, nella pagecache, ma il contenuto sul disco viene aggiornato solo una volta ogni 5 secondi. A meno che l'applicazione non lo forzi con fsync, cioè. Pensate a quante volte un'applicazione può emettere un piccolo file in questo lasso di tempo, e capite perché fsync ogni singolo file sarebbe un problema molto più grande.
/proc/sys/vm/dirty_writeback_centisecs
, naturalmente. Conservare dati freddi. Si potrebbe essere tentati di pensare che servire file da swap sia efficiente quanto un normale filesystem, ma ci sono un paio di ragioni per cui non lo è:
Ok, ecco la realtà.
Sia tmpfs che un normale filesystem sono una cache di memoria su disco.
Il tmpfs usa la memoria e lo swapspace come backing store, un filesystem usa un'area specifica del disco, nessuno dei due è limitato nella dimensione che il filesystem può avere, è abbastanza possibile avere un tmpfs da 200GB su una macchina con meno di un GB di ram se si ha abbastanza swapspace.
La differenza è in quando i dati vengono scritti sul disco. Per un tmpfs i dati vengono scritti SOLO quando la memoria è troppo piena o è improbabile che i dati vengano usati presto. OTOH la maggior parte dei normali filesystem Linux sono progettati per avere sempre un insieme più o meno consistente di dati sul disco, così se l'utente stacca la spina non perde tutto.
Personalmente, sono abituato ad avere sistemi operativi che non si bloccano e sistemi UPS (ad esempio: batterie di laptop) quindi penso che i filesystem ext2/3 siano troppo paranoici con il loro intervallo di checkpoint di 5-10 secondi. Il filesystem ext4 è meglio con un checkpoint di 10 minuti, tranne che tratta i dati dell'utente come di seconda classe e non li protegge. (ext3 è lo stesso, ma non lo si nota a causa del checkpoint di 5 secondi)
Questo frequente checkpointing significa che dati non necessari vengono continuamente scritti su disco, anche per /tmp.
Quindi il risultato è che dovete creare uno spazio di swap grande quanto avete bisogno che sia /tmp (anche se dovete creare uno swapfile) e usare quello spazio per montare un tmpfs della dimensione richiesta su /tmp.
Non usate MAI /dev/shm.
A meno che non lo stiate usando per file IPC molto piccoli (probabilmente mmap’d) e siate sicuri che esista (non è uno standard) e che la macchina abbia abbastanza memoria + swap disponibile.
Usate /tmp/ per i file temporanei. Usate /dev/shm/ quando volete memoria condivisa (cioè, comunicazione interprocesso attraverso i file).
Puoi contare sul fatto che /tmp/ ci sia, ma /dev/shm/ è una cosa relativamente recente solo per Linux.
Un'altra volta in cui dovreste usare /dev/shm (per Linux 2.6 e superiori) è quando avete bisogno di un file system tmpfs garantito perché non sapete se _potete scrivere su disco.
Un sistema di monitoraggio con cui ho familiarità ha bisogno di scrivere su file temporanei mentre costruisce il suo rapporto da inviare a un server centrale. È molto più probabile in pratica che qualcosa impedisca di scrivere su un file system (sia per mancanza di spazio su disco o per un guasto al RAID sottostante che ha spinto il sistema in una modalità hardware di sola lettura), ma sarete ancora in grado di zoppicare per avvisare, piuttosto che se qualcosa spiralizza tutta la memoria disponibile in modo tale che tmpfs sarà inutilizzabile (e la scatola non sarà morta). In casi come questo, un sistema di monitoraggio preferirà scrivere sulla RAM in modo da essere potenzialmente in grado di inviare un avviso su un disco pieno o su un hardware morto o morente.
/dev/shm è usato per i driver di dispositivo e i programmi specifici del sistema di memoria virtuale condivisa.
Se state creando un programma che richiede un heap di memoria virtuale che dovrebbe essere mappato nella memoria virtuale. Questo vale doppio se avete bisogno di processi o thread multipli per essere in grado di accedere in modo sicuro a quella memoria.
Il fatto è che solo perché il driver usa una versione speciale di tmpfs per esso, non significa che dovreste usarlo come una generica partizione tmpfs. Invece, dovreste semplicemente creare un'altra partizione tmpfs se ne volete una per la vostra directory temporanea.
In PERL, avendo 8GB minimo su qualsiasi macchina (tutte con Linux Mint), sono di quella che penso sia una buona abitudine di fare algoritmi complessi basati su DB\File (struttura dati in un file) con milioni di letture e scritture usando /dev/shm
In altre lingue, non avendo gigether ovunque, per evitare le partenze e gli arresti nel trasferimento in rete (lavorando localmente su un file che si trova su un server in un'atmosfera client-server), usando un file batch di qualche tipo, copierò l'intero (300-900MB) file in una volta sola su /dev/shm, eseguirò il programma con output su /dev/shm, riscriverò i risultati sul server, e cancellerò da /dev/shm
Naturalmente, se avessi meno RAM, non farei questo. Ordinariamente, il file system in-memory di /dev/shm ha una dimensione pari alla metà della vostra RAM disponibile. Tuttavia, l'uso ordinario della RAM è costante. Quindi non potreste davvero fare questo su un dispositivo con 2GB o meno. Per trasformare la parafrasi in iperbole, spesso ci sono cose nella RAM che nemmeno il sistema riporta bene.