¿Cómo se implementa malloc() internamente? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

¿Puede alguien explicar cómo funciona malloc() internamente?

A veces he hecho strace program y veo un montón de sbrk llamadas al sistema, haciendo man sbrk habla de que se utiliza en malloc() pero no mucho más.

Author: orlp, 2010-08-13

3 answers

La llamada al sistema sbrk mueve el "borde" del segmento de datos. Esto significa que mueve un borde de un área en la que un programa puede leer/escribir datos (dejándolo crecer o reducirse, aunque AFAIK no malloc realmente devuelve los segmentos de memoria al núcleo con ese método). Aparte de eso, también está mmap que se usa para asignar archivos a la memoria, pero también se usa para asignar memoria (si necesita asignar memoria compartida, mmap es cómo lo hace).

Así que tienes dos métodos para obtener más memoria del núcleo: sbrk y mmap. Hay varias estrategias sobre cómo organizar la memoria que tienes del núcleo.

Una manera ingenua es particionarlo en zonas, a menudo llamadas "cubos", que están dedicadas a ciertos tamaños de estructura. Por ejemplo, una implementación malloc podría crear buckets para estructuras de 16, 64, 256 y 1024 bytes. Si pides malloc que te dé memoria de un tamaño dado redondea ese número hasta el siguiente tamaño de cubo y luego te da un elemento de ese cubo. Si necesita un área mayor malloc podría usar mmap para asignar directamente con el núcleo. Si el cubo de un cierto tamaño está vacío malloc podría usar sbrk para obtener más espacio para un nuevo cubo.

Hay varios diseños malloc y es probable que no haya una manera verdadera de implementar malloc ya que necesita hacer un compromiso entre la velocidad, la sobrecarga y evitar la fragmentación/efectividad espacial. Por ejemplo, si un bucket se queda sin elementos, una implementación podría obtener un elemento de un cubo más grande, divídelo y añádelo al cubo que se quedó sin elementos. Esto sería bastante eficiente en el espacio, pero no sería posible con todos los diseños. Si usted acaba de obtener otro cubo a través de sbrk/mmap eso podría ser más rápido e incluso más fácil, pero no tan eficiente en el espacio. Además, el diseño debe, por supuesto, tener en cuenta que "free" necesita hacer espacio disponible para malloc de nuevo de alguna manera. No se reparte la memoria sin reutilizarla.

Si estás interesado, el OpenSER/Kamailio El proxy SIP tiene dos implementaciones malloc (necesitan las suyas porque hacen un uso intensivo de la memoria compartida y el sistema malloc no admite memoria compartida). Véase: https://github.com/OpenSIPS/opensips/tree/master/mem

Entonces también podrías echar un vistazo a la implementación de GNU libc malloc , pero esa es muy complicada, IIRC.

 91
Author: DarkDust,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-11 08:40:07

Simplistamente malloc y trabajo libre como este:

Malloc proporciona acceso al montón de un proceso. El heap es una construcción en la biblioteca C core (comúnmente libc) que permite a los objetos obtener acceso exclusivo a algún espacio en el heap del proceso.

Cada asignación en el montón se llama una celda de montón. Normalmente consiste en un encabezado que contiene información sobre el tamaño de la celda, así como un puntero a la siguiente celda del montón. Esto hace que un montón efectivamente un lista.

Cuando se inicia un proceso, el montón contiene una sola celda que contiene todo el espacio de montón asignado al inicio. Esta celda existe en la lista libre del montón.

Cuando se llama a malloc, la memoria se toma de la celda de montón grande, que es devuelta por malloc. El resto se forma en una nueva celda de montón que consiste en todo el resto de la memoria.

Cuando uno libera memoria, la celda del montón se agrega al final de la lista libre del montón. Los malloc posteriores recorren la lista gratuita buscando una celda de tamaño adecuado.

Como es de esperar, el montón puede fragmentarse y el administrador de montones puede de vez en cuando intentar fusionar celdas de montón adyacentes.

Cuando no queda memoria en la lista libre para una asignación deseada, malloc llama a brk o sbrk, que son las llamadas al sistema que solicitan más páginas de memoria del sistema operativo.

Ahora hay algunas modificaciones para optimizar las operaciones de montón.

  • Para grandes asignaciones de memoria (normalmente > 512 bytes, el montón gerente puede ir directamente al sistema operativo y asignar una página de memoria completa.
  • El montón puede especificar un tamaño mínimo de asignación para evitar grandes cantidades de fragmentación.
  • El montón también puede dividirse en contenedores uno para asignaciones pequeñas y otro para asignaciones más grandes para hacer asignaciones más grandes más rápidas.
  • También hay mecanismos inteligentes para optimizar la asignación de montones multihilo.
 41
Author: doron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-13 18:09:53

También es importante darse cuenta de que simplemente mover el puntero de interrupción del programa con brk y sbrk en realidad no asigna la memoria, solo configura el espacio de direcciones. En Linux, por ejemplo, la memoria será "respaldada" por páginas físicas reales cuando se acceda a ese rango de direcciones, lo que resultará en un error de página, y eventualmente llevará al núcleo a llamar al asignador de páginas para obtener una página de respaldo.

 7
Author: mgalgs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-16 21:09:11