praca_magisterska/pytania/odpowiedzi/10-zarzadzanie-pamiecia.md

601 lines
27 KiB
Markdown
Raw Normal View History

2025-12-21 19:58:11 +01:00
# Pytanie 10: Zarządzanie pamięcią - stronicowanie i segmentacja
## Pytanie
**"Scharakteryzować problemy i mechanizmy zarządzania pamięcią. Porównać cechy i przeznaczenie mechanizmów stronicowania i segmentacji."**
Przedmiot: SOI (Systemy Operacyjne)
---
## 📚 Odpowiedź główna
### Wprowadzenie
**Zarządzanie pamięcią** to jeden z kluczowych zadań systemu operacyjnego:
- Przydzielanie pamięci procesom
- Ochrona pamięci między procesami
- Efektywne wykorzystanie ograniczonego zasobu
- Abstrakcja (programista nie musi znać fizycznych adresów)
---
## 1. Problemy zarządzania pamięcią
### 1.1 Fragmentacja
#### Fragmentacja zewnętrzna (External Fragmentation)
```
┌─────────────────────────────────────────────────────────────────┐
│ Pamięć fizyczna: │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │PROC│ │FREE│ │PROC│ │FREE│ │PROC│ │FREE│ │PROC│ │
│ │ A │ │ 2K │ │ B │ │ 3K │ │ C │ │ 1K │ │ D │ │
│ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ │
│ │
│ Suma wolnej pamięci: 6K │
│ Ale nie można przydzielić bloku 5K! (fragmentacja) │
└─────────────────────────────────────────────────────────────────┘
```
**Problem:** Wolna pamięć jest rozproszona w małych, nieciągłych blokach.
#### Fragmentacja wewnętrzna (Internal Fragmentation)
```
┌─────────────────────────────────────────────────────────────────┐
│ Przydzielono blok 4KB, proces potrzebuje 3.5KB: │
│ ┌────────────────────────────────────────┐ │
│ │ WYKORZYSTANE (3.5KB) │ ZMARNOWANE (0.5KB) │ │
│ └────────────────────────────────────────┘ │
│ ↑ │
│ Fragmentacja wewnętrzna │
└─────────────────────────────────────────────────────────────────┘
```
**Problem:** Przydzielony blok jest większy niż potrzeba.
### 1.2 Ochrona pamięci
- Proces A nie może czytać/pisać pamięci procesu B
- Jądro chronione przed aplikacjami użytkownika
- Mechanizmy: rejestry bazowy/graniczny, bity ochrony, ringi
### 1.3 Relokacja
**Problem:** Program kompilowany z założeniem konkretnych adresów musi działać pod różnymi adresami.
**Rozwiązania:**
- Relokacja statyczna (loader)
- Relokacja dynamiczna (MMU - Memory Management Unit)
### 1.4 Współdzielenie
- Biblioteki współdzielone (DLL, .so)
- Pamięć współdzielona między procesami
- Copy-on-Write (COW)
### 1.5 Ograniczona pamięć fizyczna
- Więcej procesów niż RAM
- Rozwiązanie: pamięć wirtualna + swap
---
## 2. Mechanizmy zarządzania pamięcią
### 2.1 Partycjonowanie stałe (Fixed Partitioning)
```
┌────────────────────────────────────────────────────────────────┐
│ Pamięć podzielona na stałe partycje: │
│ ┌──────────┬──────────┬──────────┬──────────┐ │
│ │ Partycja │ Partycja │ Partycja │ Partycja │ │
│ │ 1MB │ 2MB │ 4MB │ 8MB │ │
│ └──────────┴──────────┴──────────┴──────────┘ │
│ │
│ Zalety: Proste, brak fragmentacji zewnętrznej │
│ Wady: Fragmentacja wewnętrzna, maks. rozmiar procesu ograniczony│
└────────────────────────────────────────────────────────────────┘
```
### 2.2 Partycjonowanie dynamiczne (Dynamic Partitioning)
```
┌────────────────────────────────────────────────────────────────┐
│ Partycje tworzone według potrzeb: │
│ ┌─────┬───────────┬────────┬─────────────────────────────┐ │
│ │ P1 │ P2 │ P3 │ WOLNA │ │
│ │ 3MB │ 5MB │ 2MB │ 10MB │ │
│ └─────┴───────────┴────────┴─────────────────────────────┘ │
│ │
│ Zalety: Brak fragmentacji wewnętrznej, elastyczność │
│ Wady: Fragmentacja zewnętrzna! │
└────────────────────────────────────────────────────────────────┘
```
**Algorytmy przydziału:**
| Algorytm | Opis | Zalety | Wady |
|----------|------|--------|------|
| **First Fit** | Pierwszy wystarczający blok | Szybki | Fragmentacja na początku |
| **Best Fit** | Najmniejszy wystarczający | Oszczędza duże bloki | Wiele małych fragmentów |
| **Worst Fit** | Największy blok | Pozostawia użyteczne resztki | Niszczy duże bloki |
| **Next Fit** | First Fit od ostatniego miejsca | Rozproszenie | Fragmentacja |
---
## 3. Stronicowanie (Paging)
### Idea
Dzielimy pamięć na **równe bloki** (strony/ramki):
- **Strona (Page)** - blok pamięci wirtualnej (4KB typowo)
- **Ramka (Frame)** - blok pamięci fizycznej (ten sam rozmiar)
```
┌─────────────────────────────────────────────────────────────────┐
│ PAMIĘĆ WIRTUALNA PAMIĘĆ FIZYCZNA │
│ (przestrzeń adresowa) (RAM) │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Strona 0│─────────────────────────│ Ramka 5 │ │
│ ├─────────┤ ├─────────┤ │
│ │ Strona 1│──────────┐ │ Ramka 1 │ │
│ ├─────────┤ │ ├─────────┤ │
│ │ Strona 2│────┐ │ │ Ramka 2 │←──────────┐ │
│ ├─────────┤ │ │ ├─────────┤ │ │
│ │ Strona 3│ │ └─────────────→│ Ramka 3 │ │ │
│ └─────────┘ │ ├─────────┤ │ │
│ │ │ Ramka 4 │ │ │
│ │ ├─────────┤ │ │
│ └───────────────────→│ Ramka 7 │ │ │
│ └─────────┘ │ │
│ │ │
│ TABLICA STRON (Page Table) Strona 2 → Ramka 7────┘ │
│ ┌──────────────────────┐ │
│ │ Strona │ Ramka │Flagi│ │
│ │ 0 │ 5 │ RW │ │
│ │ 1 │ 3 │ R │ │
│ │ 2 │ 7 │ RW │ │
│ │ 3 │ - │ INV │ ← Strona nie w pamięci (page fault) │
│ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### Translacja adresu
```
Adres wirtualny (32-bit, strony 4KB):
┌────────────────────────┬──────────────┐
│ Numer strony (20b) │ Offset (12b) │
└────────────────────────┴──────────────┘
│ │
↓ │
Tablica stron │
│ │
↓ │
┌────────────────────────┬──────────────┐
│ Numer ramki (20b) │ Offset (12b) │
└────────────────────────┴──────────────┘
Adres fizyczny
```
### Wielopoziomowe tablice stron
**Problem:** Tablica stron dla 32-bit przestrzeni z 4KB stronami = 2²⁰ wpisów × 4B = **4MB per proces!**
**Rozwiązanie:** Hierarchiczna tablica stron
```
Adres wirtualny (32-bit, 2 poziomy):
┌────────────┬────────────┬──────────────┐
│ Katalog(10)│ Tabela(10) │ Offset (12) │
└────────────┴────────────┴──────────────┘
│ │ │
↓ ↓ │
┌──────────┐ ┌──────────┐ │
│ Page │ │ Page │ │
│Directory │→ │ Table │→ Ramka + Offset
└──────────┘ └──────────┘
```
**64-bit (x86-64):** 4 poziomy (PML4 → PDPT → PD → PT)
### TLB (Translation Lookaside Buffer)
**Problem:** Każdy dostęp do pamięci wymaga 2+ odczytów (tablica + dane).
**Rozwiązanie:** Cache translacji adresów
```
┌─────────────────────────────────────────────────────────────────┐
│ TLB │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Strona wirtualna │ Ramka fizyczna │ Flagi │ ASID │ │
│ │ 0x12345 │ 0x789AB │ RW │ 42 │ │
│ │ 0x12346 │ 0x789AC │ R │ 42 │ │
│ │ ... │ ... │ ... │ ... │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ TLB hit: ~1 cykl │
│ TLB miss: ~100+ cykli (page walk) │
│ Hit rate: >99% typowo │
└─────────────────────────────────────────────────────────────────┘
```
### Zalety i wady stronicowania
| Zalety | Wady |
|--------|------|
| Brak fragmentacji zewnętrznej | Fragmentacja wewnętrzna (ostatnia strona) |
| Prosta alokacja (bitmapa ramek) | Narzut tablicy stron |
| Łatwe współdzielenie (COW) | TLB miss kosztowny |
| Pamięć wirtualna naturalna | Nie odpowiada strukturze programu |
---
## 4. Segmentacja (Segmentation)
### Idea
Dzielimy pamięć na **logiczne segmenty** odpowiadające strukturze programu:
- Segment kodu
- Segment danych
- Segment stosu
- Segment bibliotek
```
┌─────────────────────────────────────────────────────────────────┐
│ PRZESTRZEŃ LOGICZNA PAMIĘĆ FIZYCZNA │
│ │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ Segment 0 │ │ │ │
│ │ (Kod) │─────────────────│→ 0x1000 - 0x3FFF │ │
│ │ Rozmiar: 12KB │ │ │ │
│ └─────────────────┘ ├─────────────────────┤ │
│ ┌─────────────────┐ │ │ │
│ │ Segment 1 │─────────────────│→ 0x8000 - 0xBFFF │ │
│ │ (Dane) │ │ │ │
│ │ Rozmiar: 16KB │ ├─────────────────────┤ │
│ └─────────────────┘ │ │ │
│ ┌─────────────────┐ │ │ │
│ │ Segment 2 │─────────────────│→ 0xF000 - 0xF7FF │ │
│ │ (Stos) │ │ │ │
│ │ Rozmiar: 2KB │ └─────────────────────┘ │
│ └─────────────────┘ │
│ │
│ TABLICA SEGMENTÓW │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Segment │ Baza │ Limit │ Prawa │ │ │
│ │ 0 │ 0x1000 │ 12KB │ RX │ (kod - execute) │ │
│ │ 1 │ 0x8000 │ 16KB │ RW │ (dane - read/write) │ │
│ │ 2 │ 0xF000 │ 2KB │ RW │ (stos) │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### Translacja adresu
```
Adres logiczny:
┌────────────────────┬──────────────────────┐
│ Numer segmentu (s) │ Offset (d) │
└────────────────────┴──────────────────────┘
│ │
↓ │
Tablica segmentów │
┌──────┬───────┐ │
│ Baza │ Limit │ │
└──────┴───────┘ │
│ │ │
│ Sprawdź: d < Limit?
│ │ │
↓ ↓ │
Adres fizyczny = Baza + Offset
```
### Ochrona w segmentacji
Każdy segment ma **prawa dostępu:**
- **R** (Read) - odczyt dozwolony
- **W** (Write) - zapis dozwolony
- **X** (Execute) - wykonanie dozwolone
```
Segment kodu: RX (wykonaj, nie modyfikuj)
Segment danych: RW (czytaj/pisz, nie wykonuj)
Segment stosu: RW (bez wykonywania - ochrona przed exploitami)
```
### Zalety i wady segmentacji
| Zalety | Wady |
|--------|------|
| Odpowiada strukturze programu | Fragmentacja zewnętrzna |
| Naturalna ochrona (per segment) | Segmenty o zmiennej wielkości |
| Łatwe współdzielenie (cały segment) | Kompaktowanie potrzebne |
| Dynamiczny wzrost segmentów | Skomplikowana alokacja |
---
## 5. Porównanie: Stronicowanie vs Segmentacja
| Cecha | Stronicowanie | Segmentacja |
|-------|---------------|-------------|
| **Jednostka** | Strona (stały rozmiar) | Segment (zmienny rozmiar) |
| **Widoczność dla programisty** | Niewidoczna | Widoczna (logiczne jednostki) |
| **Fragmentacja zewnętrzna** | ❌ Brak | ✅ Występuje |
| **Fragmentacja wewnętrzna** | ✅ Występuje | ❌ Brak |
| **Tablica** | Tablica stron (duża) | Tablica segmentów (mała) |
| **Ochrona** | Per strona (mniej naturalna) | Per segment (naturalna) |
| **Współdzielenie** | Per strona | Per segment (całe moduły) |
| **Pamięć wirtualna** | Łatwa (strony na dysk) | Trudniejsza |
---
## 6. Segmentacja ze stronicowaniem (Hybrid)
### Intel x86 (tryb chroniony)
Kombinacja obu mechanizmów:
```
Adres logiczny (Selector:Offset)
SEGMENTACJA
(Segment → Adres liniowy)
Adres liniowy
STRONICOWANIE
(Strona → Ramka)
Adres fizyczny
```
**Praktyka:** Współczesne OS (Linux, Windows) używają **flat memory model** - wszystkie segmenty pokrywają całą przestrzeń adresową, efektywnie wyłączając segmentację.
### Zalety hybrydowego podejścia
1. **Ochrona** z segmentacji (kod vs dane vs stos)
2. **Brak fragmentacji zewnętrznej** ze stronicowania
3. **Pamięć wirtualna** ze stronicowania
---
## 7. Pamięć wirtualna (Virtual Memory)
### Idea
Nie wszystkie strony muszą być w RAM - część może być na dysku (swap).
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ PAMIĘĆ WIRTUALNA RAM DYSK (Swap) │
│ ┌─────────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Strona 0 │ ────→│ Ramka 2 │ │ │ │
│ │ Strona 1 │ │ │ │ Strona 3 │ │
│ │ Strona 2 │ ────→│ Ramka 5 │ │ Strona 5 │ │
│ │ Strona 3 │ ─────────────────────→ │ │ │
│ │ Strona 4 │ ────→│ Ramka 1 │ │ │ │
│ │ Strona 5 │ ─────────────────────→ │ │ │
│ └─────────────┘ └──────────┘ └──────────────┘ │
│ │
│ Page fault: Strona 3 → załaduj z dysku do RAM │
└─────────────────────────────────────────────────────────────────┘
```
### Algorytmy zastępowania stron
| Algorytm | Opis | Właściwości |
|----------|------|-------------|
| **FIFO** | Najstarsza strona | Prosty, anomalia Bélády'ego |
| **LRU** | Najdawniej używana | Optymalny offline, kosztowny |
| **LRU Approximation** | Clock, Second Chance | Praktyczny kompromis |
| **LFU** | Najrzadziej używana | Dobre dla hot data |
| **OPT** | Najdalej używana | Teoretycznie optymalny, niemożliwy |
### Algorytm Clock (Second Chance)
```
┌───┐
┌──→│ 1 │──┐ Bit referencji:
│ └───┘ │ 1 = używana ostatnio
│ ↓ 0 = kandydat do usunięcia
┌───┐ ┌───┐
│ 0 │ │ 1 │ Wskazówka zegara:
└───┘ └───┘ - Jeśli bit=1: zeruj, idź dalej
↑ │ - Jeśli bit=0: zastąp tę stronę
│ ┌───┐ │
└───│ 0 │←─┘
└───┘
wskazówka
```
---
## 🧠 Mnemoniki
### "STRONY RÓWNE, SEGMENTY LOGICZNE":
- **Strony** = wszystkie takie same (4KB)
- **Segmenty** = różne rozmiary, logiczny podział
### "PAGE = Physical Allocation Generates Equality":
- Fizyczne ramki równej wielkości
- Brak fragmentacji zewnętrznej
### "SEGMENT = Software Entity with Guarded Memory, ENforcing Type safety":
- Logiczne jednostki programu
- Ochrona per segment
### "TLB = Translation Lightning-fast Buffer":
- Cache dla translacji adresów
- Hit = 1 cykl, Miss = 100+ cykli
### "LRU = Last Recently Used → pierwszy do usunięcia":
- Najdawniej używana = najlepsza do wyrzucenia
---
## ❓ Możliwe pytania dodatkowe (follow-up)
### Q1: "Co to jest Page Fault i jak jest obsługiwany?"
**Odpowiedź:**
**Page Fault** = wyjątek gdy strona nie jest w RAM (bit valid=0 w tablicy stron).
```
1. Proces odwołuje się do adresu w stronie 5
2. MMU sprawdza tablicę stron: strona 5 invalid
3. Page Fault exception
4. OS:
a) Znajdź stronę na dysku (swap)
b) Znajdź wolną ramkę (lub zwolnij przez algorytm zastępowania)
c) Załaduj stronę z dysku do RAM
d) Zaktualizuj tablicę stron (valid=1, ramka=X)
e) Wznów instrukcję
5. Proces kontynuuje (nie wie, że był page fault)
```
---
### Q2: "Wyjaśnij anomalię Bélády'ego"
**Odpowiedź:**
**Anomalia Bélády'ego** = więcej ramek → więcej page faults (dla FIFO)!
```
Sekwencja odwołań: 1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5
3 ramki (FIFO): 9 page faults
4 ramki (FIFO): 10 page faults (!!)
Wniosek: FIFO nie jest "stack algorithm" - nie ma tej właściwości:
"Strony w pamięci z N ramkami ⊆ strony z N+1 ramkami"
LRU nie ma tej anomalii (jest stack algorithm).
```
---
### Q3: "Co to jest thrashing?"
**Odpowiedź:**
**Thrashing** = system spędza więcej czasu na page faults niż na wykonywaniu kodu.
```
Przyczyna: Zbyt mało RAM dla working set procesów
Working set = zbiór stron aktywnie używanych przez proces
Symptomy:
- CPU utilization spada
- Dysk ciągle pracuje (swap in/out)
- System "zamiera"
Rozwiązania:
- Zwiększ RAM
- Zmniejsz multiprogramming
- Working set model (przydziel RAM proporcjonalnie)
- Swap na SSD
```
---
### Q4: "Jak działa Copy-on-Write?"
**Odpowiedź:**
**COW** = odroczenie kopiowania do momentu modyfikacji.
```
fork() bez COW:
Rodzic: [Strona A] [Strona B] [Strona C]
↓ kopiowanie
Dziecko: [Strona A'] [Strona B'] [Strona C']
→ Kosztowne!
fork() z COW:
Rodzic: [Strona A (RO)] [Strona B (RO)] [Strona C (RO)]
↓ shared ↓ shared ↓ shared
Dziecko: [Strona A (RO)] [Strona B (RO)] [Strona C (RO)]
→ Szybkie! (tylko tablice stron)
Dziecko pisze do Strony B:
1. Page fault (strona RO)
2. OS kopiuje Stronę B → B'
3. Dziecko dostaje B' (RW), rodzic zachowuje B (RW)
```
---
### Q5: "Jaki jest typowy rozmiar strony i dlaczego?"
**Odpowiedź:**
| Rozmiar | Zalety | Wady |
|---------|--------|------|
| **Mały (1KB)** | Mała fragmentacja wewnętrzna | Duża tablica stron |
| **Duży (64KB)** | Mała tablica stron | Duża fragmentacja wewnętrzna |
| **4KB (typowy)** | Kompromis | Kompromis |
**Dlaczego 4KB?**
- Rozmiar bloku dysku (sektor 512B × 8 lub 4K native)
- Rozsądna fragmentacja (~2KB średnio)
- Rozsądna tablica stron
- Historyczne (VAX, Unix)
**Huge Pages (2MB, 1GB):**
- Dla dużych aplikacji (bazy danych)
- Mniej wpisów TLB
- Mniej page faults
---
### Q6: "Jak segmentacja jest używana w x86-64?"
**Odpowiedź:**
**x86-64 praktycznie nie używa segmentacji:**
```
CS, DS, ES, SS → Baza = 0, Limit = maksymalny
→ Efektywnie "flat model"
Wyjątki:
- FS, GS → używane dla Thread Local Storage (TLS)
- CS → poziom uprzywilejowania (ring 0/3)
```
**Powód:** Segmentacja komplikuje pamięć wirtualną i nie jest potrzebna z ochroną per-strona (NX bit, SMEP, SMAP).
---
## 🎯 Kluczowe punkty do zapamiętania
1. **Stronicowanie** = równe strony/ramki, brak fragmentacji zewnętrznej
2. **Segmentacja** = logiczne jednostki, fragmentacja zewnętrzna
3. **Współczesne OS** = stronicowanie (segmentacja wyłączona)
4. **TLB** = cache translacji, kluczowy dla wydajności
5. **Page fault** = strona nie w RAM, załaduj z dysku
6. **Thrashing** = za mało RAM, ciągłe page faults
---
## 📖 Źródła do pogłębienia
1. Silberschatz, Galvin - "Operating System Concepts"
2. Tanenbaum - "Modern Operating Systems"
3. Intel Manual Vol. 3 - System Programming Guide
4. Linux kernel documentation - Memory Management