Mechanism: Limited Direct Execution¶
📚 1️⃣ Ziel von CPU-Virtualisierung¶
Das Ziel ist, jeden Prozess so erscheinen zu lassen, als hätte er die gesamte CPU für sich.
Da jedoch mehrere Prozesse gleichzeitig ausgeführt werden müssen, teilt das Betriebssystem die CPU durch Zeitslicing (Time-Sharing) auf.
Herausforderungen:
- Performance: Wie kann Virtualisierung effizient ohne Overhead implementiert werden?
- Kontrolle: Wie kann das OS Prozesse effizient ausführen, aber trotzdem die Kontrolle behalten?
⚡ 2️⃣ Direkte Ausführung (Direct Execution)¶
Beim direkten Ausführen läuft ein Benutzerprozess direkt auf der CPU:
- Eintrag in die Prozessliste erstellen.
- Speicher zuweisen und Programm laden.
- Register setzen, dann
main()
aufrufen. - Prozess läuft direkt auf der CPU.
💡 Problem:
Ohne Einschränkungen könnte ein Prozess unkontrolliert laufen – das OS hätte keine Kontrolle über CPU-Zeit oder kritische Systemressourcen.
🚨 3️⃣ Probleme der direkten Ausführung¶
Problem 1: Geschützte Operationen¶
Was passiert, wenn ein Prozess eine kritische Aktion ausführen möchte, z. B.:
- I/O-Anfragen an eine Festplatte senden?
- Mehr Speicher oder CPU-Zeit anfordern?
🔹 Lösung: Geschützter Kontrolltransfer
→ Es gibt zwei Modi für die CPU:
- User Mode: Normale Programme können nicht direkt auf Hardware zugreifen.
- Kernel Mode: Das Betriebssystem kann alle Systemressourcen verwalten.
🔹 Systemaufruf (System Call):
- Benutzerprozesse können keine direkten I/O-Operationen ausführen.
- Stattdessen nutzen sie System Calls (
syscall
), um das OS um Erlaubnis zu bitten.
💡 Ablauf eines System Calls:
- Der Benutzerprozess führt eine Trap-Instruktion aus.
- CPU wechselt in den Kernel Mode.
- OS bearbeitet den System Call (z. B. Datei öffnen).
- CPU kehrt in den User Mode zurück.
📌 Beispiel für einen System Call in C:
#include <stdio.h>
#include <unistd.h>
int main() {
write(1, "Hello, World!\n", 14); // System Call für die Ausgabe auf stdout
return 0;
}
Problem 2: Prozesswechsel (Context Switch)¶
Damit mehrere Prozesse gleichzeitig laufen können, muss das OS zwischen Prozessen umschalten.
🔹 Lösungen für CPU-Kontrolle:
-
Kooperativer Ansatz:
- Prozesse geben freiwillig die CPU ab (
yield
odersleep
). - Problem: Ein Prozess kann in einer Endlosschleife hängen → System blockiert.
-
Erzwungener Ansatz (Timer-Interrupts):
-
Das OS startet einen Timer, der regelmäßig Interrupts auslöst.
- Sobald der Timer abläuft, wird die aktuelle Prozessausführung gestoppt.
- Das OS entscheidet, ob ein neuer Prozess gestartet wird.
- Prozesse geben freiwillig die CPU ab (
🔹 Ablauf eines erzwungenen Prozesswechsels:
- Timer läuft ab → Interrupt wird ausgelöst.
- Der aktuelle Prozess wird unterbrochen.
- Das OS speichert den aktuellen Zustand (Registersicherung).
- Das OS wählt einen neuen Prozess.
- Der neue Prozess wird geladen, und seine Register werden wiederhergestellt.
- Der neue Prozess läuft weiter.
📌 Beispiel für einen Timer-Interrupt in C (Linux Kernel)
void timer_interrupt_handler() {
save_process_state(); // Zustand des aktuellen Prozesses sichern
select_next_process(); // Nächsten Prozess auswählen
restore_process_state(); // Zustand des neuen Prozesses laden
}
🔄 4️⃣ Context Switch: Wechsel zwischen Prozessen¶
Beim Wechsel zwischen Prozessen muss das OS sicherstellen, dass keine Daten verloren gehen.
🔹 Wichtige Schritte beim Context Switch:
- Speichern des aktuellen Prozessstatus (Register, Stack-Pointer).
- Wechsel in den Kernel Mode.
- Laden des neuen Prozessstatus.
- Wechsel zurück in den User Mode.
🔹 Prozess hat zwei Stacks:
- User Stack: Speichert lokale Variablen und Rücksprungadressen für Benutzerprozesse.
- Kernel Stack: Speichert Systemaufrufe und Prozesszustände für das Betriebssystem.
💡 Prozesswechsel erfolgt über den „Dispatcher“, eine OS-Funktion, die Prozesse pausiert und neue lädt.
📌 Beispiel für Context Switch in Pseudo-Code:
🎯 5️⃣ Fazit¶
- Direkte Ausführung ist effizient, benötigt aber Sicherheitsmechanismen.
- Systemaufrufe ermöglichen kontrollierten Zugriff auf Hardware.
- Timer-Interrupts verhindern Endlosschleifen und CPU-Hogging.
- Context Switches sorgen für Multitasking und effiziente CPU-Nutzung.
💡 Ohne diese Mechanismen könnte ein einzelner Prozess das gesamte System übernehmen!