¿Los archivos abiertos por procesos se cargan en la RAM?

24

Los comandos , por ejemplo sed, son programas y los programas son lógicos codificados dentro de un archivo y estos archivos están en algún lugar del disco duro. Sin embargo, cuando se ejecutan comandos, una copia de sus archivos del disco duro se coloca en la RAM , donde cobran vida y pueden hacer cosas y se denominan procesos .

Los procesos pueden hacer uso de otros archivos, leerlos o escribirlos, y si lo hacen, esos archivos se denominan archivos abiertos. Hay un comando para listar todos los archivos abiertos por todos los procesos en ejecución: lsof.

Bien, entonces me pregunto si la doble vida de un comando, uno en el disco duro y el otro en la RAM también es cierto para otro tipo de archivos, por ejemplo, aquellos que no tienen lógica programada, pero son simplemente contenedores para datos.

Mi suposición es que los archivos abiertos por procesos también se cargan en la RAM. No sé si es verdad, es solo una intuición.

Por favor, ¿podría alguien darle sentido?

Sharkant
fuente

Respuestas:

27

Sin embargo, cuando se ejecutan comandos, una copia de sus archivos del disco duro se coloca en la RAM,

Esto está mal (en general). Cuando se ejecuta un programa (a través de execve (2) ...) el proceso (ejecutar ese programa) está cambiando su espacio de direcciones virtuales y el núcleo está reconfigurando la MMU para ese propósito. Lea también sobre memoria virtual . Tenga en cuenta que los programas de aplicación pueden cambiar su espacio de direcciones virtuales usando mmap (2) y munmap& mprotect (2) , también utilizado por el enlazador dinámico (consulte ld-linux (8) ). Ver también madvise (2) y posix_fadvise (2) y mlock (2) .

Las fallas futuras de la página serán procesadas por el kernel para cargar (perezosamente) páginas del archivo ejecutable. Lea también sobre la paliza .

El núcleo mantiene una gran caché de página . Lea también sobre copia en escritura . Ver también readahead (2) .

Bien, entonces me pregunto si la doble vida de un comando, uno en el disco duro y el otro en la RAM también es cierto para otro tipo de archivos, por ejemplo, aquellos que no tienen lógica programada, pero son simplemente contenedores para datos.

Para llamadas al sistema como read (2) & write (2), también se usa el caché de página. Si los datos a leer se encuentran en él, no se realizará ninguna E / S de disco. Si se necesita un disco IO, es muy probable que los datos leídos se pongan en la memoria caché de la página. Entonces, en la práctica, si ejecuta el mismo comando dos veces, podría suceder que no se realice ninguna E / S física en el disco la segunda vez (si tiene un disco duro giratorio antiguo, no un SSD), puede escuchar eso; o observe cuidadosamente el LED de su disco duro).

Recomiendo leer un libro como Sistemas operativos: tres piezas fáciles (descargables gratuitamente, un archivo PDF por capítulo) que explica todo esto.

Véase también Linux comió mi RAM y ejecutar comandos como xosview, top, htopo cat /proc/self/maps, o cat /proc/$$/maps(ver proc (5) ).

PD. Me estoy centrando en Linux, pero otros sistemas operativos también tienen memoria virtual y caché de páginas.

Basile Starynkevitch
fuente
35

No, un archivo no se lee automáticamente en la memoria abriéndolo. Eso sería terriblemente ineficiente. sed, por ejemplo, lee su entrada línea por línea, al igual que muchas otras herramientas de Unix. Rara vez tiene que mantener más que la línea actual en la memoria.

Con awklo mismo. Lee un registro a la vez, que por defecto es una línea. Si almacena partes de los datos de entrada en variables, eso será adicional, por supuesto 1 .

Algunas personas tienen la costumbre de hacer cosas como

for line in $(cat file); do ...; done

Puesto que la cáscara se tenga que ampliar la $(cat file)sustitución de orden completamente antes de ejecutar incluso la primera iteración del forbucle, este será leer el conjunto de fileen la memoria (en la memoria utilizada por la cáscara de ejecutar el forbucle). Esto es un poco tonto y también poco elegante. En cambio, uno debería hacer

while IFS= read -r line; do ...; done <file

Esto procesará filelínea por línea (pero lea Entendiendo "IFS = read -r line" ).

Sin embargo, rara vez se necesita procesar archivos línea por línea en el shell, ya que la mayoría de las utilidades están orientadas a la línea de todos modos (consulte ¿Por qué usar un bucle de shell para procesar texto se considera una mala práctica? ).

Estoy trabajando en bioinformática y, al procesar grandes cantidades de datos genómicos, no podría hacer mucho a menos que solo mantuviera los bits de datos que eran absolutamente necesarios en la memoria. Por ejemplo, cuando necesito eliminar los bits de datos que podrían usarse para identificar individuos de un conjunto de datos de 1 terabyte que contiene variantes de ADN en un archivo VCF (porque ese tipo de datos no puede hacerse público), lo hago línea por línea. procesamiento con un awkprograma simple (esto es posible ya que el formato VCF está orientado a líneas). ¡ No leo el archivo en la memoria, lo proceso allí y lo vuelvo a escribir! Si el archivo se comprimiera, lo alimentaría zcato gzip -d -c, lo que, dado que gzipno procesa los datos, tampoco leería todo el archivo en la memoria.

