Управление памятью

Наиболее сложным, по-моему, является алгоритм выделения памяти, каталог memory .

Выделяемые блоки памяти делятся на «большие» (далее б-блок) и «малые» (далее м-блок). Б-блок — это блок размером более PAGE_SIZE — 24 (смещение для массива м-блоков) или 4072 байт. М-блок, соответственно, блок размером от 4072 байт и менее.

Блоки всегда выделяются на границе страницы. То есть при запросе размер округляется до 4кБ. При этом для б-блоков выделяется отдельная страница, а предыдущая используется для управления. Для м-блоков выделяется одна страница, в которой и хранятся м-блоки.

В связи с этим б-блок может выделяться для отдельных процессов (processes), ячеек (cell) и универсов (universe), а м-блоки можно выделять только для одного. Данное разграничение пока не реализовано, но запланировано.

Краткое описание функций:

Функция memory_init проходит по карте памяти, предоставляемой UEFI и создаёт блоки свободной памяти, игнорируя всё занятое. Алгоритм довольно прямолинеен и в особом описании не нуждается.

Функция kmalloc является основной вместе с kmfree. Выделяется блок в списке свободной памяти. Тип блока определяется по запрашиваемому размеру. В отличие от POSIX-стандарта, в параметрах используется ссылка на переменную-указатель и размер. Это позволяет указать в переменной-указателе недействительное значение, что является запланированным внедрением уникальных указателей в многопроцессорной обработке.

Функция alloc_small никогда не вызывается напрямую. Эта функция используется kmalloc, если запрашиваемый блок относится к м-блоку.

Функция kmfree освобождает указанный блок. Б-блок и м-блок распознаются по выравниванию.

Функция free_small вызывается из kmfree, если есть признаки м-блока (невыровненный адрес).

Функция congregate_memory и congregate_small_memory объединяют б-блоки и м-блоки, соответственно. Если м-блок «пустой», то он объединяется с ближайшими б-блоками, путём вызова kmfree.