Come sapere se un file è mappato in memoria?


8

Sono confuso riguardo ai file mappati in memoria, quindi ho un paio di domande che sarei molto felice se potessi aiutarmi.

  1. Diciamo che cerco una directory nel mio file system e c'è un file in questa directory. È possibile che questo file punti a un'area nella memoria principale, anziché a un'area nel disco?
  2. Se questo è possibile, è questo che chiamiamo "file mappato in memoria"?
  3. Quale sarebbe il significato di spostare tale file all'interno del file system (ovvero, mvingingare tale file da una directory in un'altra)? Quello che ho capito è che, poiché il file è mappato in memoria, il processo (i) che interagisce con il file scrive sempre in una regione predefinita della memoria principale e quando apriamo quel file (ad esempio usando vim), leggiamo quella regione di main memoria (quindi, nessun disco è coinvolto). Quindi, indipendentemente da dove spostiamo il file, funzionerà sempre correttamente, giusto? Se sì, lo spostamento del file nel file system ha qualche significato?
  4. Esiste un comando che direbbe se un file è mappato in memoria?
  5. Infine, se apro un file mappato in memoria con vim, apporto alcune modifiche e lo salvo e chiudo vim, cosa accadrà? Le mie modifiche verranno semplicemente scritte nella memoria principale? In tal caso, altri processi che utilizzano questo file vedranno le modifiche che ho appena apportato? Nella mia esperienza, gli altri processi non hanno visto le modifiche che ho apportato al file quando ho apportato alcune modifiche al file con vim. Qual è la ragione di ciò?

12
Questo mi ricorda qualcuno che ha chiesto come sapere se un file era un collegamento reale.
Dmitry Grigoryev,

3
@DmitryGrigoryev Questo è abbastanza divertente, in effetti, ma tutti imparano :)
cat

Risposte:


24

I file associati alla memoria funzionano al contrario. La mappatura della memoria non è una proprietà del file, ma un modo per accedere al file: un processo può mappare il contenuto di un file (o un suo sottoinsieme) nel suo spazio di indirizzi. Ciò semplifica la lettura e la scrittura nel file; farlo comporta semplicemente la lettura e la scrittura in memoria. Il file stesso, su disco, è uguale a qualsiasi altro file.

Per impostare questo, i processi usano la mmapfunzione. Questo può essere utilizzato anche per altri scopi, come la condivisione della memoria tra i processi.


14
@Utku Non ha nulla a che fare con i file mappati in memoria.
Satō Katsura,

12
Se non hai spento il server MySQL, questo è normale: il server ha un descrittore di file aperto sul file, e questo rimane valido anche con mv.
Stephen Kitt,

11
Il descrittore di file punta (eventualmente) agli inode nel filesystem; è lì che vive davvero il file. Le voci della directory puntano anche a questi inode e mvcambiano semplicemente le voci della directory, non gli inode (quando si spostano i file sullo stesso filesystem).
Stephen Kitt,

