83 lines
4.5 KiB
Markdown
83 lines
4.5 KiB
Markdown
# Управление памятью: концептуальная модель
|
||
|
||
## Архитектурная философия
|
||
|
||
Управление памятью в 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
|
||
```
|