Files
Elyz/kernel/docs/memory/introduction.md
2026-07-07 16:40:41 +03:00

4.5 KiB
Raw Permalink Blame History

Управление памятью: концептуальная модель

Архитектурная философия

Управление памятью в Elyz построено как трёхуровневая иерархия, где каждый уровень решает свою задачу и взаимодействует с соседними через строго определённые интерфейсы.

Уровень 1: BitmapPMM (глобальный, физический)
    │
    │ предоставляет сырые фреймы
    ▼
Уровень 2: PMActor + BuddyAllocator (распределённый, физический)
    │
    │ управляет диапазонами, выдаёт под-диапазоны
    ▼
Уровень 3: AddressSpace (VMM) (виртуальный)
    │
    │ отображает физические фреймы в виртуальные адреса
    ▼
           CPU (MMU, page tables)

Зачем три уровня?

  • BitmapPMM — глобальный аллокатор физических фреймов. Простой, надёжный, но неэффективный для частых alloc/free маленьких блоков. Используется для начальной загрузки и для Page Table страниц.

  • BuddyAllocator + PMActor — распределённая модель. Каждый актор управляет своим диапазоном физической памяти через buddy-алгоритм. Это даёт: (1) изоляцию — актор A не может истощить память актора B; (2) масштабирование — акторы могут работать параллельно; (3) предсказуемость — каждый актор знает свой лимит.

  • AddressSpace (VMM) — виртуальные адресные пространства. PML4, VMA-деревья, copy-on-write, lazy mapping. Использует PMM для аллокации Page Table страниц (через pmm_alloc в paging.rs).

Разделение ответственности по файлам

Файл Компонент Роль в абстракции
address.rs PhysAddr / VirtAddr / HHDM Базовые типы для адресов
pmm.rs BitmapPMM Глобальный менеджер физических фреймов
buddy.rs BuddyAllocator O(1) buddy allocator (intrusive list)
pm_manages.rs PMActor + PMActorQueue Актёр физической памяти + MPSC очередь
pm_router.rs PMRouter Lock-free маршрутизация запросов/ответов
paging.rs PageTable Аппаратные 4-уровневые page tables
vmm.rs AddressSpace + VMA Виртуальные адресные пространства
allocator.rs SlabAllocator Кучевой аллокатор (global_allocator)
mod.rs Экспорт Фасад подсистемы

Поток данных: типичная аллокация

Процесс A хочет 16 страниц:
  1. Код пользователя отправляет PMRequest::Allocate в PMActor через
     PMRouter::alloc_channel() + actor.submit_request()
  2. Когда актор получает CPU, process_messages() вызывает
     buddy.alloc_pages(16)
  3. BuddyAllocator находит блок порядка 4 (2^4 = 16) или больше,
     разбивает его при необходимости
  4. PMActor создаёт Capability с CapObject::Memory { phys, size_pages }
  5. Ответ (PMResponse::Allocated) отправляется через PMRouter
  6. Получатель может отобразить фреймы в своё AddressSpace через
     map_region() или map_shared()

Поток данных: page fault

CPU ловит #PF (page fault):
  1. interrupt.rs: rust_page_fault_handler() читает CR2
  2. Получает блокировку KERNEL_SPACE
  3. process_pending_revocations() — обрабатывает накопленные отзывы
  4. handle_fault() проверяет: это COW? это lazy region?
  5. Если COW — копируем страницу (copy-on-write)
  6. Если lazy — alloc_frame() из PMM + map_page()
  7. Если нераспознанный fault — KERNEL PANIC