Когда приложения пользовательского пространства вызывают 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
) обработчик сбоев включается и перехватывает ядро, где ядро назначает физическую память неподписанной памяти.