# Scheduling
Prozess, wie das Betriebssystem die Ausführung von Aufgaben (Prozessen, Threads, ...) plant und verwaltet

- Hauptziel: Effiziente Nutzung der Systems
  - Erfüllung der Anforderungen des Systems und des Benutzers
- Kritisches Element im BS-Design
  - direkter Einfluss auf Leistung, Benutzererfahrung

## Aufgaben eines Schedulers
- **Prozessorzuweisung**
  - welcher Prozess als nächstes?
- **Prozessorwechsel**
  - Wechsel von einem laufenden Prozess zu einem anderen
- **Prioritätszuweisung**
  - Bestimmt Priorität von Prozessen → wichtige Aufgaben werden bevorzugt behandelt
- **Warteschlangenmanagement**
  - Verwaltung der Warteschlangen mit Prozessen
  

## Entscheidungsverfahren
- **CPU-Auslastung**
  - Maximierung der CPU-Auslastung
- **Durchsatz**
  - Anzahl abgeschlossene Aufgaben pro Zeit
- **Wartezeit**
  - Minimierung der Wartezeit der Prozesse in der Warteschlange
- **Umlaufzeit**
  - Gesamtzeit die ein Prozess benötigt um abgeschlossen zu werden
- **Antwortzeit**
  - Zeit zwischen der Anforderung eines Benutzers und der ersten Reaktion des Systems


## Nicht präemptives Scheduling
- Art von Prozessorscheduling beo dem der laufende Prozess nicht unterbrochen werden kann
  - bis CPU-Zeitscheibe vollständig oder andere Blockierungsbedingung
- Eingesetz in
  - einfache Systeme, Batch-Verarbeitung-Umgebungen
    - Vorhersagbarkeit, einfache Implementierung wichtiger als schnelle Reaktion auf Benutzerinteraktion


## Präemptives Scheduling
- Betriebssystemkern kann Kontrolle über CPU von einem laufenden Prozess übernehmen
  - kann anderem Prozess CPU-Zeit zuweisen, _falls best. Bedingungen erfüllt_

## Prioritätengesteuertes Scheduling
- Ausführungsreihenfolge der Prozesse hängt von deren Priorität ab
  - Jeder Prozess kriegt bestimmte Prio
  - Scheduler nimmt Prozess mit höchster Prio
    - es gibt präemptive und nicht präemptive Ansätze
- Wird in Echtzeitsystemen und vielen anderen verwendet
  - wichtige oder zeitkritische Aufgaben werden bevorzugt behandelt

## Zeitscheiben-Scheduling
- spezielle Form des [präemptiven Schedulings](#pr-emptives-scheduling)
  - Jeder Prozess wird für eine festgelegte Zeitscheibe auf dem Prozessor ausgeführt
    - sobald abgelaufen → nächster Prozess
    - wiederholt sich zyklisch
- Wird verwendet in
  - _Mehrbenutzersystemen_

## Weitere Scheduling-Strategien
- First Come First Served
- Shortest / Longest Process next
- Shortest / Longest Remaining Time next
- Highest Response Ratio next
- Earliest Deadline next
- [Fair-Share-Scheduling](#scheduling-unter-linux)
- Multilevel-Scheduling
- ...

## Scheduling unter Linux
![image_161.png](image_161.png)

[![Youtube: Linux Completely Fair Scheduler](http://i3.ytimg.com/vi/2UYuWWX3SMc/hqdefault.jpg)](https://www.youtube.com/watch?v=2UYuWWX3SMc)

### Completely Fair Scheduler (CFS)
- faire Verteilung der CPU-Ressourcen zwischen verschiedenen Prozessen oder Threads
- erstmals in Linux im Kernel 2.6.23
  - Bemühung **bessere Leistung** und **Gerechtigkeit** bei Verteilung von Ressourcen in Mehrbenutzersystemen
    - Implementierungen und genutzte Algorithmen können variieren

### Grundprinzipien des CFS
- **Fairness**
  - jeder ausführbare Prozess sollte proportional zur Anzahl der CPU-Ressourcen, die er benötigt, bedient werden
- **Keine festen Zeitscheiben**
  - Ausführungszeit wird dynamisch an Prozesse angepasst
- **Gewichtungen**
  - Prozesse mit höherem "Gewicht" erhalten größere Zeiteinteilung an CPU
- **Virtual Runtime** 
  - Gewicht und Ausführungszeit → vRuntime
    - Prozesse mit kürzerer vRuntime priorisiert
    - Entscheidungsstruktur: [Rot-Schwarz-Baum](https://de.wikipedia.org/wiki/Rot-Schwarz-Baum)
      - ![image_162.png](image_162.png)

### Beispiel Funktionsweise des CFS
![image_163.png](image_163.png)

- Neue Prozesse können während Latenz des Schedulers eingefügt werden
  - **vruntime** wird initialisiert mit minimaler Laufzeit (**min_vruntime**)der bereits vorhanden Tasks
  - weil jetzt ein zusätzlicher Task da ist, wird allen vorhandenen Tasks automatisch anteilig weniger Laufzeit zugeteilt
  - ![image_164.png](image_164.png)

> Manchmal möchte man die Priorität eines Prozesses verändern. Sie kann mit **nice** gesetzt werden
> und mit **renice** angepasst werden
> 
> Jeder Prozess kann einen [nice-Wert](#nicewert) von -20 bis 19(20) haben. Standard ist 0

### Berechnung der Gewichtung (CFS)
- **1024/1,25<sup>[niceWert](#nicewert)</sup>**
- Falls [niceWert](#nicewert) abnimmt, steigt Gewicht an
  - Zeitscheibe ist proportional zur Gewichtung dividiert durch Gesamtgewichtung aller Prozesse
    - ![image_165.png](image_165.png)

#### Beispiel
- 131 Tasks (nice = 0) → Gewicht w = 1024
- 20 Tasks (nice = -20) → Gewicht w = 88817,84

- Alle Tasks mit nice=0 belegen ca. 7% der CPU
  - $131*1024 / (131*1024 + 20*88817,84) → ca. 7%$
  - tun i.d.R nichts → genug runtime
- Alle Tasks mit $nice = -20$ belegen ca. 93% der CPU

### niceWert
Befehle mit [POSIX-API](06_prozessstruktur.md#posix-api)
- **setpriority** - niceLevel eines Prozesses setzen
- **getpriority** - niceLevel eines Prozesses lesen

## Real-Time Scheduling
- zielt darauf ab, dass Prozesse oder Aufgaben spezifische zeitliche Anforderungen erfüllen
- Bsp.:
  - Dekodierung von Bildern eines Videostreams
    - 30 Bilder / Sekunde
      - Jedes Bild muss in 1/30s dekodiert und angezeigt werden

- in **harten Echtzeitsystemen** müssen Aufgaben ihre zeitlichen Anforderungen strikt und zuverlässig erfüllen
  - bspw. Flugzeug, medizinische Geräte, ...
- _Scheduling-Algorithmen_
  - Rate Monotonic Scheduling (RMS)
  - Earliest Deadline First (EDF)

- in **weichen Echtzeitsystemen** sind zeitliche Anforderung auch wichtig, aber Versäumnis ist nicht katastrophal
  - bspw. Multimediale Anwendungen, Spiele
- _Scheduling-Algorithmen_
  - Weighted Fair Queuing (WFQ)
  - Proportional Share Scheduling