2010-08-13 25 views
92

¿Alguien puede explicar cómo funciona malloc() internamente?¿Cómo se implementa malloc() internamente?

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

+2

Usa la fuente, Boda Cydo. http://ftp.gnu.org/gnu/glibc/ – msw

+0

Creo que este enlace responde su pregunta hasta cierto punto http://stackoverflow.com/questions/1119134/how-malloc-and-free-work – Rishabh

Respuesta

87

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 (permitiéndole crecer o reducirse, aunque AFAIK no malloc realmente le da segmentos de memoria al kernel con ese método). Aparte de eso, también hay mmap que se utiliza 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).

Tiene dos métodos para obtener más memoria del kernel: sbrk y mmap. Hay varias estrategias sobre cómo organizar la memoria que tiene del kernel.

Una forma ingenua es dividirla en zonas, a menudo llamadas "cubos", que están dedicados a ciertos tamaños de estructura. Por ejemplo, una implementación de malloc podría crear divisiones para estructuras de 16, 64, 256 y 1024 bytes. Si pide malloc para darle memoria de un tamaño dado, redondea ese número al siguiente tamaño de cubo y luego le da un elemento de ese cubo. Si necesita un área más grande, malloc podría usar mmap para asignar directamente con el kernel. Si el contenedor de un determinado tamaño está vacío, malloc podría usar sbrk para obtener más espacio para un nuevo contenedor.

Existen varios diseños de malloc y no existe una manera verdadera de implementar malloc, ya que necesita hacer un compromiso entre velocidad, sobrecarga y evitar la fragmentación/efectividad del espacio. Por ejemplo, si una cubeta se queda sin elementos, una implementación podría obtener un elemento de una cubeta más grande, dividirlo y agregarlo a la cubeta que se quedó sin elementos. Esto sería bastante eficiente desde el punto de vista del espacio, pero no sería posible con cada diseño. Si acaba de obtener otro cubo a través de sbrk/mmap que podría ser más rápido y más fácil, pero no tan eficiente en el uso del espacio. Además, el diseño debe tener en cuenta, por supuesto, que "libre" necesita dejar espacio disponible para malloc de alguna manera. No solo entregas la memoria sin reutilizarla.

Si está interesado, la OpenSER/Kamailio SIP proxy tiene dos implementaciones malloc (que necesitan su propio porque hacen un uso intensivo de la memoria compartida y el sistema malloc no es compatible con memoria compartida). Ver: https://github.com/OpenSIPS/opensips/tree/master/mem

entonces también podría echar un vistazo a la GNU libc malloc implementation, pero que uno es muy complicado, IIRC.

+2

IIRC = Si recuerdo correctamente –

37

simplista malloc y de trabajo libre de esta manera:

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

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

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 gratuita del montón.

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

Cuando uno libera memoria, la pila se agrega al final de la lista libre del montón. Los mallocs subsiguientes recorren la lista gratuita buscando una célula de tamaño adecuado.

Como se puede esperar, el montón puede fragmentarse y el administrador del montón puede ocasionalmente intentar fusionar las celdas de montón adyacentes.

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

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

  • Para grandes asignaciones de memoria (típicamente> 512 bytes, el administrador del montón 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 a evitar grandes cantidades de fragmentación.
  • El montón también puede dividirse en compartimientos uno para pequeñas asignaciones y uno para asignaciones más grandes para hacer las asignaciones más grandes más rápida.
  • Hay al mecanismos tan ingeniosos para optimizar la asignación de heap multiproceso.
7

También es importante darse cuenta de que simplemente moviendo el puntero del programa en torno ruptura con brk y sbrk realidad no asignar la memoria, sólo se configura el espacio de direcciones. En Linux, por ejemplo, la memoria estará "respaldada" por páginas físicas reales cuando se acceda a ese rango de direcciones, lo que dará como resultado un error de página, y eventualmente llevará al kernel a llamar al asignador de páginas para obtener una página de respaldo.