Documentos de Académico
Documentos de Profesional
Documentos de Cultura
1
_________________________________________________________________________
CONTENIDO
_________________________________________________________________________
marcos dentro de la memoria virtual. El poder cargar solo una vez en memoria física un
mismo segmento de memoria para varios procesos soluciona los posibles problemas que
todas las variables del programa, cadenas, arreglos y demás datos” está conformado por
manera: “esta porción del espacio de direcciones virtuales de un programa contiene las
llamada BSS (Block Started by Symbol) por una referencia histórica, contiene el resto de
física.
La sección del montículo dentro del segmento de datos y el segmento de pila, conocidos
también como heap y stack respectivamente, cumplen una función similar: contener datos
su programa.
La principal diferencia entre estos dos segmentos está en el tipo de variables y datos
que almacenan: mientras que el heap contiene variables, librerías y módulos globales y
estáticos, es decir que son accesibles en todo momento durante la ejecución del programa,
el stack contiene los argumentos, las variables y valores de retorno locales de la función
Mapeo de Memoria
archivos en memoria. Tanenbaum (2009) define el mapeo de memoria como “la asignación
pueda leer y escribir en el archivo como si fuera un arreglo de bytes en la memoria”. Este
principio solo se encuentra asociado a la memoria virtual del proceso y solo es cargada en
Una de las ventajas que tiene el mapeo de memoria es que, recordando que cada marco
memoria física permite que el acceso a estos archivos se pueda compartir entre los
La Memoria Principal es un recurso valioso que se debe asignar y compartir entre los
procesos activos. Mantener en memoria la mayor cantidad posible de procesos, permite
hacer un uso eficiente del procesador y de los servicios de E/S. El micro no tendrá tiempos
ociosos pues siempre habrá un proceso para ejecutar. Por ello, una de las tareas más
importantes y complejas de un sistema operativo es la gestión de la memoria. El sistema
operativo Linux utiliza memoria virtual y para su administración, las técnicas de intercambio
y paginación por demanda. Para ello, se vale de las siguientes estructuras de datos:
· Descriptor de bloques de disco: describe el bloque de disco que contiene una página
determinada.
Es importante aclarar que, aunque los comandos y las llamadas al sistema pueden tener el
mismo nombre, no hacen lo mismo. En general, los comandos en Linux se utilizan para
interactuar con el sistema operativo y obtener información sobre él, mientras que las
llamadas al sistema se utilizan para realizar operaciones en el sistema operativo, como la
gestión de procesos y memoria.
Las llamadas al sistema son la forma en que los programas de usuario interactúan con el
kernel del S.O. Las llamadas al sistema permiten que los programas de usuario soliciten
servicios del kernel, como reservar memoria, crear procesos, gestionar archivos y la
comunicación con dispositivos de hardware. Cuando un programa de usuario realiza una
llamada al sistema, se produce un cambio de modo de usuario a modo kernel. El modo
usuario es el modo en el que se ejecuta la mayoría de los programas de usuario, y el modo
kernel es el modo privilegiado en el que se ejecuta el kernel del sistema operativo.
Durante una llamada al sistema, el programa de usuario pasa el control al kernel, que
realiza la tarea solicitada. Una vez que se completa la tarea, el control se devuelve al
programa de usuario, y se produce un cambio de vuelta al modo de usuario. Las llamadas al
sistema se realizan a través de funciones de biblioteca en un programa de usuario.
Las llamadas al sistema de administración de memoria son una interfaz proporcionada por
el sistema operativo que permiten a los procesos solicitar y liberar memoria durante su
ejecución. Estas llamadas al sistema son críticas para la administración adecuada de la
memoria en un sistema operativo.
Del mismo modo, cuando un programa necesita liberar la memoria que se ha asignado
previamente, puede llamar a la función de biblioteca "free". Esta función devuelve la
memoria al sistema operativo para su reutilización.
Las llamadas al sistema de administración de memoria más comunes son mmap, munmap,
brk, sbrk, malloc y free. Cada llamada al sistema realiza una tarea relacionada específica
con la liberación y liberación de memoria.
—------------
Las llamadas al sistema que acabamos de mencionar son las más comunes, pero también
mencionaremos algunas más:
● mlock: Esta llamada al sistema se utiliza para bloquear una página o un rango de
páginas de la memoria en la RAM para que no puedan ser intercambiadas con la
memoria secundaria (disco). Esta llamada al sistema es útil en situaciones en las
que se requiere un acceso rápido y constante a datos específicos, como en
aplicaciones de bases de datos.
● madvise: Esta llamada al sistema se utiliza para indicar al kernel cómo debe
manejar una región de memoria en particular. Por ejemplo, se puede especificar que
una página de memoria debe ser eliminada de la memoria caché o que se debe
liberar una región de memoria para su uso posterior. Esta llamada al sistema es útil
en situaciones en las que se desea un control más preciso sobre el uso de la
memoria.
Algo de lo que hay que tener mucho cuidado es sobre el mal uso de las llamadas al sistema
para administrar la memoria, esto puede tener graves consecuencias para el rendimiento y
la estabilidad del sistema. A continuación, mencionaremos algunas de las consecuencias
del mal usos de estas llamadas al sistema:
10
● Rendimiento deficiente: Si se asigna y libera memoria dinámicamente de manera
ineficiente, el rendimiento del sistema puede disminuir significativamente. Esto se
debe a que la protección y liberación ineficiente de memoria puede provocar una
fragmentación de la memoria, lo que dificulta la protección de memoria contigua para
procesos que la requieren. Esto puede llevar a cabo una disminución general del
rendimiento del sistema.
11
acceder fácilmente a la memoria virtual. El interior del espacio de direcciones virtuales se
divide en Espacio de kernel y espacio de usuario, los procesadores con diferentes
longitudes de palabra tienen diferentes espacios de direcciones, como ejemplo tenemos a
los sistemas más comunes de 32 y 64 bits como se muestra en la figura.
A continuación, se va a explicar la implementación de varios mecanismos en el Kernel de
Linux que son los responsables de administrar la memoria.
En el hardware x86, ciertos dispositivos pueden realizar operaciones de DMA sólo en los
primeros 16 MB del espacio de direcciones.Además, el hardware no puede asignar en
forma directa las direcciones de memoria por encima de 896 MB, por lo que
ZONE_HIGHMEM se encuentra arriba de esta marca. ZONE_NORMAL es cualquier
ubicación entre las dos zonas anteriores. Por lo tanto, en las plataformas (x86) los primeros
12
896 MB del espacio de direcciones de Linux se asignan en forma directa, mientras que los
128 MB restantes del espacio de direcciones del kernel se utilizan para acceder a las
regiones de la memoria superior. El kernel mantiene una estructura de zona para cada una
de las tres zonas y puede realizar asignaciones de memoria para las tres zonas por
separado.
En las de 64 bits, la zona ZONE_DMA corresponde a las direcciones físicas de 0 a 16 MB.
La zona ZONE_DMA32 existe únicamente en las plataformas de 64 bits de 16 MB a 4 GB.
La zona ZONE_NORMAL es toda la RAM disponible más allá de 4 GB. La memoria
principal en Linux está dividida en tres partes: las dos primeras partes (kernel y mapa de
memoria) están residentes (fijadas) en la memoria y el resto de la memoria se divide en
marcos de página. El kernel mantiene un mapa de la memoria principal.
Linux mantiene un arreglo de descriptores de páginas, de tipo página para cada marco de
página física en el sistema, conocido como mem_map. Cada descriptor de página
contiene un apuntador al espacio de direcciones al que pertenece, en caso de que la página
no esté libre, un par de apuntadores que le permitan formar listas doblemente enlazadas
con otros descriptores, por ejemplo para mantener juntos todos los marcos de página libres,
y unos cuantos campos más. El tamaño del descriptor de página es de 32 bytes, por lo que
el mem_map completo puede consumir menos de 1% de la memoria física (para un marco
de página de 4 KB).
Linux, también, mantiene un descriptor de zona, que contiene información sobre el uso de la
memoria dentro de cada zona, como el número de páginas activas e inactivas. Este
descriptor contiene un arreglo de áreas libres. El i-ésimo elemento en este arreglo identifica
el primer descriptor de página del primer bloque de 2i páginas libres. Como puede haber
varios bloques, Linux utiliza el par de apuntadores de descriptores de página en cada
elemento page para enlazarlos entre sí. Esta información se utiliza en las operaciones de
asignación de memoria que Linux proporciona.
En las plataformas UMA, Linux describe toda la memoria a través de un descriptor de nodo.
Los primeros bits dentro de cada descriptor de página se utilizan para identificar el nodo y la
13
zona a los que pertenece el marco de página.
Linux utiliza un esquema de paginación de cuatro niveles. Cada dirección virtual se divide
en cinco campos, como se puede observar en la Figura X. Los campos de los directorios se
utilizan como un índice, del cual hay uno para cada proceso. El valor que contiene apunta a
un nuevo directorio del siguiente nivel, que se vuelve a indexar. La entrada seleccionada en
el directorio de la página intermedia apunta a la tabla de páginas final, que se indexa
mediante el campo de página de la dirección virtual.La entrada que se encuentra aquí
apunta a la página requerida.En síntesis, las primeras 4 entradas se utilizan para
seleccionar páginas y el último índice representa el desplazamiento dentro de la página.
14
Figura X. Linux utiliza una tabla de páginas de cuatro niveles.
Por otro lado, la memoria física se utiliza para varios fines. El kernel en sí está fijo en su
totalidad; ninguna parte de él se página hacia fuera de la memoria. El resto de la memoria
está disponible para las páginas de usuario, la caché de paginación y otros fines.
Linux también acepta los módulos que se cargan en forma dinámica los cuales pueden
tener un tamaño arbitrario y a cada uno se les debe asignar una pieza contigua de memoria
del kernel, por esto Linux, administra la memoria física de forma tal que pueda adquirir una
pieza de memoria de un tamaño que se arbitrario cuando lo desee y para esto utiliza el
algoritmo de colegas (buddy algorithm), el cual será analizado a continuación.
15
efectuarse en el bloque de la parte baja de la memoria, ahora se tienen dos colegas más de
16 páginas cada uno. Se vuelve a efectuar una partición más del bloque de memoria de 16
páginas inferior y se obtienen dos bloques de 8 páginas, es en esta instancia en que se
hace efectiva la asignación. Posteriormente se hace un nueva solicitud de 8 páginas de
memoria, que como ya se tiene un bloque de tal tamaño la asignación ahora es directa. La
próxima petición de memoria necesita 4 páginas de memoria, por lo que el bloque inferior
libre de 16 páginas se divide sucesivamente hasta obtener bloques del tamaño requerido y
se efectúa la correspondiente asignación. En la siguiente instancia uno de los bloques de 8
páginas anteriormente asignado se libera, y a continuación se libera su colega también de 8
páginas, al provenir estos bloques de una misma división se procede con la combinación de
ambos para formar el bloque de 16 páginas original. A este proceso se le conoce como
fusión.
16
Inconvenientes
El principal inconveniente del sistema de colegas es la fragmentación interna, ya que se
adquiere un bloque de memoria más grande y luego se requiere. Por ejemplo, si se realiza
una solicitud de 36 páginas, sólo puede satisfacerse con un segmento de 64 páginas y se
desperdicia la memoria restante.
17
Figura X - ASIGNADOR DE LOSAS (Slab Allocator)
El algoritmo de asignación de losas usa cachés para almacenar objetos del kernel. Cuando
se crea una caché, una serie de objetos que inicialmente están marcados como libres se
asignan a la caché. La cantidad de objetos en la caché depende del tamaño de la losa
asociada.
En Linux, una losa puede estar en uno de tres estados posibles:
● Llena: todos los objetos de la losa están marcados como usados.
● Vacío: todos los objetos de la losa están marcados como libres.
● Parcial: la losa consta de ambos.
El asignador de losa primero intenta satisfacer la solicitud con un objeto libre en una losa
parcial. Si no existe, se asigna un objeto libre desde una losa vacía. Si no hay losas vacías
disponibles, se asigna una nueva losa de páginas físicas contiguas y se asigna a una
caché.
Beneficios de la asignación de losas
● No se desperdicia memoria debido a la fragmentación porque cada estructura de datos
del kernel única tiene una caché asociada.
● La solicitud de memoria se puede satisfacer rápidamente.
● El esquema de asignación de losas es particularmente efectivo para administrar cuando
los objetos se asignan o desasignan con frecuencia. El acto de asignar y liberar memoria
puede ser un proceso que requiere mucho tiempo. Sin embargo, los objetos se crean de
antemano y, por lo tanto, se pueden asignar rápidamente desde la caché. Cuando el kernel
Acuña, Avila, Manzano, Martinez, Segovia
18
ha terminado con un objeto y lo libera, se marca como libre y regresa a su caché, lo que lo
hace disponible inmediatamente para una solicitud posterior del kernel.
2.3.3 Representación del espacio de direcciones virtuales
El espacio de direcciones virtuales está dividido en áreas o secciones homogéneas,
contiguas y alineadas por páginas. Es decir, cada área consiste en una serie de páginas
consecutivas (una detrás de otra) que cuentan con las mismas propiedades tanto de
protección como de paginación.
El interior del espacio de direcciones virtuales se divide en espacio de kernel (de color
morado), y espacio de usuario (de color azul). A su vez, este espacio de usuario se puede
subdividir en:
1. Sección de solo lectura (incluye código y constantes).
2. Segmento de datos (incluye las variables globales, etc.).
3. El montón (comienza desde la dirección baja y crece hacia arriba e incluye la memoria
asignada dinámicamente).
4. La sección de mapeo de archivos (comienza desde la dirección alta y crece hacia
abajo e incluidas las bibliotecas dinámicas, la memoria compartida, etc.).
5. Pila (el tamaño de la pila es fijo, y generalmente de 8 MB, incluye el contexto de las
variables locales y las llamadas a funciones).
19
Puede haber hoyos en el espacio de direcciones virtuales entre las áreas, por lo tanto,
cualquier referencia de memoria a un hoyo producirá un fallo de página fatal. El tamaño de
página es fijo.
Cada área o segmento se describe en el kernel mediante una entrada vm_area_struct.
Todas las entradas vm_area_struct se enlazan entre sí en una lista ordenada por dirección
virtual, de tal forma que se puedan encontrar todas las páginas. Cuando la lista se hace
muy grande (más de 32 entradas), se crea un árbol para agilizar la búsqueda.
La entrada vm_area_struct se encarga de listar las distintas propiedades del área, y éstas,
incluyen el modo de protección (por ejemplo, sólo lectura o lectura/escritura), si se
encuentra fijada en la memoria, y en qué dirección aumenta su tamaño (hacia arriba para
los segmentos de datos, hacia abajo para las pilas). Además, también registra si el área
tiene asignado un almacenamiento de respaldo en el disco, y de ser así, cuál es su
ubicación.
Existe un descriptor de memoria de nivel superior denominado mm_struct, el cual se
encarga de recopilar información sobre todas las áreas de memoria virtual que pertenecen a
un espacio de direcciones, información sobre los distintos segmentos (texto, datos, pila),
información sobre los usuarios que comparten este espacio de direcciones, etc. Se puede
acceder a todos los elementos vm_area_struct de un espacio de direcciones por medio de
su descriptor de memoria de dos formas:
1. Listas enlazadas: se organizan en listas enlazadas ordenadas por direcciones de
memoria virtual. Este método es útil cuando se requiere el acceso a todas las áreas de
memoria virtual, o cuando el kernel busca asignar una región de memoria virtual de un
tamaño específico.
2. Árbol binario rojo-negro: es una estructura de datos optimizada para búsquedas
rápidas. Este método se utiliza cuando hay que acceder a una memoria virtual específica. Al
permitir el acceso a los elementos del espacio de direcciones del proceso por medio de
estos dos métodos, Linux utiliza más estado por proceso, pero permite que las distintas
operaciones del kernel utilicen el método de acceso más eficiente para la tarea que se vaya
a realizar.
20
2.4 Paginación
Las direcciones generadas por la CPU están divididas en dos partes, el “número de página
(d)” y el “desplazamiento de página (d)”. El sistema mantiene una estructura de datos
llamada Tabla de Páginas la cual almacena los números de páginas a manera de índice
hacia la memoria física, esta dirección es combinada con el desplazamiento de página para
poder localizar la dirección de la memoria física.
21
El tamaño de página es normalmente un múltiplo de 2, esto facilita el hardware de la
conversión y suma de las direcciones.
Con este esquema no existe fragmentación externa, pero sigue existiendo la fragmentación
interna, por ejemplo, si el tamaño de un proceso no coincide exactamente con el tamaño de
la suma de los marcos asignados entonces el último marco podría no quedar
completamente lleno, en el peor de los casos el tamaño de un proceso podría ser n páginas
más un byte requiriendo así n+1 marcos, dando como resultado una fragmentación interna
de prácticamente un marco.
22
2.4.1 Páginas compartidas
El término código reentrante o código puro es código que nunca cambia durante la
ejecución, entonces dos o más procesos pueden compartir y ejecutar código de una página
al mismo tiempo. Cada proceso pensara que la pagina pertenece a su espacio de
direcciones lógico mientras que en realidad físicamente los procesos estarán haciendo uso
de un mismo marco.
Conclusión
Para concluir este informe se entiende que:
23