tag - ¿Cómo se implementa sbrk/brk en Linux?
mp3tag ubuntu (4)
Bueno, desde una perspectiva de nivel super alto, el kernel asigna un bloque de memoria paginable, modifica las tablas de páginas del proceso solicitando ese bloque para que la memoria se asigne al espacio VA del proceso y luego devuelva la dirección.
Estaba pensando en cómo el kernel de Linux implementa las llamadas al sistema y me preguntaba si alguien podría darme una vista de alto nivel de cómo funciona sbrk / brk.
He revisado el código del kernel, pero hay mucho de eso y no lo entiendo. ¿Esperaba un resumen de alguien?
Un concepto clave de cómo el kernel de Linux pasa la memoria a un proceso de usuario es que el montón de procesos disponibles (el segmento de datos) crece desde la parte inferior. el kernel no realiza un seguimiento de trozos individuales de memoria, solo un bloque continuo de memoria. Las llamadas al sistema brk / sbrk amplían la cantidad de memoria que tiene el proceso, pero depende del proceso gestionarlo en partes utilizables.
Una consecuencia clave de esto es que la memoria dispersa en el espacio de direcciones de los procesos que no está en uso no puede devolverse al sistema operativo para otros usos. Solo la memoria al final del segmento de datos puede devolverse al sistema operativo, por lo que la memoria en uso cerca del final tendría que desplazarse hacia abajo hacia la parte superior. En la práctica casi ningún repartidor hace esto. Por esta razón, generalmente es importante hacer un buen trabajo para administrar la cantidad máxima de memoria que utiliza un proceso, porque eso determina cuánta memoria quedará para otros procesos.
debe comprender cómo funciona la memoria virtual y cómo se relaciona una asignación MMU con la RAM real.
La RAM real se divide en páginas, tradicionalmente 4kB cada una. cada proceso tiene su propio mapeo MMU, que presenta a ese proceso un espacio de memoria lineal (4 GB en Linux de 32 bits). por supuesto, no todos ellos están realmente asignados. al principio, está casi vacío, es decir, no se asocia una página real con la mayoría de las direcciones.
cuando el proceso llega a una dirección no asignada (ya sea tratando de leerla, escribirla o ejecutarla), la MMU genera una falla (similar a una interrupción) y se invoca el sistema VM. Si decide que algo de RAM debería estar allí, elige una página de RAM no utilizada y se asocia con ese rango de direcciones.
de esa manera, al kernel no le importa cómo el proceso usa la memoria, y al proceso no le importa cuánta RAM hay, siempre tendrá el mismo espacio lineal de direcciones de 4GB.
ahora, brk/sbrk
funciona en un nivel ligeramente superior: en principio, cualquier dirección de memoria "más allá" de esa marca no es válida y, si se accede a ella, no se obtendrá una página de RAM, el proceso se eliminará. la biblioteca de espacio de usuario administra las asignaciones de memoria dentro de este límite, y solo cuando es necesario le pide al núcleo que la aumente.
Pero incluso si un proceso comenzó estableciendo brk
en el máximo permitido, no se asignarán páginas RAM reales hasta que empiece a acceder a todas las direcciones de memoria.
En una vista de muy alto nivel, el kernel de Linux rastrea la memoria visible para un proceso como varias "áreas de memoria" ( struct vm_area_struct
). También hay una estructura que representa (de nuevo en una vista de muy alto nivel) un espacio de direcciones completo del proceso ( struct mm_struct
). Cada proceso (excepto algunos subprocesos del núcleo) tiene exactamente una struct mm_struct
, que a su vez apunta a toda la struct vm_area_struct
para la memoria a la que puede acceder.
La sys_brk
sistema sys_brk
(que se encuentra en mm/mmap.c
) simplemente ajusta algunas de estas áreas de memoria. ( sbrk
es un envoltorio glibc alrededor de brk
). Lo hace comparando el valor antiguo de la dirección brk
(que se encuentra dentro de struct mm_struct
) y el valor solicitado.
Sería más sencillo ver primero la familia de funciones mmap
, ya que brk
es un caso especial.