Rechnerarchitekturen und Betriebssysteme (CS201): Scheduling, Consumer/Producer, kritisch. Abschnitt 14. November 2014 Prof. Dr. Christian Tschudin Departement Mathematik und Informatik, Universität Basel Repetition und Diskussion • Was ist ein Batch (Betriebs-) System? • Was sind “privilegierte (CPU-) Instruktionen”? • Was ist ein “Supervisory Call”? c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 2/28 schedule() Die Implementierung von schedule() ist ein “Behelf”. • Gutes Scheduling ist Match-Entscheidend • Vielfältige Orte (in einem OS), wo Scheduling-Entscheide getroffen werden müssen. • Im Folgenden eine Annäherung an die Problematik. c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 3/28 Was ist “Scheduling”? Gegeben: eine Ressource, viele Anfragen/Reservationen Frage: Service in welcher Reihenfolge anbieten? Ein Scheduling–Problem aus dem Alltag: Rotlicht • Ressource = (Platz auf der) Kreuzung • Wie lange soll eine Richtung “grün” bekommen? Problem: Finde eine optimale Allokations-Strategie c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 4/28 Scheduling Beispiel I: CPU Ressource = CPU in einem Multiuser-System • Mehrere Prozesse sind “ready”, d.h. ausführbar • Scheduler muss den nächsten Prozess bestimmen • Schlechtes Scheduling: – Passwort-Cracking SW erhält einen 5-Sekunden-Slot → interaktive User sehen einen “eingefrorenen” Computer Obwohl: Diese Zuteilung ist effizient (spart 250 Context-Switches) c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 5/28 Preemptive Scheduling • Die CPU wird ein ‘time quanta’ / ’time slot’ zugeteilt, Typisch: 1/50 sec, bzw 10ms < quantum < 100ms (auch ‘time sharing system’ genannt) • Das Betriebssystem: – unterbricht den Prozess am Ende des Zeit-Quantum (preemption – nimmt die CPU weg) – alloziert die CPU neu – führt einen “context switch” zu einem ausgewählten Prozess (dispatching) c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 6/28 Round–Robin Scheduling PCB PCB PCB Kommt ans Ende der Queue nach dem Quantum PCB Kopf der "ready"−Queue (erhält CPU) • First-in-first-out (FIFO) Warteschlange von “ready”-Prozessen • Der vorderste Prozess (PCB=control block) erhält CPU, rechnet. • Nach Zeit-Quantum: Wird ans Ende der “run queue” gesetzt • Eigenschaften: – einfach und einleuchtend ! – Aber: kein sehr “reaktives” System! 50 interaktive Users, 20ms Quantum → bis zu 1 sec Wartezeit c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 7/28 Priorisierte Warteschlangen Wie kann Round–Robin “flinker” gemacht werden? Klassifikation von Prozessen. • Interaktive Jobs: kurze CPU-Spitzen, gefolgt von “I/O-blockiert” • I/O limitierte Jobs (IO-bound): Intensives I/O, wenig Berechnung (zB Datei kopieren) • CPU-limitierte Jobs (CPU-bound): hauptsächlich CPU, wenig Ein-/Ausgabe 1 Round–Robin Queue pro Klasse, Prozesse dynamisch zugeordnet c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 8/28 CPU Scheduling in Linux (<= 2.4.x) Das Time–Sharing Scheduling (von Linux) beruht(e) auf “Krediten” • Verfahren: – Prozess mit dem höchsten Kredit wird ausgewählt, – Jedes Quantum kostet einen Kreditpunkt, – Re-Evaluation am Ende des Quantum • Falls kein “ready”-Prozess mehr Kredit hat: neue Punkte verteilen credits = credits + priority ∀ processes 2 • Diese Formel preist mehrere Faktoren ein: Priorität, bisheriges Verhalten, Alterung c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 9/28 Randnotiz zu “nice” von UNIX • Kommando “nice” erlaubt das Setzen der Priorität: – -20 = höchste, 19 = niedrigste Priorität – normaler Prozess kann eigene Priorität nur herabsetzen • Beispiel: % nice -10 make bzImage • In Linux (/usr/src/linux-2.4.25/kernel/sched.c): #define NICE_TO_TICKS(nice) (TICK_SCALE(20-(nice))+1) for_each_task(p) p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); Wörtlich: “Kreditwährungseinheit” ist ein Zeitquantum c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 10/28 O(1)-CPU Scheduling in Linux >= 2.5.2 Problem mit vorherigem Ansatz: O(n), dazu kommen noch 100 “real-time”-Prioritäten, alles in einer “run queue” verborgen 2 Bit-Arrays, Bit für Priorität • erste Tabelle zum Auswählen, Bit löschen • zweite Tabelle für neue Priorität • Wenn die erste Tabelle leer ist, werden Sie ausgetauscht Siehe: http://www.samspublishing.com/articles/article.asp?p=101760 c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 11/28 Scheduling Beispiel II: Disk Ressource = Harddisk eines PCs • Mehrere Read-Anforderungen für spezif. Zylinder sind hängig • Scheduler bestimmt den nächsten zu lesenden Zylinder • Zwei mögliche Abfolgen: Seien Anforderung angefallen für Zyl: 35, 78, 25 und 15, und HD-Kopf stehe auf Zyl 1 – First–come–first–serve (FCFS): 1 35 78 25 15 – “Elevator”: 1 15 25 35 78 c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 12/28 Scheduling Beispiel III: Netzwerk Router Ressource = ausgehende Datenleitung, begrenzte Kapazität • Warteschlange einkommender Pakete: in welcher Reihenfolge weitersenden? • Verschiedene “packet schedulers” im Einsatz: – first-come-first-serve (FCFS) – “weighted fair queueing” (zB wichtig für Telephonie) • Je besser das Scheduling in den einzelnen Knoten, umso gleichmässiger der Verkehrfluss im Netz → Netzwerk-Vorlesung CS262 im Frühlingssemester c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 13/28 Andere Scheduler–Typen und –Algorithmen • Batch Job Scheduling • FCFS (first–come–first–serve) • Real–Time Scheduling (mit Zeit-Garantien), z.B. EDF (earliest deadline first) • SJF (shortest–job–first) • Lottery scheduling • (ökonomische) Abgebot-Nachfrage-Modelle c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 14/28 Scheduling durch eine Lotterie • Jeder Prozess hat eine Anzahl von Lotterie-Tickets • Am Ende jedes Quantum wird eine Lotterie veranstaltet • Der Prozess mit dem Siegerticket erhält das nächste Quantum Gute Eigenschaften: • (Statistisch) faire CPU-Allokation, entsprechend den Tickets • Einfach zu implementieren Nachteil: unvorhersehbare Verzögerungen (z.B. für interaktive Anwendungen) c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 15/28 Zusammenfassung zu Scheduling Scheduling in einem Betriebssystem hat 2 Aspekte: man muss (sehr schnell) Entscheide treffen über • die Reihenfolge, in welcher Anfragen bedient werden • die Rate, mit welcher eine Ressource alloziert wird (dynamische Neuzuteilung von Prioritäten!) Scheduling ist ein Optimierungsproblem . . . • und stark abhängig vom Kontext. c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 16/28 Koordination kooperierender Prozesse – Einführung Konfiguration: – Prozess A produziert Daten – Prozess B konsumiert sie Beispiel: eine UNIX-“Pipe” wie in ls | wc Problem: Der OS-Kernel hat nur beschränkten Pufferplatz • A muss bei einem “write” überprüfen, ob genügend Platz vorhanden ist. Falls nicht, muss A sich blockieren • B muss bei einem “read” überprüfen, ob Daten vorhanden sind. Falls nicht, muss B sich blockieren c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 17/28 Producer/Consumer Code–Grundstruktur: /* Producer A: */ /* Consumer B: */ for (;;) { d = new_data(); while (buf.size == MAX) {} buf.data[ buf.in ] = d; buf.in = (buf.in + 1) % MAX; buf.size = buf.size + 1; for (;;) { } } while (buf.size == 0) {} d = buf.data[ buf.out ]; buf.out = (buf.out + 1) % MAX; buf.size = buf.size - 1; /* process data item d */ (Randbemerkung: “busy-loop”/polling ist unschön) c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 18/28 Producer/Consumer II: Nebenläufige Ausführung Falls A und B ihren buf.size–Befehl “gleichzeitig” ausführen, kann buf.size falsche Werte annehmen! • Hochsprachenbefehle sind nicht “unteilbar” (atomic): sie bestehen aus mehrere Assembler-Instruktionen lds r24,buf.size lds r25,(buf.size)+1 adiw r24,1 sts (buf.size)+1,r25 sts buf.size,r24 lds r24,buf.size lds r25,(buf.size)+1 adiw r24,-1 sts (buf.size)+1,r25 sts buf.size,r24 • Interrupt kann während der Ausführung des Befehls eintreffen: → Teile davon werden im nächsten Quantum abgearbeitet c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 19/28 Producer/Consumer III: Unfall! (Sei buf.size > 0) lds r24,size lds r25,(size)+1 adiw r24,1 ; ------- timer interrupt! -->-->--> wir führen Contextswitch durch lds r24,size lds r25,(size)+1 adiw r24,-1 sts (size)+1,r25 sts size,r24 ; ------- timer interrupt! <--<--<-- wir führen Contextswitch durch sts (size)+1,r25 sts size,r24 buf.size hat zu grossen Wert – die Subtraktion ging verloren! c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 20/28 Kritischer Abschnitt (Critical Section) Um dieses Problem zu lösen: • Einführen einer “Critical Section” – bezieht sich auf eine Ressource – im Prod/Cons-Beispiel: Zugriff auf Variable buf.size • Innerhalb eines kritischen Abschnitts: – Garantie, dass nur 1 Prozess “in diesem Abschnitt ist” Ziel: Gesamtapplikation verhält sich korrekt, wenn lokale Zugriffskonflikte gelöst sind. c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 21/28 Problemstellung “Critical-Section” • N Prozesse, Wettkampf um Zugang zu gemeinsamen Daten • Jeder Prozess hat einen Code-Passage, “kritischer Abschnitt” genannt, in der auf die gemeinsamen Daten zugegriffen wird. Zugriff soll exklusiv sein. • Ansatz: Eingangs- und Ausgangscode schreiben, um Prozess gegebenenfalls aufzuhalten bzw. das Abschnittende anzuzeigen. do { ENTRY_CRITICAL_SECTION critical section EXIT_CRITICAL_SECTION } while (TRUE); c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 22/28 Eigenschaften eines kritischen Abschnitts • Gegenseitiger Ausschuss – Ausschliessen, dass mehr als 1 Prozess gleichzeitig seinen kritischen Abschnitt ausführt. • Fortschritt – Wenn kein anderer Prozess den kritischen Abschnitt ausführt, wird ein Anwärter (zwar nicht unbedingt sofort, aber) auf jeden Fall seinen kritischen Abschnitt ausführen können. • Limitiertes “Hintenanstehen” – Wenn auch andere Prozesse ihren kritischen Abschnitt ausführen wollen, kann ein Anwärter nicht beliebig oft hinten angestellt werden. c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 23/28 Kritischer Abschnitt, Versuch 1 Im folgenden: nur zwei konkurrierende Prozesse P0 und P1 • Globale Variable int belegung = 0; (d.h.: belegung == i → Pi kann krit. Abschnitt ausführen.) • do { // Code für Prozess Pi while (belegung != i) {} critical section belegung = 1 - i; } while (TRUE); Bewertung: Exklusive Ausführung ist OK, aber Fortschritt verletzt (z.B. P1). c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 24/28 Kritischer Abschnitt, Versuch 2 • Globale Variable int zugang[2] = FALSE, FALSE; (d.h.: zugang[i] == TRUE → Pi will krit. Abschnitt ausführen.) • do { // Code für Prozess Pi zugang[i] = TRUE; while (zugang[1-i] == TRUE) {} critical section zugang[i] = FALSE; } while (TRUE); Exklusive Ausführung ist OK, Fortschritt weiterhin verletzt (falls beide den Zugang gleichzeitig reservieren). c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 25/28 Kritischer Abschnitt, Versuch 3 (Kombination von 1+2) • Globale Variablen int zugang[2] = FALSE, FALSE; int belegung = 0; • do { // Code für Prozess Pi zugang[i] = TRUE; belegung = 1-i; while (zugang[1-i] == TRUE && belegung == (1-i)) {} critical section zugang[i] = FALSE; } while (TRUE); Dies löst das Problem des kritischen Abschnitts: Peterson, 1981 c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 26/28 Korrektheit des Peterson-Algorithmus • Im krit. Abschnitt ist immer zugang[0] == zugang[1] == TRUE. Falls beide Prozesse den Zugang beantragen: Die While-Schleife kann nur von einem Prozess beendet werden, da belegung nur einen der Werte 0 oder 1 annehmen kann. • Prozess P0 kann nur dann unendlich lang aufgehalten werden, wenn seine while-Schlaufe nicht endet. Entweder ist P1 nicht im Abschnitt, oder ist drin: in beiden Fällen ist eine der Bedingungen der while-Schleife von P0 nicht erfüllt. • Wenn P0 den Abschnitt verlässt, und P1 wartete, und P0 gleich wieder eintreten will, wird er zuerst P1 den Zugang gewähren. c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 27/28 Einschub OSC-Slides (altes Kapitel 6): • Synchronisationsunterstützung in HW: Test-and-set • Semaphore Konzept, und blockierende Implementierung • Klassische Synchronisationsprobleme – Bounded Buffer, Reader/Writer, Dining Philosophers c Christian Tschudin CS201 – Rechnerarchitekturen und Betriebssysteme, 2014-11-14, 28/28