Estoy confundido acerca de los archivos mapeados en memoria, así que tengo un par de preguntas que me alegraría mucho si me pudieran ayudar.
- Digamos que busco un directorio en mi sistema de archivos y hay un archivo en este directorio. ¿Es posible que este archivo apunte a una región en la memoria principal, en lugar de apuntar a una región en el disco?
- Si esto es posible, ¿es esto lo que llamamos 'archivo mapeado en memoria'?
- ¿Cuál sería el significado de mover dicho archivo alrededor del sistema de archivos (es decir,
mv
llevar dicho archivo de un directorio a otro)? Lo que entiendo es que, dado que el archivo está mapeado en memoria, los procesos que interactúan con el archivo siempre escriben en una región predefinida de la memoria principal, y cuando abrimos ese archivo (por ejemplo, usandovim
), leemos esa región de main memoria (por lo tanto, no hay disco involucrado). Por lo tanto, no importa dónde muevamos el archivo, siempre funcionará correctamente, ¿verdad? En caso afirmativo, ¿tiene algún sentido mover el archivo por el sistema de archivos? - ¿Hay un comando que diga si un archivo está mapeado en memoria?
- Finalmente, si abro un archivo mapeado con memoria
vim
, hago algunos cambios y lo guardo y cierrovim
, ¿qué sucederá? ¿Mis cambios simplemente se escribirán en la memoria principal? Si ese es el caso, ¿otros procesos que usan este archivo verán los cambios que acabo de hacer? En mi experiencia, los otros procesos no vieron los cambios que hice al archivo cuando hice algunos cambios en el archivovim
. ¿Cuál es la razón para esto?
Respuestas:
Los archivos mapeados en memoria funcionan al revés. La asignación de memoria no es una propiedad del archivo, sino una forma de acceder al archivo: un proceso puede asignar el contenido de un archivo (o un subconjunto del mismo) a su espacio de direcciones. Esto hace que sea más fácil leer y escribir en el archivo; hacerlo simplemente implica leer y escribir en la memoria. El archivo en sí, en el disco, es igual que cualquier otro archivo.
Para configurar esto, los procesos usan la
mmap
función. Esto también se puede utilizar para otros fines, como compartir memoria entre procesos.fuente
mv
.mv
simplemente cambian las entradas de directorio, no los inodos (cuando está moviendo archivos en el mismo sistema de archivos).lsof
. No desaparece hasta que el proceso llama a munmap (), o sale (o reemplaza el mapeo por uno diferente usando mmap (MAP_FIXED) ...)Un archivo mapeado en memoria no está (necesariamente) respaldado por la memoria. Puede vivir perfectamente en un disco. En realidad, el lugar donde vive un archivo no es una propiedad del archivo en sí, sino del sistema de archivos en el que reside.
La asignación de un archivo en la memoria es una operación que un proceso puede hacer para cargar una parte del archivo en la memoria. El resultado parece una región regular de memoria, excepto que cuando el proceso lee o escribe en esta región, en realidad lee y escribe en el archivo. Si abre un archivo, lo asigna a la memoria, lo escribe y lo guarda, la modificación se realizará en el archivo, en el disco (si vive en un disco, por supuesto).
Esto se puede utilizar, por ejemplo, cuando se sabe que tiene una gran cantidad de accesos a hacer en un archivo, que no van a ser secuencial, sea la causa puede ser más fácil y más eficiente de hacer las lecturas y escrituras en la memoria que al tema
read
,write
, yllseek
llamadas al sistema. El único problema con este método es que realmente no puede usarlo si varios procesos deben leer o escribir en el archivo simultáneamente. Los resultados serían impredecibles.No conozco ningún comando que pueda decirte si un archivo está asignado actualmente. Sin embargo, puede inspeccionar las asignaciones de un proceso en
/proc/<pid>/maps
(si su sistema lo tiene).Para responder a su segunda pregunta, cuando abre un archivo, incluso si lo mueve en el sistema de archivos, los procesos que lo han abierto aún pueden usarlo. Lo que sucede es que un archivo no depende de sus entradas en los sistemas de archivos. Mientras tenga un archivo abierto, tiene un "identificador", un descriptor de archivo, que le permite leer y escribir en él, incluso si cambia su ruta en el sistema de archivos. Un archivo desaparece solo cuando no tiene entrada en el sistema de archivos y ningún proceso contiene un descriptor de archivo.
fuente
/proc/<pid>/maps
. - Siempre que dicho proceso se desarrolle en un sistema que tiene/proc
que comenzar. OpenBSD no lo hace, y FreeBSD lo está eliminando gradualmente. Además, FreeBSD tiene en/proc/<pid>/map
lugar de/proc/<pid>/maps
.El
lsof
comando le mostrará todos los archivos actualmente en uso por el sistema. La columna "FD" contendrá "mem" si el archivo está mapeado en memoria. Por lo tanto, puede seleccionar la salida de este comando para el nombre de archivo que le interesa.fuente
lsof -ad mem /path/to/file
lsof -ad mem,txt /path/to/file
como los archivos que se están ejecutando también tienen partes de ellos mapeadas en el espacio de direcciones del proceso pero aparecen comotxt
en lalsof
salida.Parece confundir la asignación de memoria con archivos en sistemas de archivos que residen en memoria, junto con otros conceptos como cómo los procesos mantienen el acceso a los archivos incluso cuando se mueven.
Iré pregunta por pregunta para ver si puedo aclarar las cosas.
Apunta a la memoria principal si está en un sistema de archivos que reside en la memoria, como procfs que normalmente está montado en / proc, o sysfs que está en / sys, o tmpfs que a veces está en / tmp.
No. Como dijo stephen-kitt, "mapeo de memoria" se refiere a una forma de acceder a un archivo "mapeándolo" en la memoria principal y trabajando con él allí en lugar de leer y escribir fragmentos a la vez a través de funciones como read () y escribir().
Si lo mueve dentro del mismo sistema de archivos, realmente solo se está moviendo alrededor de una referencia, un inodo de un directorio a otro. Si hay programas que ya tenían este archivo abierto, seguirán accediendo al mismo archivo porque ya tienen el inodo a la mano a través de un descriptor de archivo. Esto es lo que sucedió con el archivo table_name.idb que mencionaste en un comentario.
Wossname ya respondió esto para los archivos mapeados en memoria.
lsof
le dirá qué procesos tienen el archivo mapeado en memoria.Para saber si un archivo está en un sistema de archivos que reside en la memoria, puede usar
df
omount
para enumerar los sistemas de archivos y sus puntos de montaje. Solo necesita saber qué tipos de sistemas de archivos residen en la memoria buscándolos (por ejemplo, en wikipedia).Personalmente, no he usado lammap
función en un programa en C, pero como la entiendo por descremadoman mmap
yinfo mmap
, no hay magia involucrada en mantener la representación en memoria sincronizada. En su forma básica, llamar a mmap copia el contenido del archivo a la memoria ymsync
se utiliza para volver a escribirlo desde la memoria al disco. Si el archivo en el disco cambia, no hay nada en el lugar para detectarlo y modificar automáticamente la representación en memoria en todos los procesos que lo mapearon.EDITAR: Resulta que mmap () en realidad intenta mantener sincronizada la representación en memoria en algunas condiciones. Si el mapa solo se lee, se mantendrá sincronizado incluso cuando otros procesos escriban en el archivo. Si se escribe en (asignando a la región de memoria), lo que sucede depende de cuál de los indicadores MAP_SHARED o MAP_PRIVATE aparentemente obligatorios se proporciona a mmap (). Si se proporciona MAP_PRIVATE, el mapa se bifurca desde la representación en disco y deja de estar sincronizado hasta que use msync (). Si se proporciona MAP_SHARED, las actualizaciones se hacen visibles para otros procesos que tienen el archivo asignado, así como (aunque esto no es necesariamente inmediato) la representación en el disco.
Acabo de abrir vim en un archivo existente
e
y ejecuté el comando:w
, mientras loinotifywait -m .
ejecutaba en otra terminal. Entre algunas partes extrañas, esta es la parte importante que obtuveinotifywait
.Vim crea un nuevo archivo y elimina el anterior. Por qué hace esto en lugar de modificar el archivo está más allá del alcance de esta pregunta, pero el punto es que este es un archivo nuevo y, por lo tanto, tiene un nuevo inodo.
Ahora, ¿qué quieres decir con otros procesos que usan este archivo? Si te refieres a procesos que tenían el archivo abierto mientras estabas haciendo esto, no, no verán los cambios. Esto se debe a que, aunque abrieron un archivo con la misma ruta, no son el mismo archivo. Si te refieres a procesos que pueden abrir el archivo después de hacer esto, entonces sí, verán los cambios. Abrirán el nuevo archivo que creaste.
Es importante tener en cuenta que aunque los programas pueden tener un archivo abierto en la interfaz de usuario, eso no significa necesariamente que mantengan el archivo abierto en el proceso. Vim es un ejemplo de esto, como se muestra arriba.
fuente
write
función es cambiar los datos del archivo. Eso puede o no significar cambiar el contenido del disco, pero sea lo que sea lo que implique, es responsabilidad del sistema de archivos hacerlo bien. En este caso, implicaría modificar la página de memoria asignada y marcarla como sucia.