Verteilte Echtzeit-SystemeŸerdem kurz: HARTIK u. SHaRK (verwandte funktionsfähige Kerne) Dabei:...

94
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

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