Ответ 1
Когда приложения пользовательского пространства вызывают malloc()
, этот вызов не реализован в ядре. Вместо этого это вызов библиотеки (реализованный glibc или аналогичный).
Короткий вариант заключается в том, что реализация malloc
в glibc либо получает память из системного вызова brk()
/sbrk()
, либо анонимную память через mmap()
. Это дает glibc большой непрерывный (относительно адресов виртуальной памяти) фрагмент памяти, который реализует реализацию malloc
, и уменьшает количество кусочков в меньших частях и руки в ваше приложение.
Здесь небольшая реализация malloc
, которая даст вам идею, а также множество ссылок.
Обратите внимание, что пока ничего не происходит в физической памяти - обрабатывается системой виртуальной памяти ядра, когда сегмент данных процесса изменяется через brk()
/sbrk()
или mmap()
, и когда на память ссылаются (посредством чтение или запись в память).
Подводя итог:
-
malloc()
будет искать свои управляемые фрагменты памяти, чтобы увидеть, есть ли кусок неиспользуемой памяти, удовлетворяющий требованиям распределения. - В противном случае
malloc()
попытается расширить сегмент данных процесса (черезsbrk()
/brk()
или в некоторых случаяхmmap()
).sbrk()
заканчивается в ядре. - Вызов
brk()
/sbrk()
в ядре корректирует некоторые смещения вstruct mm_struct
процесса, поэтому сегмент данных процесса будет больше. Сначала физическая память не будет отображаться на дополнительные виртуальные адреса, которые расширяют сегмент данных. - Когда эта немаркированная память сначала затрагивается (вероятно, чтение/запись с помощью реализации
malloc
), обработчик ошибок будет запускаться и зависеть от ядра, где ядро назначит физическую память для памяти без памяти.