Systemprogrammierung (37-023) Assemblerprogrammierung Maschinenmodelle • 16 K System, 8 K Anwenderprogramme gespeichert auf 512 K Platte Dozent: • 1973 Reimplementation in C Prof. Thomas Stricker • Ab 1974 Verteilung des Systems weltweit an Universitäten und Industrie Unterrichtssprache: Deutsch Begleit-/Textbuch: R. P. Paul: SPARC Architecture, Assembly Language Programming and C, Prentice Hall, 1994 Heute: • 1977-1982 Entwicklung des UNIX System III bei AT&T und Portierungen • 1983 erste Version von System V • Berkeley Software Distribution (BSD) mit Systemen wie BSD4.2 oder BSD4.3 • Unix • 1984 bereits 100 000 Installationen • Processes • Problem der Standardisierung resultiert in IEEE POSIX Heute LINUX • Scheduling 37-023 Systemprogrammierung • 1965 MULTICS Projekt von AT&T Bell, GE und MIT • 1969 UNIX Version auf PDP 7/11 (Ken Thompson und Dennis Ritchie Betriebssystemgrundlagen 31.1.00 - 1 Geschichte von UNIX © Stricker 31.1.00 - 2 Struktur des UNIX Systems 37-023 Systemprogrammierung © Stricker Prozesse • Prozess als Instanz eines aktuell ausgeführten Programmes • Mehrere Instanzen desselben Programmes gleichzeitig ausführbar • system calls, um Prozesse zu synchronisieren, zu starten, zu beenden usw. • Beispiel: fork und execl • Ziel: Multiuser, Multiprozessor System • Innerer Layer, der KERNEL, stellt Interface zur HW bereit • Äusserer Layer von Programme, welche mit dem Kernel über system calls interagieren. • fork generiert einen child-Prozess • Viele dieser Programme stellen UNIX Kommandos (z.B. wc, grep) dar. • execl überlagert den Adressraum des child-Prozesses mit dem file copy und führt es mit entsprechenden Argumenten aus 31.1.00 - 3 31.1.00 - 4 37-023 Systemprogrammierung © Stricker 37-023 Systemprogrammierung © Stricker Der UNIX-Kernel • wait suspendiert den parent-Prozess bis copy beendet ist. • programmierbarer command line interpreter, auch shell (sh, csh, bash) genannt, liest Kommandos aus der command line und forkt in child-Prozesse zur Ausführung der Kdos (NICHT Bestandteil des Kernels) Aufgaben • Verwaltung und Überwachung von Prozessen gemäss zugewiesener Prioritäten • Verwaltung des physikalischen Adressraumes. • synchone und asynchrone Ausführung der Kommandos durch die shell (foreground <->background mit &) • Swapping out von Prozessen bei Platzbedarf im Hauptspeicher • Primitive zur Anweisung der shell, wie z. B. > oder |: • Paging out einzelner Seiten der Hauptspeichers • paging system versus swapping system a.out >dat ls -l | more • Verwaltung des File-Systems • Insbesondere | (pipe) Zeichen zum Aufbau eines Kommunikationskanal zwischen zwei Prozessen. Output des ersten wird als Input an den zweiten geschickt. • Zugriffstuerung auf periphere Geräte Vermeidung temporärer files. 31.1.00 - 5 37-023 Systemprogrammierung © Stricker Architektur des Kernels 31.1.00 - 6 37-023 Systemprogrammierung © Stricker Elementare Komponenten • Filesystem, Speicherverwaltung und Process control subsystem als elementare Komponenten • open, close, create, write, read usw. zur Anweisung des file subsystems • Zugriff erfolgt über buffering-Mechanismus zur Datenflusskontrolle von Block I/ O devices • device drivers (Treiber) zur Steuerung von Peripherie • system call und library interface als Schnittstelle zu Anwenderprogramm • system calls in höheren Sprachen über Library (C-Funktionen) • In Assembler direkt über traps 31.1.00 - 7 37-023 Systemprogrammierung © Stricker • fork, exec, exit, wait usw. zur Anweisung des process control subsystems • Scheduler allociert CPU für Prozesse • Verschiedene Inter Process Communication (IPC) Mechanismen, wie pipes, signals, sockets, shared memory etc. 31.1.00 - 8 37-023 Systemprogrammierung © Stricker UNIX Prozesse • Getrennte stacks für user und kernel modi eines jeden Prozesses • Prozess durch ausführbares Programm, Daten und Stack gekennzeichnet • Prozess ist in sich abgeschlossen und kann a priori nicht auf andere Prozesse zugreifen (IPC) • Wird durch fork generiert • Prozess durch Prozessnummer PID definiert • Ausführbares Program-file wird von kernel durch exec geladen, initialisiert (bss) und in Regionen, wie text, data und stack aufgeteilt. • Stack frames in bekannter Weise für user und kernel organisiert • traps zu Systemroutinen: user -> kernel mode (su) 31.1.00 - 9 37-023 Systemprogrammierung © Stricker 31.1.00 - 10 low level - Aspekte der Prozesse • zwei modi zur Ausführung von Prozessen:user und kernel mode • system call vergleichbar zu trap immer im kernel mode • kernal mode erlaubt Zugriff auf user und kernel Adressen 37-023 Systemprogrammierung © Stricker Kontext Switch • Die Umschaltung des kernels vom aktuellen auf einen anderen Prozess wird als Kontext switching bezeichnet • Prozess durch verschiedene states und state transitions gekenntzeichnet • su Maschineninstruktionen, die dem kernel mode vorbehalten bleiben (z. B. wrpsr) • kernel mode Prozesse werden von user mode Prozessen aus aufgerufen • Bei externen Interrupts speichert der kernel den aktuellen Kontext und bedient den Interrupt gemäss aktueller Priorität. • Modes: user, kernel, ready und sleep • Traps werden immer im Kontext des Prozesses ausgeführt, aus dem der trap aufgerufen wurde. 31.1.00 - 11 37-023 Systemprogrammierung © Stricker 31.1.00 - 12 37-023 Systemprogrammierung © Stricker Statusdiagramm eines Prozesses • Vollständiges Statusdiagramm umfasst insgesamt 9 Prozess-Stati Zustände eines Prozesses 1 Prozess in User Mode 2 Prozess in Kernel Mode 3 Prozess ist Ready to Run und wartet auf Scheduling 4 Prozess ist schlafend, aber resident im Hauptspeicher 5 Prozess ist Ready to Run, aber Swapper hat ihn auf sekundäres Medium ausgelagert 6 Prozess ist schlafend und vom Swapper ausgelagert 7 Prozess ist bei Rücksprung von Kernel in User Mode aufgrund eines Kontext Switches Preempted1 worden. Er wartet auf Scheduling 8 Prozess ist neu geschaffen worden und in einem Übergangszustand 9 Prozess hat exit() Call aufgerufen und ist im Zombie Zustand. Er hinterlässt noch Information zu exit und Timing, welche vom Vater gelesen werden kann. • Äquivalenz von Ready to Run und Preempted, jedoch explizite Unterscheidung aufgrund eingeschränktem Kontext Switching im Kernel Mode. • Eingeschränkte Kontrolle eines Prozesses über seine Zustandsübergänge 1. Preemption (wörtlich: Vorkaufsrecht) wird im Kontext von Multitasking verwendet. Man unterscheidet hier zwischen preemptivem und nicht-preemptivem Multitasking. Beim preemptiven Multitasking können Prozesse vom Scheduler unterbrochen werden, wogegen beim nicht-preemptiven Multitasking der Prozess die CPU freiwillig freigeben muss.. 31.1.00 - 13 37-023 Systemprogrammierung © Stricker Kernel Datenstrukt. für Prozesse 31.1.00 - 14 37-023 Systemprogrammierung © Stricker • Elementare Kernel Datenstrukturen Process Table und u_area • Process Table mit Statusinformation, Lage im Hauptspeicher etc. • u_area enthält Zugriffsrechte, Signalmaskierung, Returns von System Calls, File Offsets, Open Files • process table als Struktur in /sys/proc.h typedef struct proc { char p_stat; /* status of process. */ char p_cpu; /* cpu usage for scheduling */ char p_nice; /* nice for cpu usage */ char p_time; /* resident time for scheduling */ uint p_flag; /* flags defined below. */ gid_t p_pgrp; /* name of process group leader */ pid_t p_pid; /* unique process id */ pid_t p_ppid; /* process id of parent*/ struct proc *p_flink; /* linked list of sleeping p’s */ struct proc *p_blink; /* linked list of sleeping procs*/ caddr_t p_wchan;/* Wait addr for sleeping procs */ caddr_t p_w2chan; /* Wait addr for sleeping p’s */ lock_t p_parlck; /* lock to protect p_parent */ struct proc *p_parent; /* ptr to parent process */ struct proc *p_child; ........................... 31.1.00 - 15 37-023 Systemprogrammierung © Stricker • region table als zusammenhängender Bereich des Adressraumes eines jeden Prozesses, wie text, data • Attribute für regions, wie private, shared... • Bei Aufruf von exec wird Adressraum vom kernel allociert 31.1.00 - 16 37-023 Systemprogrammierung © Stricker Der Kontext eines Prozesses • Kontext als Summe aller relevanter Daten und Zustände eines Prozesses • Wird unterteilt in User Kontext, System Kontext und Register Kontext • User Kontext durch Speichersegmente, wie Text, Data, Stack oder Shared Memory beschrieben • Register Kontext durch Registerinhalte des Prozessors, wie %sp, PSR, etc. • System Kontext besteht aus Process Table, u_area, Process Region und Konsistenz der Datenstrukturen • Zur Wahrung der Konsistenz von kernel Datenstrukturen ist Kontext switching im kernel mode nur eingeschränkt möglich Beispiel: • Kontext switching oder Interrupt während der Manipulation einer verketteten Liste • Möglichkeit: Liste ist nicht mehr in konsistentem Zustand • Lösung: kernel maskiert Interrupts während der Ausführung von kritischen Code-Passagen Notwendige Kontext Switches: • sleep modus, wenn Prozesse auf events warten, wie z. B. I/O. • Bei Auftreten des events weckt der kernel den Prozess auf ->ready to run 31.1.00 - 17 37-023 Systemprogrammierung © Stricker 31.1.00 - 18 37-023 Systemprogrammierung © Stricker Scheduling • Beispiel: locking und freigeben von Datenstukturen des kernels • Individuellen Prozessen wird vom Scheduler gemäss einer vordefinierten Strategie ein CPU Zeitfenster zugeordnet • Die Verwaltung übernimmt ein sog. Scheduler (je nach UNIX PID 0) • Bei Kontext Switching wird Prozess mit aktuell höchster Priorität ausgewählt. • Prozesspriorität wird dynamisch, aus der aktuellen CPU Zeit ermittelt • Bei jedem Rücksprung vom Kernel in User Mode wird Prozesspriorität neu berechnet und ev. der Proz. gewechselt. • Datenstrukturen des kernels sehr einfach als Tabellen fester Grösse -> effiziente, kompakte Implementierung • Neuberechnung aller Prozessprioritäten im Ready-to-Run Status periodisch • Konfiguration des Kernels beim Compilieren-> LINUX Installation • Kontext Switch erfolgt nach Ablauf eines Zeitfenster. Dann wird Prozess in eine Warteschlange (Priority Queue) gemäss aktueller Priorität eingeordnet. 31.1.00 - 19 31.1.00 - 20 37-023 Systemprogrammierung © Stricker 37-023 Systemprogrammierung © Stricker Scheduling Algorithmus Scheduling Parameter • Bei Kontext Switching wird Prozess mit höchster Priorität ausgewählt, welcher resident im Hauptspeicher ist (Ready to Run oder Preempted) • Pozesspriorität dynamisch als Funktion der Vorgeschichte berechnet • Bei gleicher Priorität wird derjenige genommen, der am längsten wartet • Wenn kein Prozess bereit, -> idle bis zum nächsten clock interrupt • Prozess-Tabelle enthält ein entsprechendes Priority Field • Es wird zwischen Kernel und User Priorität unterschieden • Für jede Prioritätsklasse ist getrennt Queue vorhanden, in die aktuelle Prozesse eingeschrieben werden • Kernel Mode Prozesse mit geringerer Priorität können durch Signale unterbro- 31.1.00 - 21 37-023 Systemprogrammierung © Stricker chen werden 31.1.00 - 22 37-023 Systemprogrammierung © Stricker • Bei jedem Rücksprung von Kernel in User Mode wird Priorität neuberechnet • Hierbei können verschiedene Strategien verwendet werden (fair scheduling). Insbesondere muss die Vorgeschichte, verbrauchte Ressourcen etc. mit in den Algorithmus einfliessen. • Clock Handler verändert die Prioritäten aller User Mode Prozesse 1 mal pro Sekunde (SV). • Prozesspriorität wird vom Kernel nach folgenden Regeln berechnet: • Beim Übergang in den Sleep-Zustand wird dem Prozess eine feste Priorität zugewiesen, welche NICHT von seiner Vorgeschichte abhängt. • Hierbei hat z. B. Sleep on Disk I/O eine höhere Priorität, als Terminal Input 31.1.00 - 23 37-023 Systemprogrammierung © Stricker • Dazu wird mehrmals pro Sekunde (60) ein entsprechender Clock Interrupt generiert und beim Justieren ein Eintrag (CPU Usage) in der Prozess-Tabelle inkrementiert • Für wartende Prozesse wird CPU mit einem decay beaufschlagt: decay(CPU) = CPU/2 • Neuberechnung der Priorität aller wartenden Prozesse gemäss priority = („recent CPU usage“/2) + (base level user priority) 31.1.00 - 24 37-023 Systemprogrammierung © Stricker • Base Level User Priority ist die Grenze zwischen User und Kernel Prioritäten Beispiel für UNIX Scheduler • Geringer Wert typischerweise hohe Priorität • Priorität von Kernel Mode Prozessen wird dabei nicht neuberechnet • Wichtig: Clock Interrupt wird nicht immer zeitgenau behandelt, da aktueller Prozess durchaus in kritischem CodeSegment sein kann. • Beispiel: Scheduling von 3 Prozessen A, B, C • Clock Interrupt 60 mal pro Sekunde, Justierung erfolgt einmal pro Sekunde • Prozess A wird zu Beginn geschedult mit Priorität 60, läuft für eine Sekunde und wird dann unterbrochen, neue Priorität 60 + 60/4 = 75 • Danach wird B abgearbeitet usw. 31.1.00 - 25 37-023 Systemprogrammierung © Stricker 31.1.00 - 26 37-023 Systemprogrammierung © Stricker