1
La descrizione è un'utile semplificazione, ma solo per l'accuratezza: i mapping di memoria tecnicamente non sono la stessa cosa dei descrittori di file, ma funzionano allo stesso modo (facendo riferimento all'inode, non al nome del file). open (), mmap (), close () non lascia FD, solo una mappatura, che verrà visualizzata con lsof. Non scompare fino a quando il processo chiama munmap () o non esce (o sostituisce la mappatura con una diversa usando mmap (MAP_FIXED) ...)
Peter Cordes,

3
@Utku In realtà non hai spostato il file. Hai appena creato una nuova voce di directory che fa riferimento allo stesso file e quindi rimosso quella precedente. La modifica della denominazione non ha alcun effetto su un processo in cui il file è già aperto.
David Schwartz,

11

Un file mappato in memoria non è (necessariamente) supportato dalla memoria. Può vivere perfettamente su un disco. In realtà, dove vive un file non è una proprietà del file stesso ma del file system in cui risiede.

La mappatura di un file in memoria è un'operazione che un processo può eseguire per caricare una parte del file in memoria. Il risultato sembra una normale regione di memoria, tranne per il fatto che quando il processo legge o scrive su questa regione, in realtà legge e scrive sul file. Se apri un file, lo associ alla memoria, lo scrivi e lo salvi, la modifica verrà effettuata sul file, sul disco (se vive su un disco, ovviamente).

Questo può essere usato per esempio quando sai di avere un sacco di accessi fare in un file, che non stanno andando a essere sequenziale, sia perché può essere più facile e più efficiente di fare le letture e scritture in memoria rispetto al problema read, write, e llseekchiamate di sistema. L'unico problema con questo metodo è che non puoi davvero usarlo se il file deve essere letto o scritto da più processi contemporaneamente. I risultati sarebbero imprevedibili.

Non conosco alcun comando che possa dirti se un file è attualmente mappato. È possibile controllare le mappature di un processo, tuttavia, in /proc/<pid>/maps(se il sistema lo possiede).

Per rispondere alla tua seconda domanda, quando apri un file, anche se lo sposti nel filesystem, i processi che lo hanno aperto possono ancora usarlo. Quello che succede è che un file non dipende dalle sue voci nei filesystem. Finché hai aperto un file, hai un "handle", un descrittore di file, che ti permette di leggere e scrivere su di esso, anche se il suo percorso nel file system cambia. Un file scompare solo quando non ha alcuna voce nel filesystem e nessun processo contiene un descrittore di file su di esso.


Quindi, quando spostiamo un file, il valore del descrittore di file non cambia. Esiste un mapping descrittore percorso-file e cambia solo la parte del percorso di tale mapping. È corretto?
Utku,

1
In un certo senso sì, ma non sono sicuro di capirti, quindi lasciami riformulare. Fondamentalmente, "un file" è tre cose. Una voce della directory è un percorso nel file system. Un inode è il contenuto di un file. E un descrittore di file rappresenta un file aperto. Sia le voci della directory che i descrittori dei file contengono un puntatore al loro inode di supporto. Quando si apre un file, si passa la voce della directory e il kernel restituisce un descrittore di file. Pertanto, anche se la voce della directory originale cambia, il descrittore di file punta ancora allo stesso inode e puoi accedere al file.
lgeorget,

1
Tuttavia, puoi esaminare le mappature di un processo /proc/<pid>/maps. - A condizione che detto processo viva su un sistema che deve /proccominciare. OpenBSD non lo fa e FreeBSD lo sta gradualmente eliminando. Inoltre, FreeBSD ha /proc/<pid>/mapinvece di /proc/<pid>/maps.
Satō Katsura,

@SatoKatsura Grazie per la precisione. Ho solo una macchina Linux a portata di mano, quindi ho pensato di raccontare il mio caso e lasciare che le persone parlassero del loro ... Sentiti libero di modificare la risposta se hai cose da correggere / aggiungere qui.
Lgeorget,

Da quando lo chiedi: hai assunto che l'OP capisca effettivamente cosa sta chiedendo e spiegando in dettaglio quali sono i file mappati in memoria. Non credo che tu l'abbia reso un servizio. IMO il tuo primo commento sopra era molto più pertinente a ciò che l'OP stava effettivamente chiedendo quindi la tua risposta. FWIW.
Satō Katsura,

9

Q4: esiste un comando che direbbe se un file è mappato in memoria?

Il lsofcomando ti mostrerà tutti i file attualmente in uso dal sistema. La colonna "FD" conterrà "mem" se il file è mappato in memoria. Quindi potresti grep l'output di questo comando per il nome file che ti interessa.


3
Oppure usalsof -ad mem /path/to/file
Stéphane Chazelas il

5
O meglio lsof -ad mem,txt /path/to/file, come i file che vengono eseguiti hanno anche porzioni di essi mmaped nello spazio di indirizzi del processo, ma apparire come txtnel lsofuscita.
Stéphane Chazelas,

7

Sembra che tu confonda la mappatura della memoria con i file nei filesystem che risiedono nella memoria, insieme ad altri concetti come il modo in cui i processi mantengono l'accesso ai file anche quando vengono spostati.

Vado domanda per domanda per vedere se riesco a chiarire le cose.

  1. Diciamo che cerco una directory nel mio file system e c'è un file in questa directory. È possibile che questo file punti a un'area nella memoria principale, anziché a un'area nel disco?

Indica la memoria principale se si trova su un file system residente in memoria, come procfs che è tipicamente montato su / proc, o sysfs che è su / sys o tmpfs che a volte è su / tmp.

  1. Se questo è possibile, è questo che chiamiamo "file mappato in memoria"?

No. Come ha detto Stephen-Kitt, "mappatura della memoria" si riferisce a un modo per accedere a un file "mappandolo" sulla memoria principale e lavorando con esso piuttosto che leggere e scrivere blocchi alla volta tramite funzioni come read () e Scrivi().

  1. Quale sarebbe il significato di spostare tale file all'interno del file system (ovvero spostare tale file da una directory in un'altra)? Quello che ho capito è che, poiché il file è mappato in memoria, il processo (i) che interagisce con il file scrive sempre in una regione predefinita della memoria principale e quando apriamo quel file (ad esempio usando vim), leggiamo quella regione di memoria principale (quindi, nessun disco è coinvolto). Quindi, indipendentemente da dove spostiamo il file, funzionerà sempre correttamente, giusto? Se sì, lo spostamento del file nel file system ha qualche significato?

