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

601 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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