Verteilte Echtzeit-SystemeŸerdem kurz: HARTIK u. SHaRK (verwandte funktionsfähige Kerne) Dabei:...
Transcript of Verteilte Echtzeit-SystemeŸerdem kurz: HARTIK u. SHaRK (verwandte funktionsfähige Kerne) Dabei:...
CSI
Technische Universität Ilmenau
www.tu-ilmenau.de
-
Verteilte Echtzeit-Systeme
Hans-Albrecht Schindler
Wintersemester 2018/19
Teil C: Echtzeit-Betriebssysteme
Abschnitt 15:
Beispiel für einfache Echtzeit-Exekutive
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 2
Echtzeit-Exekutive entsprechend Abschnitt 6/Folie 25:
kleiner Betriebssystem-Kernel, ohne z.B. Primärspeicherverwaltung u.
Sekundärspeicherverwaltung (Dateisystem)
15.1 Einleitende Bemerkungen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.1 Einleitende Bemerkungen
Echtzeit-Executiven
... stellen 3 wesentliche Funktionen für (dann) vollständige Prozesse –
mit oder ohne Thread-Konzept – zur Verfügung:
1. Scheduling
2. Dispatching
3. Interprozess-Kommunikation u. Synchronisation
sowie:
4. Adressräume
5. Ein-/Ausgabe-Dienste
Varianten von Echtzeit-Betriebssystemen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 3
Einleitende Bemerkungen
Betriebssystem-Kern(el)
„innerster“ Teil eines Betriebssystems, der
im Kernel-Modus (Supervisor-Modus) des Prozessors läuft – und
unmittelbar auf Hardware der physischen Maschine aufsetzt
Wesentlich:
hat: Vorrechte gegenüber anderen Software-Komponenten
bildlich: eine Art Regierung, Schiedsrichter etc.
stellt mindestens folgende Betriebssystem-Funktionalität zur
Verfügung:
1. Prozess-Management (einschließlich Scheduling u.
Dispatching)
2. Interrupt-Behandlung
3. Interprozess-Kommunikation u. –synchronisation
bzw. je nach Typ des Kernels nur Grundfunktionen dazu
(vergleiche z.B. Mikrokern)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.1 Einleitende Bemerkungen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 4
Besprochenes Beispiel
Struktur u. Hauptkomponenten einer kleinen Echtzeit-Executive am
Beispiel DICK (DIdactic C Kernel) nach [Buttazzo97],
außerdem kurz: HARTIK u. SHaRK (verwandte funktionsfähige Kerne)
Dabei:
besonders auf notwendige (bzw. sinnvolle) Unterschiede zu üblichen
Nicht-Echtzeit-Betriebssystemen eingegangen
Diese Unterschiede:
dienen hauptsächlich wichtigstem Ziel bei Echtzeit-
Betriebssystemen:
Vermeidung unkontrollierbarer/unvorhersagbarer
Verzögerungen der Prozessbearbeitung (zeitliche
Nichtdeterminismen)
Einleitende Bemerkungen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.1 Einleitende Bemerkungen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 5
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
AufrufeService-
Schicht
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
15.2 Struktur u. Funktionsblöcke von DICK
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwaltungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
L3a L3b L3c
15. Einfache Echtzeit-Exekutive (Kernel) / 15.2 Struktur u. Funktionsblöcke
Bild 15-1: Struktur und Komponenten von DICK
DICK
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 6
Funktionsblöcke
DICK: Funktionsblöcke
1. Maschinennahe Schicht• direkte Interaktionen mit Rechnerhardware (Interrupts etc.)
2. Verwaltungsstrukturen-Schicht• insbesondere: Management diverser Warteschlangen
(Warteschlangen für rechenbereite Prozesse, für blockierte
Prozesse usw.)
3. Prozessor-Management-Schicht• Prozess-Scheduling und -Dispatching (= unmittelbare Prozess-
Zuordnung)
4. Service-Schicht• alle Dienste, die auf Nutzerebene als Menge von Systemaufrufen
sichtbar (API), typisch:
Prozess-Erzeugung u. Beendigung
spezielle Operationen für periodische Prozesse
15. Einfache Echtzeit-Exekutive (Kernel) / 15.2 Struktur u. Funktionsblöcke
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 7
DICK: Definitionen
grundlegende Definitionen als include-Datei:
// DATEN-TYPEN
typedef int queue; // Kopf-Index einer Warteschlange
typedef int sem; // Semaphor-Index
typedef int proc; // Prozess-Index
typedef int cab; // Index für cab-Puffer
typedef char* pointer; // Speicherplatz-Zeiger
// GLOBALE KONSTANTEN
#define MAXLEN 12 // maximale String-Länge
#define MAXPROC 32 // maximale Prozessanzahl
#define MAXSEM 32 // maximale Semaphoranzahl
#define MAXDLINE 0x7FFFFFFF // maximal mögliche Frist
#define PRT_LEV 255 // Anzahl Prioritätsebenen
#define NIL -1 // Null-Zeiger
#define TRUE 1
#define FALSE 0
#define LIFETIME MAXDLINE - PRT_LEV
15.3 Basisdefinitionen & Initialisierung bei DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
// zur Simulation v. Bool‘schen Variablen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 8
Definitionen
// PROZESS-TYPEN
#define HARD 1 // harter Echtzeitprozess
#define NRT 2 // Nicht-Echtzeitprozess
// PROZESS-ZUSTAENDE
#define FREE 0 // PCP nicht zugeordnet (kein Zustand)
#define READY 1 // bereit
#define EXE 2 // Prozess „läuft“ („executing“)
#define SLEEP 3 // Prozess „schläft“
#define IDLE 4 // Idle-Zustand
#define BLOCKED 5 // Prozess blockiert
#define ZOMBIE 6 // Zombie-Zustand
(vergleiche dazu auch: Abschnitt 15.11: DICK-Prozess-Management
u. Bild 15-13: Prozesszustandsdiagramm)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
DICK: Definitionen
Definitionen für Prozesse (1)
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 9
// Prozess-Kontroll-Block (PCB) – andere Bezeichnung: Prozess-Deskriptor
struct pcb{
char name[MAXLEN +1]; // Prozess-Name
proc (*addr)(); // Adresse des ersten Befehls
int type; // Typ des Prozesses
int state; // Prozess-Zustand
long dline; // absolute Frist
int period; // Periodendauer
int prt; // Prioritaet
int wcet; // „worst case execution time“ (WCET)
float util; // Prozessor-Auslastungsfaktor
int *context; // Zeiger auf Prozess-Kontext
proc next; // Zeiger auf nächsten PCB
proc prev; // Zeiger auf vorhergehenden PCB
};
struct pcb vdes[MAXPROC]; // Array von PCBs
Definitionen
DICK: Definitionen
Definitionen für Prozesse (2)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
(vergl. auch Bild 15-2)
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 10
Definitionen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Prozess-Name
Adr. 1. Befehl
Prozess-Typ
Prozess-Zustand
Frist
Periodendauer
WCET
Prozessor-Auslastung Zeiger auf
Prozesskontext
Zeiger zum
nächsten PCB
Zeiger zum
vorhergehenden
PCB
Bild 15-2: Prozess-Deskriptor (Prozess-Kontrollblock PCB)
DICK: Definitionen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 11
Definitionen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Bild 15-3: Das vereinbarte Array von “leeren” Prozess-Deskriptoren
DICK: Definitionen
queue
0 1 2 3 4 5 31
(0) (1) (2) (3) (4) (30)(NIL)
(5)(1) (2) (3) (4) (NIL)(6)
(0)
Indizes der einzelnen Prozessdeskriptoren:
Vorwärtsverkettung:
Rückwärtsverkettung:
…… … … … … … …
Hinweis: Vorwärts- und Rückwärtsverkettung nach der Vereinbarung noch nicht eingetragen
struct pcb vdes[MAXPROC]
sym-
bo-
lisch
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 12
// SEMAPHORE
// Semaphor-Kontrollblock (SCB)
struct scb{
int count; // (Zaehl-)Wert des Semaphors
int qsem; // Warteschlange (queue) am Semaphor
sem next; // Zeiger auf nächsten Semaphor
};
struct scb vsem[MAXSEM]; // Array von SCBs
Definitionen
DICK: Definitionen
Definitionen bezüglich Synchronisationsmechanismen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 13
Definitionen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Bild 15-4: Das vereinbarte Array von “leeren” Semaphoren
DICK: Definitionen
queue
0 1 2 3 4 5 31
(5)(1) (2) (3) (4) (NIL)(6)
(0)
Indizes der einzelnen Semaphor-Kontrollblöcke:
Vorwärtsverkettung: …
Hinweis: Verkettung nach der Vereinbarung noch nicht eingetragen
symbo-
lisch
struct scb vsem[MAXSEM];
… … … … … … …
möglicherweise:
Warteschlangen von
Prozessen, die an diesem
Semaphor blockiert
(wenn in Benutzung)
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 14
// FEHLER-MITTEILUNGEN
#define OK 0 // kein Fehler
#define TIME_OVERFLOW 1 // Frist ueberschritten
#define TIME_EXPIRED 2 // System-Lebenszeit erreicht
#define NO_GUARANTEE 3 // Prozess nicht einplanbar, Überlast
#define NO_PCB 4 // zu viele Prozesse; kein PCP mehr frei
#define NO_SEM 5 // zu viele Semaphore
Definitionen
DICK: Definitionen
Definitionen von Fehlermitteilungen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 15
// AKTUELLE WERTE
proc pexe; // momentan in Ausführung befindlicher Prozess
queue ready; // Warteschlange rechenbereiter Prozesse
queue idle; // Idle-Warteschlange
queue zombie; // Zombie-Warteschlange
queue freepcb; // Liste freier Prozesskontrollblöcke
queue freesem; // Liste freier Semaphore
float util_fact; // Prozessor-Auslastungsfaktor
// ZEIT-MANAGEMENT
unsigned long sys_clock; // System-Zeit
float time_unit; // Größe der Zeiteinheit (in ms)
Definitionen
DICK: Definitionen
Definitionen bezüglich aktueller Werte u. für Zeitmanagement
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 16
Definitionen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Bild 15-5: Variable u. Datenstrukturen im Kernel – mit Beispielbelegung
DICK: Definitionen
0 1 2 3 4 5 31
(0) NIL NIL 1 NIL NIL(NIL)
NIL1 4 NIL NIL NIL6
Indizes der einzelnen scb‘s:
Vorwärtsverkettung:
Rückwärtsverkettung:
…… … … … … … …
0 1 2 3 4 5 31
5(1) (2) (3) (4) (NIL)6Vorwärtsverkettung:
…
…
pexeready
20
idle
3
zombie
31
freepcb
5
freesem
4util_
fact
17
25 NIL
14
NIL
0.574
Prozess-
Deskriptoren
Semaphore
Kernel-Variablen
Warteschlangen von an Sema-
phoren blockierten Prozessen
200
sys_
clock
time_
unit
20
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 17
#include "definitions"
void init_system(float tick)
{
proc i; // Laufvariable (Folie 7: Datentyp proc = Datentyp int)
time_unit = tick; // Zeiteinheit festlegen
<enable the timer to interrupt every time unit>
<initialize the interrupt vector table>
// Initialisieren der Liste unbelegter („freier“) PCBs
for (i=0; i<MAXPROC-1; i++) vdes[i].next = i+1;
vdes[MAXPROC-1].next = NIL;
// Initialisieren der Liste unbelegter („freier“) Semaphore
for (i=0; i<MAXSEM-1; i++) vsem[i].next = i+1;
vsem[MAXSEM-1].next = NIL;
…
System-Initialisierung
DICK: System-Initialisierung
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 18
…
ready = NIL; // READY-Queue noch leer
idle = NIL; // IDLE-Queue noch leer
zombie = NIL; // ZOMBIE-Queue noch leer
freepcb = 0; // Index des ersten freien PCB ist „0“
freesem = 0; // Index des ersten freien Semaphors ist „0“
util_fact = 0; // Prozessor-Auslastung noch „0“ (Anfangswert)
<initialize the PCB of the main process>
pexe = <main index>;
}
System-Initialisierung
DICK: System-Initialisierung
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 19
Zur Systeminitialisierung
Vorwärts-
Verkettung
Kopf-Element
NIL
Rückwärts-Verkettung
(bei Initialisierung nicht
benutzt)
Bild 15-6: “Queue“ unbelegter PCBs nach der Initialisierung
PCB:
MAXPROC-1PCB: 0
struct pcb vdes[MAXPROC]; // Array von PCBs
next
prev
15. Einfache Echtzeit-Exekutive (Kernel) / 15.3 Basisdefinitionen & Initialisierung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 20
15.4 Maschinennahe Schicht
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwal-
tungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
Aufrufe
Service-
Schicht
L3a L3b L3c
15. Einfache Echtzeit-Exekutive (Kernel) / 15.4 Maschinennahe Schicht
Bild 15-7: Maschinennahe Schicht in der hierarchischen Struktur von DICK
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 21
Maschinennahe Schicht
… interagiert direkt mit Hardware der physischen Maschine
Routinen dieser Schicht:
normalerweise in Assembler-Sprache (Hardwareabhängigkeit!)
Primitiven dieser Ebene realisieren insbesondere
1. Kontext-Umschaltungen am Prozessor
2. Behandlung von Interrupts
3. Timer-Verwaltung
4. Ansteuerung weiterer Hardware einschließlich externer Geräte
(Geräte-Treiber)
Schicht realisiert somit auch:
Basis-Abstraktionen bezüglich darunterliegender Hardware
... ist auf Nutzer-Niveau nicht sichtbar
Maschinennahe Schicht
15. Einfache Echtzeit-Exekutive (Kernel) / 15.4 Maschinennahe Schicht
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 22
Maschinennahe Schicht
betrachtet werden Routinen zur
1. zur Kontext-Umschaltung – und
2. zur Timer-Verwaltung
• Interruptbehandlung:
stark hardwareabhängig
deshalb: nur allgemeine Ausführungen mit Hinsicht auf
Echtzeit-Betriebssystem-Kerne
Maschinennahe Schicht
15. Einfache Echtzeit-Exekutive (Kernel) / 15.4 Maschinennahe Schicht
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 23
15.5 Routinen zur Kontextumschaltung bei DICK
Kontextumschaltung
Benötigt werden:
1. Routine zum Retten des Kontextes gerade bearbeiteter Aufgabe: (d.h. eines Prozesses oder oder einer Betriebssystemkomponente)
L0a_save_context.c: Retten des „alten“ Kontextes
2. Routine, die neuen Kontext in die Prozessorregister lädt
L0a_load_context.c: Laden eines „neuen“ Kontextes
Hinweise:1. Kontext: bei DICK nur die Prozessorregister
2. Routinen: wegen Hardware-Abhängigkeit eigentlich nicht in „C“
formulierbar
Deshalb: Hardware-Abhängigkeiten in Pseudo-Code formuliert
15. Einfache Echtzeit-Exekutive (Kernel) / 15.5 Routinen zur Kontextumschaltung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 24
// L0a_save_context.c:// Rette Kontext der Aktivität in Ausführung (Prozess oder Betriebssystem-Routine)
#include "definitions"
void save_context(void)
{
int *pc; // Zeiger auf Kontext von pexe
<disable interrupts> // Beginn kritischer Abschnitt
pc = vdes[pexe].context; // auf Kontext des bisher laufenden
// Prozesses setzen
pc[0] = <register_0>; // Register 0 retten
pc[1] = <register_1>; // Register 1 retten
pc[2] = <register_2>; // Register 2 retten
...
pc[n] = <register_n>; // Register n retten
}
L0a_save_context.c:
Kontext-Rettung [am Beispiel DICK]
15. Einfache Echtzeit-Exekutive (Kernel) / 15.5 Routinen zur Kontextumschaltung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 25
// L0a_load_context.c: // Lade Kontext des jetzt auszuführenden Prozesses
#include "definitions"
void load_context(void)
{
int *pc; // Zeiger auf Kontext von pexe
pc = vdes[pexe].context; // auf Kontext des Prozesses setzen,
// der jetzt laufen soll
<register_0> = pc[0]; // Register 0 laden
<register_0> = pc[1]; // Register 1 laden
<register_0> = pc[2]; // Register 2 laden
...
<register_0> = pc[n]; // Register n laden
<enable interrupts>; // Ende: kritischer Abschnitt
}
Laden eines Kontextes
L0a_load_context.c:
15. Einfache Echtzeit-Exekutive (Kernel) / 15.5 Routinen zur Kontextumschaltung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 26
15.6 Interrupt-Behandlung
Zweck der Interrupt-Behandlung
… ist die Bedienung von Interruptanforderungen von beliebigen
Peripherie-Geräten (bzw. die Behandlung spezieller Prozessor-
Zustände, z.B. sog. Ausnahmen [Exceptions] )
Bedienung:
= Ausführung einer speziellen Interrupt-[Service]-Routine
bei Interrupt-Anforderungen durch (E/A-)Geräte:
Ausführung des jeweiligen Geräte-Treibers
15. Einfache Echtzeit-Exekutive (Kernel) / 15.6 Interrupt-Behandlung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 27
Implementierung in klassischen Nicht-Echtzeit-
Betriebssystemen
jeder (Echtzeit-)Anwendungsprozess kann jederzeit durch Interrupt-
Service-Routine (z.B. Geräte-Treiber-Prozess) verdrängt werden
Echtzeitfähigkeit?
• Nein!
Frist
tatsächlicher
Verlauf
theoretischer
Verlauf
Unterbrechungen
durch
Interruptbearbeitung
Fristüberschreitung
Zeit
14. Einfache Echtzeit-Exekutive (Kernel) / 14.6 Interrupt-
Behandlung
Interrupt-Behandlung
Bild 15-8: Fristüberschreitung durch ungeeignete Interruptbearbeitung
15. Einfache Echtzeit-Exekutive (Kernel) / 15.6 Interrupt-Behandlung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 28
Lösung für Echtzeit-Systeme
Interrupt-Behandlungsmechanismus mit Scheduling-Mechanismus
verknüpfen!
Interrupt: zunächst nur registriert
hierdurch: Bearbeitungsunterbrechung eines Anwendungsprozesses
ganz geringfügig (Wenn maximale zeitliche Interruptdichte bekannt, kann
diese berücksichtigt werden.)
Interrupt-Behandlung für Echtzeit-Systeme
nur minimale Unterbrechungen der
Prozessbearbeitung durch Interruptregistrierung
Zeit
Bild 15-9: Keine Fristüberschreitung durch geeignete
Interruptbearbeitung (1)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.6 Interrupt-Behandlung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 29
Lösung für Echtzeit-Systeme
eigentliche Bearbeitung der Interruptroutine durch Scheduler eingeplant
Interrupt-Behandlung für Echtzeit-Systeme
Zeit
geplante Bearbeitung der
Interruptroutine
Bild 15-10: Keine Fristüberschreitung durch geeignete
Interruptbearbeitung (2)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.6 Interrupt-Behandlung
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 30
Zeitbasis Erzeugung einer Bezugsbasis für interne Systemzeit:
Timer-Hardware muss so programmiert werden, dass Prozessor mit
festzulegender Frequenz unterbrochen wird (Folie 17)
Interne Systemzeit: • hier: repräsentiert durch ganzzahlige Variable sys_clock
(siehe Definitionen: Folie 15)
• diese:
bei System-Initialisierung: zurückgesetzt
bei jedem Timer-Interrupt: inkrementiert (Folie 37)
• damit:
Zeiteinheit im System (auch: clock tick oder system tick) durch
Zeitintervall definiert, mit dem Timer programmiert
// ZEIT-MANAGEMENT
unsigned long sys_clock; // System-Zeit
float time_unit; // Zeiteinheit [in ms]
15.7 Timer-Management am Beispiel DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 31
Zeitbasis
1 clock tick: kleinste Zeiteinheit, mit der Kern umgehen kann
bestimmt damit Zeit-Auflösung im System
sys_clock:
enthält zu jedem Zeitpunkt Anzahl Interrupts, die seit System-
Initialisierung durch Timer erzeugt wurden
Damit wirkliche Systemzeit:
Maximalwert für Systemzeit (system lifetime):
damit abhängig von:
1. Wert eines system ticks
2. Bit-Anzahl zur Speicherung von sys_clock
sys_clock * time_unit [in Millisekunden]
Timer-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 32
System Lifetime („System-Lebenszeit“)
Bei 32 Bit Darstellungslänge für sys_clock u. unterschiedlichen
Werten für time_unit:
• folgende Richtwerte für system lifetime :
1 ms 50 Tage
5 ms 8 Monate
10 ms 16 Monate
50 ms 7 Jahre
Timer-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 33
Größenwahl für clock tick
anwendungsabhängig – allgemein gilt:
• kleine tick-Werte:
verbessern System-Responsivität – und
ermöglichen Ausführung periodischer Aktivitäten mit hohen
Aktivierungsraten (d.h. kleinen Periodendauern)
• andererseits: sehr kleiner tick-Wert:
verursacht hohen Laufzeit-Overhead aufgrund öfteren
Durchlaufens der Timer-Routine – und
verkleinert system lifetime
• typische Werte: zwischen 1 … 50 ms
Timer-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 34
Größenwahl für clock tick
zur exakten Angabe von Fristen u. periodischen Aktivierungen von
Prozessen:
• alle für Prozesse definierten Zeitparameter sollten Vielfaches eines
system tick sein
falls tick durch Nutzer festlegbar:
• bester Wert:
größter gemeinsamer Teiler aller Prozess-Periodendauern
Timer-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 35
Behandlungsroutine für Timer-Interrupts
... spielt bei Echtzeit-Systemen kritische Rolle
außer Hochzählen d. internen Zeit muss sie mögliche
Fristüberschreitungen „harter“ Echtzeit-Prozesse überwachen (aufgrund nicht 100%tig möglicher Vorhersage der worst case execution times
[WCET])
weitere mögliche Aktivitäten:• lifetime-Überwachung
• Aktivierung von periodischen Prozessen im Zustand idle
• Aufwecken von durch delay-Primitive suspendierten Prozessen
• Kontrolle bezüglich deadlock-Bedingungen
• endgültiges Beenden von Zombie-Prozessen
Timer-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 36
DICK- Behandlungsroutine für Timer-Interrupts
1. rettet Kontext des unmittelbar zuvor gelaufenen Prozesses
2. inkrementiert Wert von sys_clock
3. erzeugt timing-error, falls momentane Zeit größer als system lifetime
geworden
4. erzeugt time_overflow-error, falls momentane Zeit größer als
irgendeine harte Frist wird
5. entfernt alle zombie-Prozesse, deren Frist abgelaufen ist
6. weckt alle idle-Prozesse, die neue Periode beginnen müssen
7. ruft Scheduler auf, wenn wenigstens ein Prozess geweckt wurde
8. lädt Kontext des jetzt auszuführenden Prozesses
9. kehrt vom Interrupt zurück
Laufzeit-Overhead durch Ausführung der Timer-Interrupt-
Behandlungsroutine
• proportional zur Timer-Interrupt-Frequenz
Timer-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 37
// L0c_wake_up.c: // Behandlungs-Routine für Timer-Interrupts
#include "definitions"
void wake_up(void)
{
proc p;
int count = 0;
save_context();
sys_clock++;
if (sys_clock >= LIFETIME) abort(TIME_EXPIRED);
if (vdes[pexe].type = HARD)
if (sys_clock > vdes[pexe].deadline)
abort(TIME_OVERFLOW);
L0c_wake_up.c:
Hochzählen von sys_clock
Fehler: maximale Systemzeit überschritten
Fehler: Frist überschritten
DICK-Behandlungsroutine für Timer-Interrupts
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
Kontext der laufenden Aktivität retten
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 38
while(!empty(zombie) && (firstdeadline(zombie) <= sys_clock)) {
p = getfirst(&zombie);
util_fact = util_fact - vdes[p].util;
vdes[p].state = FREE;
insert(p, &freepcb);
}
while(!empty(idle) && firstdeadline(idle) <= sys_clock)) {
p = getfirst(&idle);
vdes[p].deadline += (long)vdes[p].period;
vdes[p].state = READY;
insert(p, &ready);
count++;
}
if (count > 0) schedule;
load_context();
}
Entfernen von Zombies
Aufwecken von
idle-Prozessen
Aufruf des Schedulers: weitere
Prozesse gerade aufgeweckt
(siehe Folie 52)
L0c_wake_up.c:
DICK-Behandlungsroutine für Timer-Interrupts
15. Einfache Echtzeit-Exekutive (Kernel) / 15.7 Timer-Management
alten oder neuen Kontext zum Prozessor
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 39
15.8 Management von Verwaltungsstrukturen
Verwaltungs-Datenstrukturen
in dieser Schicht:
Basis-Primitiven zum Ein- u. Austragen von Prozessen in
Verwaltungsdatenstrukturen enthalten
DICK• benutzt (vereinfachte!) verkettete Listen („Warteschlangen“) u.
verwendet folgende Primitiven:
1. L1_insert.c: Prozess entsprechend Frist in Warteschlange
einfügen
2. L1_extract.c: Prozess aus Warteschlange „ausketten“
3. L1_getfirst.c: ersten Prozess aus Warteschlange
„ausketten“
4. L1_firstdeadline.c: Periodendauer eines Prozesses
bestimmen
5. L1_empty.c: Belegungsprüfung einer Warteschlange
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 40
Management von Verwaltungsstrukturen
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwal-
tungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
Aufrufe
Service-
Schicht
L3a L3b L3c
Bild 15-11: Schicht zum Management von Verwaltungsstrukturen bei DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 41
// Füge Prozess entsprechend Frist in Warteschlange ein
#include "definitions"
void insert(proc i, queue *que)
{
long dl; // Frist des einzufügenden Prozesses
int p; // Zeiger auf sich davor befindenden PCB
int q; // Zeiger auf sich danach befindenden PCB
p = NIL;
q = *que;
dl = vdes[i].dline;
...
L1_insert.c:
Prozess in Warteschlange einfügen
Beginne am Anfang der Warteschlange
Index („PCB-Nr.“) des einzufügenden Prozesses
Zeiger auf zu verwendende
Warteschlange
Deadline des einzufügenden PCBs
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 42
...
// finde Element vor der Einsetzstelle
while ((q != NIL) && (dl >= vdes[q].dline)) {
p = q;
q = vdes[q].next;
}
if (p != NIL) vdes[p].next = i;
else *que = i;
if (q != NIL) vdes[q].prev = i;
vdes[i].next = q;
vdes[i].prev = p;
}
L1_insert.c:
Prozess in Warteschlange einfügen
Durchsuche Warteschlange
schrittweise solange bis …
… Stelle zum Einfügen
gefunden
Einfügen des PCB =
= neue Verkettung eintragen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 43
Prozess in Warteschlange einfügen
einzufügender
PCB
Vorwärts-
Verkettung
Kopf-
Element
NIL
NIL
Rückwärts-
Verkettung
Darstellung nach [Buttazzo2011] Bild 10.12 S. 369
Bild 15-12: Einketten eines Prozesskontrollblocks
p q
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 44
// L1_extract.c:
// Entnimm einen Prozess aus Warteschlange
#include "definitions"
proc extract(proc i, queue *que)
{
int p; // Index des vorhergehenden PCBs
int q; // Index des nachfolgenden PCBs
p = vdes[i].prev;
q = vdes[i].next;
if (p == NIL) *que = q; // erstes Element
else vdes[p].next = vdes[i].next;
if (q != NIL) vdes[q].prev = vdes[i].prev;
return i;
}
L1_extract.c:
Prozess aus Warteschlange „ausketten“
Index („PCB-Nr.“) und Warteschlange
des gewünschten Prozesses
Verkettungsinfos aus aktuellem PCB
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 45
Prozess aus Warteschlange „ausketten“
zu entfernender
PCB
Vorwärts-
Verkettung
Kopf-
Element
NIL
NIL
Rückwärts-
Verkettung
Darstellung nach [Buttazzo2011] Bild 10.13 S. 370
Bild 15-13: “Ausketten“ eines Prozesskontrollblocks
p q
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 46
// L1_getfirst.c: // Entnimm Prozess am Anfang der Warteschlange
#include "definitions"
proc getfirst(queue *que)
{
int q;
q = *que;
if (q == NIL) return(NIL);
*que = vdes[q].next;
vdes[*que].prev = NIL;
return q;
}
L1_getfirst.c:
Ersten Prozess aus Warteschlange „ausketten“
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Parameter: welche Warteschlange?
Verweis auf erstes Element
Warteschlange enthält kein Element
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 47
Prozess aus Warteschlange „ausketten“
zu entfernender
PCB
Vorwärts-
Verkettung
Kopf-
Element
NIL
NIL
Rückwärts-
Verkettung
Darstellung nach [Buttazzo2011] Bild 10.14 S. 371
Bild 15-14: “Ausketten“ des ersten Prozesskontrollblocks
q
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 48
// L1_firstdeadline.c: // Bestimme Frist des ersten Prozesses am Beginn einer Warteschlange
#include "definitions"
long firstdeadline(queue *que)
{
return (vdes[*que].dline);
}
L1_firstdeadline.c:
Frist des ersten Prozesses
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 49
// L1_empty.c: // Gib bei leerer Warteschlange TRUE zurück, sonst FALSE
#include "definitions"
int empty(queue *que)
{
if (que == NIL) return TRUE; else return FALSE;
}
L1_empty.c:
Belegungsprüfung einer Warteschlange
15. Einfache Echtzeit-Exekutive (Kernel) / 15.8 Management von Verwaltungsstrukturen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 50
15.9 Prozessor-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.9 Prozessor-Management
DICK: Prozessor-Management-Schicht
hier: Implementierung von Scheduling u. Dispatching
DICK:
umfasst dazu folgende Betriebssystem-Komponenten
1. L2_schedule.c: Scheduler (realisiert EDF)
2. L2_dispatch.c: Dispatcher
(macht Prozess mit frühester Frist zum
laufenden Prozess)
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 51
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwal-
tungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
AufrufeService-
Schicht
L3a L3b L3c
Prozessor-Management bei DICK
Bild 15-15: Prozessor-Management-Schicht bei DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.9 Prozessor-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 52
// L2_schedule.c: Wähle Prozess mit frühester Frist (EDF)
#include "definitions"
void schedule(void)
{
if (firstdeadline(ready) < vdes[pexe].deadline) {
vdes[pexe].state = READY;
insert(pexe, &ready);
dispatch();
}
}
Hat erster Prozess in READY-Queue
frühere Frist als laufender Prozess?
… füge diesen in
READY-Queue ein …
… und mache ersten Prozess der
READY-Queue zum laufenden.
L2_schedule.c:
Scheduler
… dann setze Zustand des
gerade noch laufenden
Prozesses auf „READY“, …
15. Einfache Echtzeit-Exekutive (Kernel) / 15.9 Prozessor-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 53
// L2_dispatch.c:
// Ordne CPU erstem Prozess der ready-Queue zu
#include "definitions"
void dispatch(void)
{
pexe = getfirst(&ready);
vdes[pexe].state = EXE;
}
Mache Prozess mit frühester
Frist aus READY-Queue
zum laufenden Prozess …
L2_dispatch.c:
Dispatching
… und ändere seinen
Zustand auf „laufend“.
15. Einfache Echtzeit-Exekutive (Kernel) / 15.9 Prozessor-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 54
Aufgaben
stellt alle auf Nutzer-Niveau sichtbaren Dienste zur Verfügung
realisiert Systemaufruf-Schnittstellen (API)
enthält Routinen aus den Funktionsgruppen:
1. Prozess-Management
2. (Interprozess-)Kommunikation und Synchronisation – sowie
3. sog. Utility-Funktionen (hier nur für verschiedene
Zustandsabfragen)
15.10 Dienste-Schicht (Service Schicht)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.10 Dienste-Schicht
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 55
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwal-
tungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
Aufrufe
Service-
Schicht
L3a L3b L3c
Dienste-Schicht in hierarchischer Struktur von DICK
Bild 15-16: Dienste-Schicht von DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.10 Dienste-Schicht
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 56
Praktisch alle Betriebssystem-Kerne, die Ausführung konkurrenter
Aktivitäten (Schwergewichts- oder Leichtgewichts-Prozesse [=Threads])
an 1-Kern-Prozessor unterstützen, ermöglichen 3 Grundzustände:
1. AKTIV (EXE)
Prozess hat Prozessor zugeordnet u. „rechnet“
2. BEREIT (READY)
Prozess ist bereit zur Ausführung, wird aber noch nicht
ausgeführt, da bisher kein Prozessor zugeordnet wurde
es existiert: Warteschlange bereiter Prozesse
3. BLOCKIERT (BLOCKED)
Prozess wartet auf Erfüllung einer (oder mehrerer)
Bedingungen
bei Synchronisation mit Semaphoren: Zustand durch
Ausführung der wait-Primitive eines verriegelten Semaphors
erreicht
Prozess wird in mit diesem Semaphor verknüpfte
Warteschlange eingefügt
15.11 Prozess-Management
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Basis-Prozesszustände
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 57
Prozesskontrollblock enthält spezifische Parameter zur Verwaltung von
Echtzeitprozessen, z.B. zur Anwendung spezieller Echtzeit-Scheduling-
Verfahren (vergleiche DICK-PCB auf Folie 8)
neben Prozess-Basis-Zuständen oft weitere Prozesszustände zur
Unterstützung spezieller Aufgaben eingeführt, z.B.:
1. GEPARKT (IDLE)
zur Unterstützung periodischer Prozesse
2. DELAY
für zeitgesteuerten Wiederstart durch Timer
3. RECEIVE
zur Unterstützung des Nachrichtenaustausches
4. ZOMBIE
zur Unterstützung dynamischer Erzeugung u. Beendigung harter
periodischer Prozesse
(siehe auch Prozesszustandsdiagramm mit „idle“-Zustand u. DICK-Zustandsdiagramm)
Unterschied zu Nicht-Echtzeit-Betriebssystemen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 58
• … beinhaltet Routinen zu Erzeugung, Aktivierung, Suspendierung und
Beendigung von Prozessen
L3a_create.c:
L3a_guarantee.c:
L3a_activate.c:
L3a_sleep.c:
L3a_end_cycle.c:
L3a_end_process.c:
L3a_kill.c:
DICK-Prozess-Management
DICK-Prozess-Management besteht aus folgenden 7 Routinen:
Prozess-Erzeugung
Garantietest auf Ausführbarkeit
Einfügen in Warteschlange (rechen)bereiter Prozesse
Selbst-Suspendierung eines Prozesses
Einfügen in „idle“-Warteschlange
Terminierung des laufenden Prozesses
Terminieren eines ausgewählten Prozesses
Prozess-Zustandsdiagramm mit Wirkung einzelner Routinen in nachfolgender
Graphik gezeigt.
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 59
(aktiv)
(blockiert)
(bereit)
DICK: Prozess-Zustandsdiagramm
SLEEP
(geparkt)
Darstellung nach [Buttazzo97] Bild 9.7 S.260
create
READY
WAIT
EXEZOMBIE
IDLE
activate
terminate
FREE
dispatching
preemption
TIMER
Bild 15-17: Prozess-Zustandsdiagramm von DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 60
// L3a_create.c: // Erzeuge neuen Prozess, Anfangszustand „schlafend“ (SLEEP)
#include "definitions"
proc create(
char name[MAXLEN+1], // process name
proc (*addr)(), // process address
int type, // process type: HARD or NRT
float period, // period or priority
float wcet // execution time
)
{
proc p;
<disable cpu interrupts> // keine Unterbrechung erlaubt!
// kurzer kritischer Abschnitt
L3a_create.c:
Parameterliste:
enthält bereits bekannte
Parameter des Prozesses
neu erzeugter Prozess:
Index des PCB
Prozess-Erzeugung
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 61
p = getfirst(&freepcb);
if (p == NIL) abort(NO_PCB);
if (vdes[p].type == HARD) if (!guarantee(p)) return(NO_GUARANTEE);
vdes[p].name = name;
vdes[p].addr = addr;
vdes[p].type = type;
vdes[p].state = SLEEP;
vdes[p].period = (int) (period / time_unit);
vdes[p].wcet = (int) (wcet / time_unit);
vdes[p].util = wcet / period;
vdes[p].prt = (int) period;
vdes[p].deadline = MAX_LONG + (long)(period - PRT_LEV);
<initialize process stack> // Stack des neuen Prozesses
// initialisieren
<enable cpu interrupts> // Interrupts wieder einschalten
return(p); // alles O.K. – Rückkehrwert: Prozess-
} // Index
Prozess-
kontrollblock
wird gefüllt
max. Prozess-
Anzahl erschöpft
Garantietest
L3a_create.c:
Prozess-Erzeugung
verwende ersten freien pcb
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 62
// L3a_guarantee.c: // Untersuche, ob [neuer, harter Echtzeit-]Prozess zu Überlast führt
#include "definitions"
int guarantee(proc p)
{
util_fact = util_fact + vdes[p].util;
if (util_fact > 1.0) {
util_fact = util_fact - vdes[p].util;
return(FALSE);
}
else return(TRUE);
}
L3a_guarantee.c:
Prozessor-Überlast?
bewirkt neu erzeugter Prozess
Überlast am Prozessor?
Garantie-Test
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 63
// L3a_activate.c: // Füge Prozess in READY-Queue ein
#include "definitions"
int activate(proc p)
{
save_context();
if (vdes[p].type == HARD)
vdes[p].deadline = sys_clock + (long)vdes[p].period;
vdes[p].state = READY;
insert(p, &ready);
schedule();
load_context();
}
L3a_activate.c:
gliedere Prozess in READY-Queue ein
Bestimme Prozess mit frühester Frist
und bringe diesen zur Ausführung
Kontext des gerade laufenden
Prozesses sichern
Prozess-Aktivierung
bestimme aktuelle Frist
Lade zugehörigen Kontext
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 64
// L3a_sleep.c: // Prozess begibt sich freiwillig in Schlaf-Zustand
#include "definitions"
void sleep(void)
{
save_context();
vdes[p].state = SLEEP;
dispatch();
load_context();
}
L3a_sleep.c:
„Schlafen-Legen“ (Blockieren) eines Prozesses
Kontext des (noch) laufenden
Prozesses sichern …
Bereiter Prozess mit frühester
Frist wird laufender Prozess
Lade Kontext des neu
ausgewählten Prozesses
… und seinen Zustand auf
„SLEEP“ ändern
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 65
// L3a_end_cycle.c: // Füge Prozess ein in IDLE-Queue
#include "definitions"
void end_cycle(void)
{
long dl; // interner Vergleichswert für Frist
save_context();
dl = vdes[pexe].deadline;
if (sys_clock < dl) {
vdes[pexe].state = IDLE;
insert(pexe, &idle);
} else {
dl = dl + (long)vdes[pexe].period;
vdes[p].deadline = dl;
vdes[p].state = READY;
insert(pexe, &ready);
}
...
L3a_end_cycle.c:
Einfügen in IDLE-Warteschlange
Aktuelle Zeit kleiner
als Deadline des
laufenden Prozesses?
Ja: einfügen in IDLE-Queue
Sonst:
Setze Vergleichswert auf Frist
des laufenden Prozesses
4. in READY-Queue einfügen
1. Neue Frist berechnen
2. neue Frist eintragen
3. Zustand: „READY“
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 66
…
dispatch();
load_context();
}
L3a_end_cycle.c:
Einfügen in IDLE-Warteschlange
ready-Prozess mit frühester Frist
wird laufender Prozess
Lade Kontext des neu
ausgewählten Prozesses
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 67
// L3a_end_process.c: // Beende laufenden Prozess
#include "definitions"
void end_process(void)
{
<disable cpu interrupts>
if (vdes[pexe].type == HARD)
insert(pexe, &zombie);
else {
vdes[pexe].state = FREE;
insert(pexe, &freepcp);
}
dispatch():
load_context();
}
L3a_end_process.c:
Prozess-Terminierung („terminate“)
Laufender Prozess:
harter Echtzeitprozess?
1. PCP auf „FREE“ setzen
Prozess aus READY-Queue mit
frühester Frist wird laufender Prozess
Lade Kontext des neu ausgewählten Prozesses
Ja: einfügen in ZOMBIE-Queue
Sonst:
2. PCP in FREE-Queue einfügen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 68
// L3a_kill.c: // Brich laufenden Prozess ab
#include "definitions"
void kill(proc p)
{
<disable cpu interrupts>
if (pexe == p) {
end_process();
return;
}
if (vdes[p].state == READY) extract(p, &ready);
if (vdes[p].state == IDLE) extract(p, &idle);
…
L3a_kill.c:
Prozess-Terminierung („kill“)
Falls es der laufende Prozess ist ...
... beende diesen.
ready- oder idle-Prozess aus
jeweiliger Queue ausketten
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 69
…
if (vdes[p].type == HARD)
insert(p, &zombie);
else {
vdes[p].state = FREE;
insert(p, &freepcb);
}
<enable cpu interrupts>
}
(harter) Echtzeit-Prozess
wird Zombie
bei Prozessen anderer
Typen PCB löschen
L3a_kill.c:
Prozess-Terminierung (kill)
15. Einfache Echtzeit-Exekutive (Kernel) / 15.11 Prozess-Management
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 70
15.12 Kommunikation & Synchronisation
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwal-
tungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
Aufrufe
Service-
Schicht
L3a L3b L3c
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Bild 15-18: Komponente zur Kommunikation u. Synchronisation bei DICK
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 71
bei DICK entsprechend:
Synchronisation an sich und gegenseitiger Ausschluss speziell mittels
Semaphoren gehandhabt.
Zur Arbeit mit Semaphoren existieren vier Primitiven:
L3b_newsem.c:
L3b_delsem.c:
L3b_wait.c:
L3b_signal.c:
Zuweisen und initialisieren eines neuen Semaphors
„Löschen“ eines Semaphores (Freigeben der Struktur)
bewirkt Warten auf ein Ereignis (P-Operation)
signalisiert ein Ereignis (V-Operation)
allgemein bei Echtzeitsystemen:
• typische Realisierung von gegenseitigem Ausschluss:
durch spezielle Semaphore
unter Integration von Maßnahmen zur Verhinderung von
Prioritätsumkehr
Kommunikation & Synchronisation
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 72
// L3b_newsem.c: „Erzeuge“ neuen Semaphor
#include "definitions"
sem newsem(int n) {
sem s;
<disable cpu interrupts>
s = freesem;
if (s == NIL) abort(NO_SEM);
freesem = vsem[s].next;
vsem[s].count = n;
vsem[s].qsem = NIL;
<enable cpu interrupts>
return(s)
}
L3b_newsem.c:
ersten freien Semaphorindex verwenden
Liste freier Semaphore aktualisieren
Zähler initialisieren (binärer oder Zählsemaphor)
Semaphor-Queue aktualisieren
Semaphore
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 73
// L3b_delsem.c: Semaphor löschen
#include "definitions"
void delsem(sem s)
{
<disable cpu interrupts>
vsem[s].next = freesem;
freesem = s;
<enable cpu interrupts>
}
L3b_delsem.c:
gliedere s am Anfang der
Liste freier Semaphore ein
Semaphore
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 74
// L3b_wait.c: Semaphor-WAIT-Operation
#include "definitions"
void wait(sem s)
{
<disable cpu interrupts>
if (vsem[s].count > 0) vsem[s].count --;
else {
save_context();
vdes[pexe].state = WAIT;
insert(pexe, &vsem[s].qsem);
dispatch();
load_context();
}
<enable cpu interrupts>
}
L3b_wait.c:
Zustand des laufenden Prozesses
auf „WAIT“ setzen
diesen Prozess in zum Semaphor
gehörende Warteschlange einfügen
ready-Prozess mit
frühester Frist auswählen
Kontext dieses Prozesses laden
Semaphore
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 75
// L3b_signal.c: Semaphor-SIGNAL-Operation
#include "definitions"
void signal(sem s)
{
proc p;
<disable cpu interrupts>
if (!empty(vsem[s].qsem)) {
p = getfirst(&vsem[s].qsem);
vdes[p].state = READY;
insert(p, &ready);
save_context();
schedule();
load_context();
} else vsem[s].count++;
<enable cpu interrupts>
}
L3b_signal.c:
Ersten Prozess aus Semaphor-
Warteschlange entnehmen
Zustand auf „READY“ setzen u. in
ready-Queue einfügen
aktuellen Kontext sichern
Kontext dieses Prozesses laden
EDF ausführen
Semaphore
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 76
Interprozess-Kommunikation über zyklische Puffer (CABs)
Zyklische asynchrone Puffer
Haben wir uns schon einmal (kurz) angesehen … (Abschnitt 3 /Folie 5)
geeignet:
insbesondere für Kommunikation zwischen periodischen Prozessen
• CABs bilden Eins-zu-Viele-Kommunikationskanal u. enthalten stets
zuletzt zugestellte Nachricht (bzw. jeweils zuletzt abgespeichertes
Datenelement)!
• Pufferinhalte:
nie explizit entnommen (z.B. durch lesenden Prozess), sondern erst
im gegebenen Moment durch aktuelleres Datenelement überschrieben (somit auch Garbage-Collection integriert)
• folglich:
1. ein Sender kann nie blockiert werden
2. Falls immer mindestens eine Botschaft zur Verfügung steht –
auch nie ein Empfänger!
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 77
free
mrb
max_buf
dim_buf
next
use
data
next
use
(wird z.B.
gefüllt)
use
(leer)
NIL
use
(leer)Pointer p
lesender
Prozess
Darstellung nach [Buttazzo97] Bild 9.17 S.293
Bild 15-19: Schema eines zyklischen Puffers für IPC
CAB
Control
Block
Interprozess-Kommunikation über zyklische Puffer
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
…
maximal max_buf Pufferelemente
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 78
CAB-Benutzung
gesteuert durch: CAB Control Block
dieser enthält:
free: Zeiger auf Liste freier Pufferelemente
mrb: Zeiger auf aktuelles Pufferelement („most recent buffer“)
max_buf: maximale Anzahl von Pufferelementen
dim_buf: Größe (Dimension) eines Pufferelements
jedes Pufferelement:
enthält weitere Steuer-Informationen:
next: Zeiger zum Aufbau einer Liste freier Pufferelemente
use: Zähler der momentan auf Pufferelement zugreifenden
Prozesse
sowie:
data: momentan gespeicherte Daten (bzw. „leer“ [empty])
Interprozess-Kommunikation über zyklische Puffer
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 79
Funktionen zur CAB-Benutzung
Es existieren vier Primitiven:
L3b_reserve.c:
L3b_putmes.c:
L3b_getmes.c:
L3b_unget.c:
Reserviere Pufferelement in einem CAB
Lege Nachricht (Message) im CAB ab
[Nur Verwaltung des Vorgangs im CAB]
Liefere Zeiger auf zuletzt geschriebenes
Pufferelement
Deallokiere Pufferelement, aber nur, falls nicht auf
es zugegriffen wird und es nicht das aktuelle
Pufferelement ist
Interprozess-Kommunikation über zyklische Puffer
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 80
Einspeichern einer „Message“
1. Reservieren eines Pufferelements
2. Message in Pufferelement speichern
3. benutztes Pufferelement zum „most recent“ Pufferelement machen
buf_pointer = reserve(cab_id);
<„Message“ in *buf_pointer schreiben>
putmes(cab_id, buf_pointer);
Interprozess-Kommunikation über zyklische Puffer
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 81
Lesen einer „Message“
Mehrere Prozesse können gleichzeitig lesen
1. Zeiger auf „most recent“ Pufferelement besorgen
2. Message aus Pufferelement lesen
3. Pufferelement (gegebenenfalls) freigeben
mes_pointer = getmes(cab_id);
<„Message“ lesen>
unget(cab_id, buf_pointer);
Interprozess-Kommunikation über zyklische Puffer
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 82
// L3b_reserve.c: // Reserviere einzelnen Puffer in einem CAB
#include "definitions"
pointer reserve(cab c)
{
pointer p;
<disable cpu interrupts>
p = c.free; // besorge einen freien Puffer
c.free = p.next; // Liste freier Puffer aktualisieren
return(p);
<enable cpu interrupts>
}
L3b_reserve.c:
CAB-Primitiven
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 83
// L3b_putmes.c: // Lege eine Nachricht (Message) im CAB ab
#include "definitions"
void putmes(cab c, pointer p)
{
<disable cpu interrupts>
if (c.mrb.use == 0) { // if not accessed
c.mrb.next = c.free; // deallocate the mrb
c.free = c.mrb;
}
c.mrb = p; // update the mrb
<enable cpu interrupts>
}
L3b_putmes.c:
CAB-Primitiven
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 84
// L3b_getmes.c: // Liefere Zeiger auf zuletzt belegten Puffer
#include "definitions"
pointer getmes(cab c)
{
pointer p;
<disable cpu interrupts>
p = c.mrb; // besorge Zeiger auf mrb
p.use = p.use + 1; // Zähler inkrementieren
return(p);
<enable cpu interrupts>
}
L3b_getmes.c:
CAB-Primitiven
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 85
// L3b_unget.c: // Deallokiere Puffer, aber nur, falls nicht auf ihn zugegriffen wird –
// und er nicht der aktuelle Puffer ist
#include "definitions"
void unget(cab c, pointer p)
{
<disable cpu interrupts>
p.use = p.use - 1; // Zähler dekrementieren
if ((p.use == 0) && (p != c.mrb)) {
p.next = c.free;
c.free = p;
}
<enable cpu interrupts>
}
L3b_unget.c:
CAB-Primitiven
15. Einfache Echtzeit-Exekutive (Kernel) / 15.12 Kommunikation & Synchronisation
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 86
L3c: Utility-Funktionen: Statusabfragen
Es existieren vier Primitiven:
L3c_get_time.c:
L3c_get_state.c:
L3c_get_dline.c:
L3c_get_period.c:
Systemzeit in Millisekunden
Prozesszustand
Deadline eines Prozesses
Periodendauer eines Prozesses
15.13 Utility-Funktionen von DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.13 Utility-Funktionen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 87
Management von Verwaltungsstrukturen
Scheduling Dispatching
Kontext-
Umschaltung
Interrupt-
Behandlung
Timer-
Management
Kern-
Mecha-
nismen
Prozessor-
Manage-
ment
Maschinen-
nahe
Schicht
Darstellung nach [Buttazzo97] Bild 9.1 S.255
Verwal-
tungs-
Strukturen-
Schicht
L0a L0b L0c
L1
L2
Kommunikation
& Synchronisation
Prozess-
Management
Utility-
Funktionen
System-
AufrufeService-
Schicht
L3a L3b L3c
Utility-Funktionen in hierarchischer Struktur von DICK
Bild 15-20: Zur Lage der Utility-Funktionen bei DICK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.13 Utility-Funktionen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 88
// L3c_get_time.c: // Ausgabe der Systemzeit [in Millisekunden]
#include "definitions"
float get_time(void)
{ return(sys_clock * time_unit); }
L3c_get_time.c:
// L3c_get_state.c: // Ausgabe des Prozess-Zustandes
#include "definitions"
int get_state(proc p)
{ return(vdes[p].state); }
L3c_get_state.c:
Status-Abfragen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.13 Utility-Funktionen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 89
// L3c_get_dline.c: // Ausgabe der Frist eines Prozesses
#include "definitions"
long get_dline(proc p)
{ return(vdes[p].dline); }
L3c_get_dline.c:
// L3c_get_period.c: // Ausgabe der Periodendauer eines Prozesses
#include "definitions"
float get_period(proc p)
{ return(vdes[p].period); }
L3c_get_period.c:
Status-Abfragen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.13 Utility-Funktionen
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 90
Prinzipielles An der Scuola Superiore S. Anna in Pisa wurden im gleichen Kontext wie
DICK die funktionsfähigen Echtzeit-Betriebssysteme
• HARTIK („HArd Real TIme Kernel“) – und
• SHaRK („Soft Hard Real-time Kernel“)
entwickelt
entwickelt.
15.14 DICK‘s „lauffähige“ Verwandte
… ist ein Betriebssystemkern zur Unterstützung von
Echtzeitanwendungen mit harten Fristen
… wurde speziell für fortgeschrittene Roboter-Steuerungs-
Anwendungen entwickelt, die sich durch strenge zeitliche Restriktionen
auszeichnen
15. Einfache Echtzeit-Exekutive (Kernel) / 15.14 DICK‘s „lauffähige“ Verwandte
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 91
1. Scheduling-Politiken
2. aperiodischen Server-Prozessen – und
3. Protokollen zur Handhabung konkurrenter Ressourcenzugriffe
SHaRK
… ist eine Weiterentwicklung von HARTIK und besitzt eine dynamisch
konfigurierbare Architektur
… wurde zur Unterstützung von „harten“ und „weichen“ Echtzeit- sowie
Nicht-Echtzeit-Anwendungen entworfen.
Der Kernel wurde vollständig modular gestaltet bezüglich
die in traditionellen Betriebssystemen normalerweise nicht modular sind
15. Einfache Echtzeit-Exekutive (Kernel) / 15.14 DICK‘s „lauffähige“ Verwandte
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 92
HARTIK u. DICK
Im Folgenden:
kurze Darstellung spezieller Eigenheiten von HARTIK, die u.a. reale
Echtzeit-Systeme vom „didaktischen Kern“ DICK unterscheiden:
1. Entwicklungs-Umgebung
HARTIK kommt mit zusätzlichen Werkzeugen („Tools“) zur Entwicklung
u. Konfiguration von Echtzeitanwendungen:
(1) Design-Tool
um u.a. eine Anwendung auf 3 verschiedenen Ebenen beschreiben
zu können
(2) Schedulability-Analyzer
um die Ausführbarkeit kritischer Prozesse zu verifizieren
(3) Scheduling-Simulator
um die System-Performanz unter einer synthetischen Arbeitslast
testen zu können
HARTIK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.14 DICK‘s „lauffähige“ Verwandte
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 93
HARTIK u. DICK
1. Entwicklungs-Umgebung
(4) Worst-case-Execution-Time-Estimator,
der auf Grundlage von Programmtext u. Prozessor-Architektur
WCET-Abschätzung vornehmen kann
(5) Real-Time-Tracer
zur Registrierung u. Visualisierung von Traces von Ausführungen
2. IPC
zusätzlich zu CABs:
verschiedene synchrone Kommunikationsmechanismen
3. Interrupt-Behandlung
Gerätetreiber in 2 Komponenten gesplittet:
a) „schneller“ Handler
b) „sicherer“ Handler
HARTIK
15. Einfache Echtzeit-Exekutive (Kernel) / 15.14 DICK‘s „lauffähige“ Verwandte
Verteilte Echtzeitsysteme:
© ws 2018/19 H.-A. Schindler Folie: 15 - 94
Im Internet
HARTIK u. SHaRK inklusive Quellcode verfügbar unter den Adressen:
http://hartik.sssup.it
bzw.
http://shark.sssup.it
ENDE Abschnitt 15
HARTIK & SHaRK
Unter obiger Adresse: auch gezeigtes SHaRK-Video
15. Einfache Echtzeit-Exekutive (Kernel) / 15.14 DICK‘s „lauffähige“ Verwandte