Incluso con formatos de archivo que no están orientados a la línea, como JSON o XML, existen analizadores de flujo que permiten procesar grandes archivos sin almacenarlo todo en la RAM.

Con los ejecutables, es un poco más complicado ya que las bibliotecas compartidas pueden cargarse a pedido y / o compartirse entre procesos (consulte Carga de bibliotecas compartidas y uso de RAM , por ejemplo).

El almacenamiento en caché es algo que no he mencionado aquí. Esta es la acción de usar RAM para contener datos de acceso frecuente. El sistema operativo puede almacenar en caché archivos más pequeños (por ejemplo, ejecutables) con la esperanza de que el usuario haga muchas referencias a ellos. Además de la primera lectura del archivo, los accesos posteriores se realizarán en la RAM en lugar de en el disco. El almacenamiento en caché, como el almacenamiento en búfer de entrada y salida, generalmente es en gran medida transparente para el usuario y la cantidad de memoria utilizada para almacenar en caché puede cambiar dinámicamente dependiendo de la cantidad de RAM asignada por las aplicaciones, etc.


1 Técnicamente, la mayoría de los programas probablemente leen una porción de los datos de entrada a la vez, ya sea utilizando el almacenamiento en búfer explícito o implícitamente a través del almacenamiento en búfer que hacen las bibliotecas de E / S estándar, y luego presentan esa porción en línea al código del usuario. Es mucho más eficiente leer un múltiplo del tamaño de bloque del disco que, por ejemplo, un carácter a la vez. Sin embargo, este tamaño de fragmento rara vez será mayor que un puñado de kilobytes.

Kusalananda
fuente
usted dijo, es posible cargar bibliotecas compartidas en RAM, ¿también es posible cargar un archivo normal, que contiene solo datos en RAM, incluso si no tuviera sentido?
Sharkant
1
@harkant Por supuesto. Eso es solo una cuestión de agregar datos a una variable (o matriz, o hash, o cualquier estructura de datos que proporcione el idioma en cuestión) hasta que se haya almacenado todo el archivo. Con awk, { a[i++] = $0 }agregaría todas las líneas del archivo de entrada a la matriz a. Es posible que también desee buscar la función C mmap(), pero su uso puede estar un poco fuera de tema aquí.
Kusalananda
66
sed, awky otros programas orientados a líneas no leen una línea a la vez en la memoria, porque los archivos de texto sin formato no contienen un índice de línea, y las API del sistema de archivos y el hardware de almacenamiento de bajo nivel leen uno o más "sectores" (generalmente 512 o 1024 bytes) a la vez. Me sorprendería si el sistema operativo leyera menos de 8 KB en la memoria antes de que se procesara la primera línea.
Russell Borogove
55
Aunque una utilidad como sedsolo leerá una línea a la vez en la memoria, vale la pena mencionar que el sistema operativo usará RAM libre para almacenar en caché los archivos para que se pueda acceder a ellos rápidamente. Si está ejecutando seden un archivo más pequeño, es posible que el sistema operativo almacene en caché todo el archivo en la memoria y la operación se realizará por completo en la RAM. Ver: en.wikipedia.org/wiki/Page_cache
Sean Dawson
55
@sharkant Es útil tener un archivo completamente accesible en la memoria (vea la otra respuesta, mmap es la llamada al sistema de palabras clave aquí). Por ejemplo, un sistema de base de datos generalmente querría tener, para facilitar y acelerar el acceso, toda la base de datos o al menos algunos de los índices asignados a la memoria. Esto no significa necesariamente que todo esté realmente en la memoria. El sistema operativo es libre de "pretender" que el archivo está en la memoria. Le dice a la aplicación "aquí, en este rango de memoria está su archivo", y solo una vez que se realiza una lectura (al igual que cuando se ha intercambiado el proceso), los datos se leen realmente.
Jonas Schäfer
5

No. Aunque tener gigas de RAM en estos días es fantástico, hubo un momento en que la RAM era un recurso muy limitado (aprendí a programar en un VAX 11/750 con 2MB de RAM) y lo único en la RAM era páginas ejecutables y de datos activas de procesos activos y datos de archivo que estaban en la memoria caché del búfer.
La memoria caché del búfer se vació y las páginas de datos se intercambiaron. Y con frecuencia a veces. Las páginas ejecutables de solo lectura se sobrescribieron y las tablas de páginas se marcaron, de modo que si el programa tocaba esas páginas nuevamente, se enviaban desde el sistema de archivos. Los datos se enviaron por intercambio. Como se señaló anteriormente, la biblioteca STDIO introdujo datos en bloques y los obtuvo el programa según sea necesario: fgetc, fgets, fread, etc. Con mmap, un archivo podría asignarse al espacio de direcciones de un proceso, como se hace con objetos de biblioteca compartida o incluso archivos normales. Sí, es posible que tenga cierto grado de control si está en RAM o no (mlock), pero solo llega hasta cierto punto (consulte la sección del código de error de mlock).

Roger L.
fuente
1
La afirmación "su RAM será demasiado pequeña para sus archivos" es cierta ahora como en los viejos tiempos de VAX.
Federico Poloni
1
@Federico_Poloni No es tan cierto hoy. En mi último empleador teníamos una PC de clase de estación de trabajo con 1Tb de RAM y solo 0.5Tb de disco duro. (Clase de problema: entradas pequeñas, salidas medianas, matrices grandes de acceso aleatorio durante el cálculo).
nigel222