Se lo sposti all'interno dello stesso filesystem, stai semplicemente spostando un riferimento, un inode da una directory all'altra. Se ci sono programmi che hanno già aperto questo file, accederanno comunque allo stesso file perché hanno già l'inode a portata di mano tramite un descrittore di file. Questo è ciò che è accaduto con il file table_name.idb che hai citato in un commento.

  1. Esiste un comando che direbbe se un file è mappato in memoria?

Wossname ha già risposto a questa domanda per i file mappati in memoria. lsofti dirà quali processi hanno il file mappato in memoria.

Per sapere se un file si trova in un filesystem residente in memoria, è possibile utilizzare dfo mountelencare i filesystem e i loro mountpoint. Hai solo bisogno di sapere quali tipi di filesystem risiedono in memoria cercandoli (ad es. In Wikipedia).

  1. Infine, se apro un file mappato in memoria con vim, apporto alcune modifiche su di esso e salvo e chiudo vim, cosa accadrà? Le mie modifiche verranno semplicemente scritte nella memoria principale? In tal caso, altri processi che utilizzano questo file vedranno le modifiche che ho appena apportato? Nella mia esperienza, gli altri processi non hanno visto le modifiche che ho apportato al file quando ho apportato alcune modifiche al file con vim. Qual è la ragione di ciò?

Personalmente, non ho usato la mmapfunzione in un programma C, ma come ho capito dallo skimming man mmape info mmapnon c'è magia per mantenere sincronizzata la rappresentazione in memoria. Nella sua forma base, chiamare mmap copia il contenuto del file in memoria e msyncviene usato per riscriverlo dalla memoria al disco. Se il file su disco cambia, non c'è nulla in atto per rilevarlo e modificare automaticamente la rappresentazione in memoria in tutti i processi che lo hanno mappato.

EDIT: Si scopre che mmap () in realtà cerca di mantenere sincronizzata la rappresentazione in memoria in alcune condizioni. Se la mappa viene solo letta, verrà mantenuta sincronizzata anche quando altri processi scrivono nel file. Se è scritto (assegnando alla regione di memoria), ciò che accade dipende da quale flag MAP_SHARED o MAP_PRIVATE apparentemente obbligatori viene fornito a mmap (). Se viene fornito MAP_PRIVATE, la mappa esegue il fork dalla rappresentazione su disco e smette di essere sincronizzata fino a quando non si utilizza msync (). Se viene fornito MAP_SHARED, gli aggiornamenti vengono resi visibili ad altri processi su cui è stato mappato il file, nonché (anche se non necessariamente necessario) la rappresentazione su disco.

