Prozesse und Scheduling unter Linux (Kernel 2.4.XX)

Prozesse und Scheduling unter Linux (Kernel 2.4.XX) Vorlesung: Dozent: Betriebssysteme Odej Kao Vortragende: Andrè Neubert Alexander Geburzi Überb...
Author: Sven Günther
0 downloads 1 Views 124KB Size
Prozesse und Scheduling unter Linux (Kernel 2.4.XX) Vorlesung: Dozent:

Betriebssysteme Odej Kao

Vortragende: Andrè Neubert Alexander Geburzi

Überblick 1. • • •

2. • • •

3. • • •

Prozesse unter Linux ProcessControlBlock Prozessliste / PID-Hashing Prozesshierarchie Lebenslauf von Prozessen Erzeugung & RunQueue / WaitQueues Prozess-Zustände Beenden & Zerstören von Prozessen Scheduling unter Linux Allgemeines Strategie Der Scheduler

Prozesse unter Linux (1) task_struct

ProcessControlBlock (PCB)

volatile long state; Zustandsinformationen

Struktur vom Typ task_struct (derzeit 1680Bytes groß ) Teilweise Integerwerte, enthaltene Strukturen oder Zeiger auf solche Max. Anzahl von Prozessen nur durch die Größe des Hauptspeichers begrenzt seit Kernel 2.4 (512MB RAM = 32k Prozesse) Zusammen mit Prozess-KernelStack in einer 8 KByte großen Seite gespeichert

unsigned long flags; pid_t pid; struct list_head run_list

Prozessverwaltung

struct task_struct *next_task, *prev_task; struct task_struct *pidhash_next; struct task_struct **pidhash_pprev; struct task_struct *p_opptr, *p_pptr;

Prozessbeziehungen

struct task_struct *p_cptr, *p_ysptr, *p_osptr;

Benutzerkontext

struct user_struct *user;

Dateisystem

struct fs_struct *fs;

geö geöffnete Dateien

struct files_struct *files;

Speicherbereich

struct mm_struct *mm; volatile long need_resched; long counter;

Scheduling

unsigned long policy; long nice; unsigned long rt_priority;





Prozesse unter Linux (2) Prozessliste Doppelt verketteten Ringliste von PCBs Zeiger auf Vorgänger *prev_task und Nachfolger *next_task Der Init_Task (PID 1) bildet Anfang und Ende PID-Hashing Lineares Suchen eines Prozesses zu aufwendig Nahezu konstanter Zugriff durch Hashtable (1024 Einträge) PIDs durch das pid_hashfn(x)-Makro in Klassen unterteilt Einträge sind doppelt verkettete PCB-Listen aller Prozesse aus der korrespondierenden Klasse Realisiert durch die Zeiger *pidhash_next, **pidhash_pprev

Prozesse unter Linux (3) Prozesshierarchie Idle_Task (PID 0) „

„

Wird als erster Prozess von Hand durch INIT_TASK(tsk)-Makro während der Initialisierung von Linux erzeugt Ruft später immer wieder idle() auf um den Prozessor freizugeben

KernelThreads „ „ „ „

Erledigen sog. Kerndienste z.B. Pageframe-Swapping, Netzwerk Besitzen daher bestimmte Privilegien z.B. I/O privileged benutzen Adressraum des Kernels Ö Leichtgewichtsprozesse z.B. Init_Task (PID 1) u.a. Zerstörung elternloser Prozesse

UserTasks „ „

Normalen Prozesse des Linux-System Klassischer Unix-Prozess

Lebenslauf von Prozessen (1) Erzeugung von Prozessen mit do_fork() PCB des Vaterprozess wird in ein neues task_struct kopiert Referenzzähler werden erhöht, Flags werden gesetzt Neue Prozesse zunächst im Zustand Task_Uninterruptible Neue PID ermitteln, in Hashtable einfügen und Anzahl der aktiven Prozesse erhöhen Zustand auf Task_Running setzen und seine PID an Vater zurückgeben

RunQueue Enthält Prozesse im Zustand Task_Running Doppelt verkettete Liste mit Zeigern auf vorherigen und nächsten Prozess

WaitQueues Task_Interruptible und Task_Uninterruptible allein zu ungenau Unterschiedliche Listen je nach Art und Kontext des Wartezustandes

Lebenslauf von Prozessen (2) Prozess-Zustände Task_Running • •

Besitzt entweder gerade die CPU oder wartet auf Zuteilung vom Scheduler Befindet sich in der RunQueue

Task_Interruptible •

Wartet auf Ereignis z.B. HardwareInterrupt, Verfüg. einer Systemressource, Signal

