GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué malloc() llama a mmap() y brk() indistintamente?

mmap (cuando se usa con MAP_ANONYMOUS ) asigna una porción de RAM que se puede colocar en cualquier lugar dentro del espacio de direcciones virtuales del proceso y que se puede desasignar más tarde (con munmap ) independientemente de todas las demás asignaciones.

brk cambia la dirección final de una única "arena" contigua de espacio de direcciones virtuales:si esta dirección aumenta, asigna más memoria a la arena, y si disminuye, desasigna la memoria al final de la arena. Por lo tanto, la memoria asignada con brk solo se puede devolver al sistema operativo cuando un rango continuo de direcciones al final de la arena ya no es necesario para el proceso.

Usando brk para asignaciones pequeñas, y mmap para asignaciones grandes, es una heurística basada en la suposición de que es más probable que todas las asignaciones pequeñas tengan la misma vida útil, mientras que es más probable que las asignaciones grandes tengan una vida útil que no está correlacionada con la vida útil de otras asignaciones. Por lo tanto, las asignaciones grandes usan la primitiva del sistema que les permite desasignarse independientemente de cualquier otra cosa, y las asignaciones pequeñas usan la primitiva que no lo permite.

Esta heurística no es muy fiable. La generación actual de malloc implementaciones, si no recuerdo mal, se ha rendido por completo en brk y usa mmap para todo. El malloc La implementación que sospecho que está viendo (la que está en la biblioteca GNU C, según sus etiquetas) es muy antigua y se sigue utilizando principalmente porque nadie es lo suficientemente valiente como para correr el riesgo de cambiarla por algo más nuevo que probablemente pero no ciertamente ser mejor.


entonces, ¿por qué malloc llama a mmap cuando se trata de asignar un gran tamaño de memoria?

La respuesta corta es para mejorar la eficiencia en las implementaciones más recientes de Linux y los algoritmos de asignación de memoria actualizados que vienen con ellas. Pero tenga en cuenta que este es un tema muy dependiente de la implementación, y los porqués y razones variarían mucho para las diferentes épocas y sabores del sistema operativo Linux específico que se está discutiendo.

Aquí hay un artículo bastante reciente sobre las partes de bajo nivel mmap() y brk() jugar en la asignación de memoria de Linux. Y, un artículo de Linux Journal no tan reciente, pero aún relevante, que incluye algo de contenido que es muy pertinente para el tema aquí, incluido este:

Para solicitudes muy grandes, malloc() usa la llamada al sistema mmap() para encontrar espacio de memoria direccionable. Este proceso ayuda a reducir los efectos negativos de la fragmentación de la memoria cuando se liberan grandes bloques de memoria, pero están bloqueados por bloques más pequeños, asignados más recientemente, que se encuentran entre ellos y el final del espacio asignado. En este caso, de hecho, si el bloque hubiera sido asignado con brk(), habría permanecido inutilizable por el sistema incluso si el proceso lo liberara.
(énfasis mío)

Con respecto a brk() :
por cierto, "...mmap() no existía en las primeras versiones de Unix. brk() era la única forma de aumentar el tamaño del segmento de datos del proceso en ese momento. La primera versión de Unix con mmap() fue SunOS a mediados de los 80, la primera versión de código abierto fue BSD-Reno en 1990. ". Desde entonces, la implementación moderna de los algoritmos de asignación de memoria se ha refactorizado con muchas mejoras, lo que reduce en gran medida la necesidad de que incluyan el uso de brk() .


Linux
  1. ¿Qué devuelve malloc(0)?

  2. ¿Qué hace la llamada al sistema brk()?

  3. ¿Qué es una GPU Matrox y por qué el servidor UNIX de mi universidad tiene una?

  4. ¿Por qué mi sistema muestra solo 3,2 GiB de RAM cuando definitivamente tengo 4,0 GiB?

  5. ¿Por qué debian y ubuntu tienen por defecto el nivel de ejecución 2?

¿Qué es un servidor Linux y por qué su negocio necesita uno?

¿Qué es el comando Grep en Linux? ¿Por qué se usa y cómo funciona?

Supervisión y gestión de la memoria

¿Por qué sed falla con los caracteres internacionales y cómo solucionarlo?

¿Por qué mmap() es más rápido que IO secuencial?

¿Cuándo se maneja una señal y por qué alguna información se congela?