Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

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

Soy nuevo en C y en la memoria del montón, todavía me cuesta entender la asignación de memoria dinámica.

Rastreé las llamadas del sistema Linux y descubrí que si uso malloc para solicitar una pequeña cantidad de memoria en montón, entonces malloc llama a brk internamente.

Pero si utilizo malloc para solicitar una gran cantidad de memoria en montón, entonces malloc llama a mmap internamente.

Por lo tanto, debe haber una gran diferencia entre brk y mmap , pero teóricamente deberíamos poder usar brk para asignar memoria de almacenamiento dinámico independientemente del tamaño solicitado. Entonces, ¿por qué malloc llama a mmap cuando asigna una gran cantidad de memoria?

over 4 years ago · Santiago Trujillo
6 answers
Answer question

0

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 puede devolverse al sistema operativo cuando el proceso ya no necesita un rango continuo de direcciones al final de la arena .

El uso de 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 ninguna otra. vida útil de las 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 hace.

Esta heurística no es muy fiable. La generación actual de implementaciones de malloc , si no recuerdo mal, ha renunciado por completo a brk y usa mmap para todo. La implementación de malloc que sospecho que está viendo (la que está en la Biblioteca C de GNU, 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.

over 4 years ago · Santiago Trujillo Report

0

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 nuevas 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 los motivos 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() reproducen 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 esto:

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 quedan 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 se hubiera asignado con brk(), el sistema no lo habría podido utilizar, incluso si el proceso lo hubiera liberado.
(énfasis mío)

Con respecto a brk() :
dicho sea de paso, "... 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() .

over 4 years ago · Santiago Trujillo Report

0

brk() es una forma tradicional de asignar memoria en UNIX: simplemente expande el área de datos en una cantidad determinada. mmap() le permite asignar regiones independientes de memoria sin estar restringido a una sola porción contigua de espacio de direcciones virtuales.

malloc() usa el espacio de datos para asignaciones "pequeñas" y mmap() para asignaciones "grandes", por varias razones, incluida la reducción de la fragmentación de la memoria. Es solo un detalle de implementación del que no debería preocuparse.

Por favor revise esta pregunta también.

over 4 years ago · Santiago Trujillo Report

0

Quiero enfatizar otro punto de vista.

malloc es una función del sistema que asigna memoria.

Realmente no necesita depurarlo, porque en algunas implementaciones, puede proporcionarle memoria de "arena" estática (por ejemplo, matriz de caracteres estática).

En algunas otras implementaciones, puede devolver un puntero nulo.

Si quieres ver lo que realmente hace la malva, te sugiero que mires
http://gee.cs.oswego.edu/dl/html/malloc.html

Linux gcc malloc se basa en esto.

También puedes echar un vistazo a jemalloc. Básicamente usa el mismo brk y mmap, pero organiza los datos de manera diferente y generalmente es "mejor".

Feliz investigando.

over 4 years ago · Santiago Trujillo Report

0

La reducción de la fragmentación se da comúnmente como la razón por la cual mmap se usa para asignaciones grandes; vea la respuesta de ryyker para más detalles. Pero creo que ese no es el verdadero beneficio hoy en día; en la práctica, todavía hay fragmentación incluso con mmap , solo en un grupo más grande (el espacio de direcciones virtuales, en lugar del montón).

La gran ventaja de mmap es la descartabilidad.

Al asignar memoria con sbrk , si la memoria se usa realmente (de modo que el kernel mapea la memoria física en algún momento) y luego se libera, el kernel en sí no puede saberlo, a menos que el asignador también reduzca la interrupción del programa (que no puede si el bloque liberado no es el bloque utilizado anteriormente en la parte superior debajo de la interrupción del programa). El resultado es que los contenidos de esa memoria física se vuelven “preciosos” en lo que respecta al kernel; si alguna vez necesita reutilizar esa memoria física, debe asegurarse de que no pierda su contenido. Por lo tanto, podría terminar intercambiando páginas (lo cual es costoso) a pesar de que el proceso de propiedad ya no se preocupa por ellas.

Al asignar memoria con mmap , liberar la memoria no solo devuelve el bloque a un grupo en algún lugar; la asignación de memoria virtual correspondiente se devuelve al kernel, y eso le dice al kernel que la memoria física correspondiente, sucia o no, ya no es necesaria. Luego, el kernel puede reutilizar esa memoria física sin preocuparse por su contenido.

over 4 years ago · Santiago Trujillo Report

0

la parte clave de la razón por la que pienso, que copié del chat dicho por Peter

free() es una función de espacio de usuario, no una llamada al sistema. O los devuelve al sistema operativo con munmap o brk, o los mantiene sucios en el espacio del usuario. Si no realiza una llamada al sistema, el sistema operativo debe conservar el contenido de esas páginas como parte del estado del proceso.

Entonces, cuando usa brk para aumentar su dirección de memoria, cuando regresa, debe usar brk con un valor negativo, por lo que brk solo puede devolver el bloque de memoria más reciente que asignó, cuando llama a malloc (enorme), malloc (pequeño) , abrazo gratis). el enorme no se puede devolver al sistema, solo puede mantener una lista de fragmentación para este proceso, por lo que el enorme es realmente retenido por este proceso. este es el inconveniente de brk.

pero mmap y munmap pueden evitar esto.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!