Task_Uninterruptible • Wie Task_Interruptible, kann nur nicht geweckt werden bei beiden befindet sich der Prozess in entsprechenden WaitQueues

Task_Zombie • • •

Beendet, aber Vaterprozess hat noch keine Infos vom toten Prozess abgerufen Erst nach Abfrage oder Tot des Vaterprozesses kann er entfernt werden Wird aber schon aus RunQueue / WaitQueues entfernt

Task_Stopped •

Wurde durch überwachenden Prozess (z.B. mittels ptrace()) angehalten

Task_Exclusive •

Bevorzugte Behandlung beim Aufwecken

Lebenslauf von Prozessen (3) Zombie

Interruptible exit()

fork()

I/O

Running

ptrace()

Stopped

usleep()

Uninterruptible

Lebenslauf von Prozessen (4) Beendigung von Prozessen mit do_exit() Benutzte Datenstrukturen entfernen, Referenzzähler dekrementieren Exit-Code setzen, Verwandte benachrichtigen „ „

Kinder erhalten PID 1 als Vaterprozess Vaterprozess erhält Signal SIGCHL

Init_Task erbt Kindsprozesse Ö sauberes Entfernen nach Beendigung Zustand Task_Zombie, Aufruf des Schedulers

Zerstören von Prozessen mit release_task() Anzahl der Benutzerprozesse dekrementieren Prozess aus Hashtable entfernen Nichtverbrauchte CPU-Zeit verschenken PID auf 0 gesetzt Vom Prozess belegte Speicherseite wird freigegeben

Scheduling unter Linux Zeitscheibenverfahren und Prioritäten (statisch u. dynamisch) Epochen „

„

Zu Beginn erhält jeder Prozess eine max. Laufzeit (abhängig von statischer und dynamischer Priorität) Endet, wenn alle lauffähigen Prozesse Laufzeit abgearbeitet haben

Unterbrechung durch Timer-Interrupt (x86 Systeme 10ms) Berücksichtigt sowohl Echtzeitprozesse als auch interaktive bzw. Batch-Prozesse Kernel ist non-preemptive „ „

Nur UL Prozesse können unterbrochen werden KL Prozesse nicht

Die Strategie Realisiert drei verschiedene Schedulingverfahren (FIFO, RR, Multi-Level-Feedback) Jeder Prozess kann festlegen, welches Verfahren für ihn verwendet werden soll Alle aktuell lauffähigen Prozesse werden in einer RunQueue organisiert

Strategie SCHED_FIFO SCHED_FIFO: • FIFO-Prinzip • Echtzeitprozess • benötigt Superuser-Privilegien • Abgabe der CPU: bei Aktivierung eines Prozesses mit höherer „ Priorität bei Aufruf einer I/O-blockierenden Operation „ durch eigene Freigabe (Yield) „

Strategie SCHED_RR • • • •

SCHED_RR: Round-Robin Echtzeitprozess Benötigt Superuser-Privilegien Abgabe der CPU: Bei Aktivierung eines Prozesses mit höherer Priorität Bei Aufruf einer I/O-blockierenden Operation Durch eigene Freigabe (Yield) Nach Ablauf der Zeiteinheiten

Strategie SCHED_OTHER • • •

SCHED_OTHER: Multi-Level-Feedback „normale“ Prozesse Abgabe der CPU: Bei Aktivierung eines Prozesses mit höherer Priorität Bei Aufruf einer I/O-blockierenden Operation Durch eigene Freigabe (Yield) Nach Ablauf der Zeiteinheiten

Der Scheduler Scheduler bestimmt, welchem Prozess aus der RunQueue als nächstes die CPU-Zeit zugewiesen werden soll Er muss dabei die drei verschiedenen Strategien berücksichtigen Bewertet jeden Prozess mit Hilfe der Funktion goodness() Evtl. wird dabei eine neue Epoche eingeleitet und alle SCHED_RR und SCHED_OTHER erhalten neue Zeiteinheiten: counter = counter / 2 + nice Der Prozess mit dem größten Wert erhält den Zuschlag Evtl. vor dem Umschalten organisatorische Dinge erledigen

Die goodness() -Funktion Bewertet einen Prozess folgendermaßen:

• •

Flag SCHED_YIELD gesetzt: -1 SCHED_FIFO oder SCHED_RR: 1000 + rt_priority SCHED_OTHER: 0, wenn alle Zeiteinheiten verbraucht sind Sonst Summe aus counter, der statischen Priorität (nice) und evtl. einem Bonus von 1, falls der Prozess denselben Adressraum hat wie der abzulösende Prozess