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?
Respuestas:
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) .
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
,htop
ocat /proc/self/maps
, ocat /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.
fuente
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
awk
lo 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
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 delfor
bucle, este será leer el conjunto defile
en la memoria (en la memoria utilizada por la cáscara de ejecutar elfor
bucle). Esto es un poco tonto y también poco elegante. En cambio, uno debería hacerEsto procesará
file
lí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
awk
programa 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íazcat
ogzip -d -c
, lo que, dado quegzip
no 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.
fuente
awk
,{ a[i++] = $0 }
agregaría todas las líneas del archivo de entrada a la matriza
. Es posible que también desee buscar la función Cmmap()
, pero su uso puede estar un poco fuera de tema aquí.sed
,awk
y 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.sed
solo 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á ejecutandosed
en 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_cacheNo. 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).
fuente