Ho appena aperto vim su un file esistente eed eseguito il comando :w, pur avendo inotifywait -m .eseguito in un altro terminale. Tra alcuni bit strani, questa è la parte importante da cui ho avuto inotifywait.

./ MOVED_FROM e
./ MOVED_TO e~
./ CREATE e
./ OPEN e
./ MODIFY e
./ CLOSE_WRITE,CLOSE e
./ ATTRIB e
./ ATTRIB e
./ DELETE e~

Vim crea un nuovo file e rimuove quello vecchio. Perché lo fa invece di modificare il file va oltre lo scopo di questa domanda, ma il punto è che questo è un nuovo file e quindi ha un nuovo inode.

Ora, cosa intendi con altri processi usando questo file? Se intendi processi che avevano aperto il file mentre lo facevi, no non vedranno le modifiche. Questo perché, sebbene abbiano aperto un file con lo stesso percorso, non sono lo stesso file. Se intendi processi che potrebbero aprire il file dopo averlo fatto, allora sì vedranno le modifiche. Apriranno il nuovo file che hai creato.

È importante notare che sebbene i programmi possano sembrare avere un file aperto nell'interfaccia utente, ciò non significa necessariamente che mantengano il file aperto nel processo. Vim ne è un esempio, come mostrato sopra.


3
" Se il file su disco cambia, non c'è nulla in atto per rilevarlo e modificare automaticamente la rappresentazione in memoria in tutti i processi che lo hanno mappato. " Cosa cambierebbe il file system su disco dietro il retro della mappatura della pagina del sistema operativo sistema? Stai immaginando un accesso non elaborato al dispositivo a blocchi o a un dispositivo a blocchi condiviso su iSCSI o qualcosa del genere?
David Schwartz,

@ David-Schwartz No. Sto immaginando due processi con un file open () 'ed. Il processo 1 utilizza mmap () per copiare / mappare il contenuto del file nella memoria. Quindi, il processo 2 utilizza write () (e possibilmente fsync ()) per modificare i contenuti su disco. In questo momento, il contenuto del file 1 processo in memoria non riflette le modifiche apportate dal processo 2, giusto?
JoL

No certo che no. Lo scopo della writefunzione è di modificare i dati del file. Ciò può significare o meno cambiare il contenuto su disco, ma qualunque cosa implichi, è responsabilità del file system farlo correttamente. In questo caso, implicherebbe la modifica della pagina di memoria mappata e la sua marcatura.
David Schwartz,

@ David-Schwartz ho sperimentato mmap () e hai ragione. Nello scenario che ho esposto nel mio commento precedente, il contenuto del processo 1 aveva in memoria (nella mappa) effettivamente rifletteva le modifiche a meno che il processo 1 non avesse scritto in precedenza nella memoria nella mappatura. Ciò era vero anche quando il processo di modifica 1 era in una posizione diversa dalla modifica effettuata dal processo 2. Ho aggiornato la risposta cancellando ciò che non è corretto e aggiungendo ciò che ho trovato.
JoL,

1
@ david-schwartz Siamo spiacenti, non intendevo implicare che mmap si comportasse diversamente da quanto specificato nella documentazione, ma sì, penso di aver reso la risposta troppo confusa. Penso che sia ancora nell'ambito, ma la domanda "altri processi che utilizzano questo file vedranno le modifiche che ho appena apportato?", Sembra essere troppo ampio. Ci sono troppi "dipende". Poiché il bisogno del PO sembra essere puramente autodidattico, ho cercato di dare una risposta accurata e coprire il più possibile il terreno, ma avrei potuto esagerare. Tuttavia, sono ancora felice di averlo fatto, come ho imparato anche un po '.
JoL
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.