Moderne Realzeitsysteme kompakt - Jürgen Quade - E-Book

Moderne Realzeitsysteme kompakt E-Book

Jürgen Quade

0,0

Beschreibung

Dieses Buch behandelt den Entwurf und die Realisierung von Realzeitsystemen und berücksichtigt dabei die tiefgreifenden Fortschritte der jüngsten Zeit. Anhand zahlreicher Codebeispiele vermitteln die Autoren die nebenläufige Realzeitprogrammierung (Posix) und den Aufbau unterschiedlicher Realzeitarchitekturen auf Basis von Embedded Linux. Sie führen ein in die Terminologie und den Aufbau moderner Realzeitbetriebssysteme, in formale Beschreibungsmethoden sowie in die Grundlagen der Betriebs- und IT-Sicherheit und in den Realzeitnachweis.Ein Buch für Studierende und Praktiker. Hinweis: Dieses E-Book ist nur teilweise mit interaktiven Elementen (aktives Inhaltsverzeichnis, Querverweise) ausgestattet! Wir bieten Ihnen das PDF daher zu einem günstigeren Preis an.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern
Kindle™-E-Readern
(für ausgewählte Pakete)

Seitenzahl: 309

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Jürgen Quade studierte Elektrotechnik an der TU München. Danach arbeitete er dort als Assistent am Lehrstuhl für Prozessrechner (heute Lehrstuhl für Realzeit-Computersysteme), promovierte und wechselte später in die Industrie, wo er im Bereich Prozessautomatisierung bei der Softing AG tätig war. Heute ist Jürgen Quade Professor an der Hochschule Niederrhein, wo er u.a. das Labor für Echtzeitsysteme betreut. Seine Schwerpunkte sind Echtzeitsysteme, Embedded Linux, Rechner- und Netzwerksicherheit sowie Open Source. Als Autor ist er vielen Lesern über das dpunkt-Buch »Linux-Treiber entwickeln« und die regelmäßig erscheinenden Artikel der Serie »Kern-Technik« im Linux-Magazin bekannt.

Michael Mächtel ist Professor für Betriebssysteme an der Hochschule für Technik, Gestaltung und Wirtschaft in Konstanz, wo er u.a. das Labor für Systemsoftware und Realzeitsysteme betreut. Nach dem Studium der Elektrotechnik an der TU München arbeitete er im Bereich Fahrzeugtechnik. In seiner Promotion untersuchte er die Ursachen für Latenzzeiten in Realzeit-Betriebssystemen. Seit mehr als 20 Jahren arbeitet Michael Mächtel sowohl an der Universität als auch in der Wirtschaft im Embedded-System-Umfeld. Seine engeren Fachgebiete sind Betriebssysteme und Systemsoftware, Realzeitsysteme sowie Embedded Systems mit Schwerpunkt Embedded Linux.

Moderne Realzeitsysteme kompakt

Eine Einführung mit Embedded Linux

Jürgen QuadeMichael Mächtel

Jürgen [email protected][email protected]

Lektorat: René SchönfeldtCopy Editing: Sandra Gottmann, MünsterSatz: data2type GmbH, HeidelbergHerstellung: Nadine ThieleAutorenfotos: privat (Quade), Franzis von Stechow (Mächtel)Umschlaggestaltung: Helmut Kraus, www.exclam.deDruck und Bindung: M.P. Media-Print Informationstechnologie GmbH, 33100 Paderborn

Bibliografische Information der Deutschen NationalbibliothekDie Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie;detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN:Buch 978-3-89864-830-1PDF 978-3-86491-217-7ePub 978-3-86491-218-4

1. Auflage 2012Copyright © 2012 dpunkt.verlag GmbHRingstraße 19B69115 Heidelberg

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.

Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.

Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Vorwort

Der amerikanische Begriff Realtime System wird im Deutschen mit Echtzeitsystem oder Realzeitsystem übersetzt. Alle drei Begriffe bezeichnen im technischen Umfeld Systeme, die neben funktionalen auch zeitlichen Anforderungen genügen. Während der populäre Begriff Echtzeit ganz allgemein eingesetzt wird, wird der Begriff Realzeit eindeutig auf den technischen Bereich fokussiert – weswegen ihm in den folgenden Ausführungen der Vorzug gegeben wird.

Realzeitaspekte gehören seit vielen Jahren zur klassischen Informatiker- und Ingenieursausbildung. Die fortschreitende Miniaturisierung und Leistungssteigerung der Hardware auf der einen Seite und die technologischen Entwicklungen in der Software – allen voran bei Linux – auf der anderen Seite ermöglichen dem Entwickler heute, seine Systeme mit erheblich mehr Funktionalität auszustatten als es früher mit vertretbarem Aufwand möglich war. Allerdings: Die eingesetzten Entwurfstechniken stehen den klassischen Technologien zum Teil diametral entgegen. Wurden früher parallel stattfindende Abläufe trickreich in eine Singlethread-Lösung gepackt, werden heute sequenzielle Abläufe parallelisiert: Erst damit wird eine Multicore-CPU effizient genutzt.

Der Wandel im Bereich der Realzeitsysteme geht noch tiefer. Die Parallelisierung beispielsweise bringt neue Probleme, wie den Schutz kritischer Abschnitte, mit sich. Deren klassische Methoden, nämlich Interrupts zu sperren oder ein Semaphor einzusetzen, bringen das Zeitverhalten durcheinander. Oder: Die Vernetzung benötigt Schutzmechanismen, um Hackerangriffe abzuwehren.

Diese ausgewählten Beispiele stehen stellvertretend für unsere Motivation, die Grundlagen moderner Realzeitsysteme kompakt zu beschreiben und zu diskutieren. Die Auswahl der Inhalte stammt sowohl aus Vorlesungen, die wir in den Studiengängen Informatik, Elektrotechnik und Mechatronik halten, als auch aus Industrieprojekten. Uns ist bewusst, dass viele Aspekte wie beispielsweise XML oder Webservices unberücksichtigt geblieben sind. Trotz dieser Auslassungen liegt das Themenspektrum im Umfang deutlich über der ursprünglichen Planung.

Wir hoffen, dass der Leser unsere Auswahl und die Beschreibungen nützlich und hilfreich findet!

Inhaltsverzeichnis

1       Einleitung

2       Realzeitbetrieb

2.1     Zentrale Beschreibungsgrößen

2.1.1    Beschreibungsgrößen des technischen Prozesses

2.1.2    Beschreibungsgrößen der Rechenprozesse

2.1.3    Beschreibungsgrößen der Systemsoftware

2.2     Realzeitbedingungen

2.2.1    Gleichzeitigkeit und Auslastung

2.2.2    Rechtzeitigkeit

2.2.3    Harte und weiche Realzeit

2.3     Systemaspekte

2.3.1    Unterbrechbarkeit

2.3.2    Prioritäten

2.3.3    Ressourcenmanagement

3       Systemsoftware

3.1     Firmware

3.2     Realzeitbetriebssysteme

3.2.1    Systemcalls

3.2.2    Taskmanagement

3.2.3    Memory Management

3.2.4    I/O-Management

3.2.5    Timekeeping (Zeitverwaltung)

3.2.6    Sonstige Realzeitaspekte

3.3     Linux

4       Aspekte der nebenläufigen Realzeitprogrammierung

4.1     Allgemeines

4.2     Programmtechnischer Umgang mit Tasks

4.2.1    Tasks erzeugen

4.2.2    Tasks beenden

4.2.3    Tasks parametrieren

4.3     Schutz kritischer Abschnitte

4.3.1    Semaphor und Mutex

4.3.2    Programmtechnische Behandlung der Prioritätsinversion

4.3.3    Deadlock

4.3.4    Schreib-/Lese-Locks

4.3.5    Weitere Schutzmaßnahmen für kritische Abschnitte

4.3.6    Unterbrechungsmodell

4.4     Umgang mit Zeiten

4.4.1    Aktuelle Zeit bestimmen

4.4.2    Der Zeitvergleich

4.4.3    Differenzzeitmessung

4.4.4    Schlafen

4.4.5    Weckrufe per Timer

4.5     Inter-Prozess-Kommunikation

4.5.1    Pipes, Mailbox und Messages

4.5.2    Shared-Memory

4.5.3    Sockets

4.6     Condition-Variable (Events)

4.7     Signale

4.8     Peripheriezugriff

4.9     Bitoperationen

4.10   Memory Management

5       Realzeitarchitekturen

5.1     Realzeitsysteme ohne spezielle Systemsoftware

5.2     Realzeitsysteme basierend auf einem Standard-OS

5.3     Threaded Interrupts (Realzeiterweiterungen für Standardbetriebssysteme)

5.4     Userland-to-Kernel

5.5     Realzeitbetriebssystem

5.6     Realzeitarchitektur auf Multicore-Basis

5.7     Multikernel-Architektur (RTAI/Xenomai)

5.8     Besonderheiten beim Entwurf moderner Realzeitsysteme

6       Safety und Security

6.1     Grundbegriffe der Betriebssicherheit (Safety)

6.2     Angriffssicherheit (Security)

6.2.1    Geräteimmanente Schutzvorrichtungen

6.2.2    Strukturelle Abwehrmaßnahmen (Security by Structure)

7       Formale Beschreibungsmethoden im Überblick

7.1     Daten- und Kontrollflussdiagramm

7.2     Struktogramme

7.3     Beschreibung nebenläufiger Prozesse (Petrinetze)

7.4     Netzwerkanalyse

7.5     UML

7.5.1    Strukturdiagramme

7.5.2    Verhaltensdiagramme

8       Realzeitnachweis

8.1     Grundlagen

8.2     Nachweis ohne Berücksichtigung der Ressourcen

8.2.1    Prioritätengesteuertes Scheduling

8.2.2    EDF-Scheduling

8.3     Nachweis unter Berücksichtigung der Ressourcen

8.3.1    Berechnung der Blockierzeit

8.3.2    Schedulingtest

8.4     Bewertung und weitere Einflussfaktoren

Bibliographie

Stichwortverzeichnis

1 Einleitung

Systeme, die neben den ohnehin vorhandenen funktionalen Anforderungen zusätzlich noch zeitlichen Anforderungen – typischerweise im Sekundenbereich und darunter – genügen müssen, werden als Realzeitsysteme bezeichnet.

Als wesentliche Komponente eines solchen Realzeitsystems gilt die Steuerung, die über Ein- und Ausgabeinterfaces, über Sensoren und Aktoren mit dem Benutzer und der Umwelt kommuniziert. Klassische Realzeitsteuerungen bestehen aus einer Singlecore-CPU, die häufig am leistungstechnischen Limit betrieben wird. Als Systemsoftware wird – wenn überhaupt – ein schlankes, vielfach selbst entwickeltes Realzeitbetriebssystem eingesetzt.

Dabei wird der Entwickler oft mit dem Problem konfrontiert, viele unterschiedliche Aufgaben in einer einzelnen Task zu implementieren. Der Zugriff auf Hardware erfolgt direkt, ohne Interaktion mit der Systemsoftware. Höhere Funktionalitäten wie Internetdienste sind in diesem Umfeld nur mit erheblichem Aufwand zu realisieren.

Neue Entwicklungen auf dem Gebiet der Prozessoren hin zu mehr Leistungsstärke, zu Energieeffizienz und zu Multicore eröffnen neue Möglichkeiten, moderne Realzeitsysteme zu verwirklichen. In modernen Realzeitsteuerungen löst der sogenannte Tickless-Betrieb die periodisch ablaufende Systemsoftware ab. Intuitive Mensch-Maschine-Schnittstellen und Vernetzung, insbesondere die Internetanbindung, stehen dem Entwickler über standardisierte Interfaces zur Verfügung. Anstelle proprietärer Systemsoftware bietet sich ein echtzeitfähiges Standardbetriebssystem an, bei dem beispielsweise ein einzelner Prozessorkern für Realzeitaufgaben reserviert werden kann.

Die Applikation passt sich an. Wo klassisch ein einzelner Thread ereignisgesteuert viele unterschiedliche Aufgaben abarbeitet, werden bei einem modernen Systementwurf unabhängige Aufgaben identifiziert und in separate Tasks implementiert. Die dabei notwendige Inter-Prozess-Kommunikation bringt allerdings kritische Abschnitte mit sich, die mit geeigneten Methoden zu schützen sind.

Für die Kodierung greift der Entwickler auf die vielfältigen, vorgefertigten und ebenfalls standardisierten Funktionen des Betriebssystems zurück, um beispielsweise Tasks zu erzeugen, zu priorisieren oder auf einen Rechnerkern zu fixieren; auf Funktionen, um den Scheduler zu konfigurieren, zwischen seinen Tasks Daten auszutauschen oder um kritische Abschnitte zu schützen, und auf Funktionen, die für das Zeitmanagement benötigt werden.

Die Erstellung eines modernen Echtzeitsystems erfordert über die Kenntnis der technischen Möglichkeiten hinaus ein theoretisches Basiswissen. Neben der formalen Beschreibung seines Entwurfs muss der Entwickler aus der Aufgabenstellung die Echtzeitparameter für den Realzeitnachweis extrahieren und die zugehörigen Realzeitbedingungen aufstellen und anhand des von ihm erstellten Entwurfs überprüfen können. Für diesen notwendigen, in der Praxis häufig ausgelassenen Schritt benötigt der Entwickler Kenntnisse über das eingesetzte Scheduling-Verfahren und über die detallierte Verarbeitung kritischer Abschnitte.

Ziel dieses Buches ist es damit,

Grundkenntnisse moderner Realzeitsysteme kompakt und praxisorientiert zu vermitteln,

die Parameter vorzustellen, die die zeitlichen Anforderungen auf der einen Seite und das Zeitverhalten der zur Lösung eingesetzten Rechenprozesse auf der anderen Seite beschreiben,

die Möglichkeiten zum Entwurf und zur Realisierung moderner Realzeitsysteme auf Basis von Single- oder Multicore-Hardware aufzuzeigen,

die vielfältigen Einsatzmöglichkeiten von (Embedded) Linux im Realzeitumfeld zu verdeutlichen,

die praxisrelevanten Funktionen zur Realisierung der Applikation anhand von Codebeispielen vorzustellen,

in die Grundlagen der Betriebssicherheit (Safety) und der Angriffssicherheit (Security) einzuführen,

einfache und weitestgehend intuitiv einzusetzende formale Beschreibungsmethoden vorzustellen und

das Rüstzeug für einen Realzeitnachweis zu vermitteln, der auch Blockierzeiten berücksichtigt.

Scope

Das Buch gibt einen kompakten Überblick über die wesentlichen Aspekte von Realzeitsystemen. Es ist damit weder ein themenumfassendes Handbuch, noch ein auf Einzelaspekte fokussiertes Werk.

Das Buch richtet sich sowohl an Neulinge auf dem Gebiet der Realzeitsysteme, wie beispielsweise Studenten der Informatik, Elektrotechnik oder Mechatronik, als auch an den erfahrenen Entwickler. Es soll dabei den Systemarchitekten ebenso ansprechen wie den Programmierer. Da softwarespezifische Aspekte im Vordergrund stehen, richtet es sich nicht an Hardwareentwickler.

Grundkenntnisse auf dem Gebiet der Betriebssysteme sind zum Verständnis von Vorteil, die Codebeispiele im Praxisteil sind in der Programmiersprache C geschrieben. Sie sind grundsätzlich unabhängig von einer spezifischen Systemversion, wir haben sie auf einem Ubuntu 12.04 LTS mit Kernel 3.2 getestet.

Das Buch ist aufgrund der Verbreitung und der herausragenden Eigenschaften Linux-zentriert, allerdings dabei unabhängig von einer spezifischen Plattform oder einer bestimmten CPU. In Beispielen referenzieren wir meist die verbreiteten x86- oder ARM-Architekturen.

Realzeitsysteme werden im amerikanischen Sprachraum sehr häufig mit eingebetteten Systemen (Embedded Systems) gleichgesetzt. Streng genommen ist das nicht korrekt, denn die integrierte, mikroelektronische Steuerung – so die Definition eines eingebetteten Systems – muss nicht zwangsweise zeitliche Anforderungen erfüllen. Dennoch besteht zwischen Realzeitsystemen und eingebetteten Systemen eine enge Verwandtschaft und ist daher auch Thema dieses Buches. Sogenannte Deeply Embedded Systems – Systeme, die auf einfachen Prozessoren und oft selbst geschriebener Systemsoftware beruhen – sind allerdings außerhalb des Scopes.

Aufbau des Buches

In Kapitel 2 werden zunächst die Beschreibungsgrößen eines Realzeitsystems definiert und die Bedingungen abgeleitet, die zur Erfüllung der zeitlichen Anforderungen einzuhalten sind.

Das dritte Kapitel stellt die für das Realzeitverhalten wesentlichen Komponenten der Systemsoftware vor. Dazu gehören beispielsweise die innerhalb der Realzeitsysteme auswählbaren und parametrierbaren Scheduling-Strategien und die Zeitverwaltung.

Aspekte der nebenläufigen Realzeitprogrammierung behandelt das vierte Kapitel anhand von vielen Codebeispielen. Hier werden die wichtigsten Systemcalls und Funktionen vorgestellt, mit denen Tasks erzeugt, Zeiten gelesen oder kritische Abschnitte geschützt werden.

Verschiedene, mit Linux gut realisierbare Realzeitarchitekturen, basierend auf Single- und Multicore-Hardware, werden im fünften Kapitel vorgestellt.

Realzeitsysteme werden häufig im sicherheitskritischen Umfeld eingesetzt. Daraus resultieren erweiterte Anforderungen an die Korrektheit, an die Ausfallsicherheit, aber auch an den Schutz vor unbefugtem Zugriff, lokal, aber auch über das Internet. Kapitel 6 behandelt Aspekte der Betriebs- und der Angriffssicherheit.

Kapitel 7 gibt dem Entwickler ausgewählte Methoden an die Hand, mit denen die Taskgebilde eines Realzeitentwurfs dargestellt und die Abläufe innerhalb der Tasks modelliert werden können. Vielen Lesern dürften die vorgestellten Verfahren bekannt sein; das hat uns motiviert, den Abschnitt weiter hinten im Buch zu platzieren.

Das letzte Kapitel widmet sich schließlich dem Realzeitnachweis, mit dem formal das Einhalten der zeitlichen Anforderungen unter Berücksichtigung verschiedener Systemparameter (zum Beispiel Scheduling) nachgewiesen werden kann.

Embedded Linux

Im Rahmen des Buches referenzieren wir immer wieder auf Linux. Tatsächlich ist Linux in den letzten Jahren zu einem Standardbetriebssystem mit Realzeiteigenschaften umgebaut worden. Dabei ist Linux – natürlich abhängig von der eingesetzten Hardware – in der Lage, harte Zeitgrenzen im Mikrosekundenbereich einzuhalten. Allerdings benötigt der Kernel hierzu zurzeit noch den sogenannten PREEMPT-RT-Patch ([http://www.kernel.org/pub/linux/kernel/projects/rt/]). Da Linus Torvalds mit jeder neuen Kernel-Version Teile des Patches übernimmt, wird das Patchen jedoch schon sehr bald unnötig sein.

Langzeitmessungen am Kernel belegen, dass das deterministische Zeitverhalten unabhängig von der eingesetzten Prozessorarchitektur und auch langzeitstabil ist [QuKu2012-63]. Das wird durch die sogenannten High Resolution Timer (hrtimer) und den Tickless-Betrieb erreicht. Das Zeitmanagement des Kernels basiert intern nicht mehr auf Timerticks, sondern auf einer Zeitbasis in Nanosekundenauflösung. Zeitaufträge werden also nicht mehr mit dem nächsten Timertick, sondern zu exakt den Zeitpunkten angestoßen, zu denen der Auftrag terminiert ist.

Das für ein Realzeitbetriebssystem typische prioritätengesteuerte Scheduling unterstützt Linux bereits seit vielen Jahren, ebenso wie Mutexe, die eine sogenannte Prioritätsvererbung ermöglichen.

Linux zeichnet aber noch mehr aus. Mithilfe von Control-Groups lassen sich Tasks gezielt auf einzelne Kerne einer Multicore-Maschine fixieren und per Threaded Interrupts werden Interrupt-Service-Routinen als priorisierbare Threads abgearbeitet.

Das Applikationsinterface orientiert sich für Realzeitanwendungen am POSIX-Standard.

Neben den Realzeiteigenschaften weist Linux weitere Merkmale auf, die es für den Einsatz als Embedded System prädestinieren. Wesentliche Eigenschaften sind

Skalierbarkeit,

Modularität,

Portierbarkeit,

Quelloffenheit,

eine große Entwicklergemeinde und

gute und umfangreiche Dokumentation.

Um ein Embedded System zusammenzustellen und zu bauen, können Sie auf diverse Hilfsmittel wie beispielsweise Buildroot (siehe Abschnitt 3.3) oder OpenEmbedded ([http://www.openembedded.org]) zurückgreifen. Buildroot bietet sich für kleinere Projekte an, auf OpenEmbedded greifen Sie erst zurück, wenn Sie sehr komplexe Systeme aufbauen müssen. Beide Programme bauen nicht nur das eigentliche System zusammen, sondern sorgen selbstständig dafür, dass die notwendigen Entwicklungswerkzeuge wie beispielsweise Crosscompiler zur Verfügung stehen.

2 Realzeitbetrieb

Realzeitsysteme sind Systeme, die neben den funktionalen Anforderungen auch zeitlichen Anforderungen genügen. Sie sind also für die fristgerechte Reaktion auf Ereignisse zuständig. Diese Ereignisse – wie beispielsweise Überdrucksignale oder aber auch die Tastatureingaben eines Computerspiels – wirken quasi von außen auf das Realzeitsystem ein. Somit gibt die Umgebung zeitliche Anforderungen vor, denen das Realzeitsystem, das softwaretechnisch aus einer Reihe von Rechenprozessen, den Tasks (siehe Abschnitt 3.2.2), besteht, genügen muss.

Insofern sind im Folgenden die von außen eintreffenden Anforderungen, die darauf reagierenden Rechenprozesse und die für das Zeitverhalten mitverantwortliche Systemsoftware (Betriebssystem) zeitlich zu charakterisieren. Aus der zeitlichen Charakterisierung lassen sich zwei Echtzeitbedingungen ableiten. Der letzte Abschnitt dieses Kapitels behandelt anschließend funktionale Anforderungen an die Systemsoftware und weitere Aspekte, die sich aus der Abarbeitung beziehungsweise dem Zusammenspiel der Rechenprozesse ergeben. Zentral ist dabei der Umgang mit Ressourcen.

Abbildung 2-1 Realzeitsteuerungen verarbeiten Signale von und für die Umwelt.

Zur Erläuterung werden wir häufiger auf das Beispiel eines Fahrradcomputers zurückgreifen. Dieser bekommt mit jeder Umdrehung des Vorderrades über einen Magnetschalter ein Signal, aus dem unter Kenntnis der Vorderradgröße die Trittfrequenz, die Geschwindigkeit und die zurückgelegte Strecke abgeleitet werden können. Das Ergebnis der Berechnungen wird per Touchscreen dem Radfahrer visualisiert. Zur Umwelt gehören demnach das Signal des Magnetschalters ebenso wie der Touchscreen, der sowohl für die Ausgaben zuständig ist als auch die Eingaben des Radfahrers entgegennimmt.

2.1 Zentrale Beschreibungsgrößen

Im Folgenden werden zunächst die zentralen Beschreibungsgrößen des technischen Prozesses, der Rechenprozesse und schließlich der Systemsoftware beschrieben.

2.1.1 Beschreibungsgrößen des technischen Prozesses

Der technische Prozess repräsentiert die Umwelt, die über Sensoren als Datenquellen Informationen zur Verfügung stellt beziehungsweise die über Aktoren (Datensenken) beeinflusst wird. Der Prozess wird formal über die von ihm gestellten Anforderungen an Rechenzeit und die zugehörigen Zeitparameter (Releasetime, Prozesszeit, Deadlines und Phase) beschrieben.

Rechenzeitanforderung

Löst der technische Prozess ein Ereignis aus, muss dieses in der zugehörigen Realzeitsteuerung (Computer) verarbeitet werden. Aus Sicht des Rechners stellt der technische Prozess eine Rechenzeitanforderung. Um die einzelnen Rechenzeitanforderungen voneinander unterscheiden zu können, werden sie mithilfe ihres Namens oder auch eines Buchstabens gekennzeichnet.

Beispiel 2-1 Rechenzeitanforderungen an einen modernen Fahrradcomputer

Aus Sicht des Fahrradcomputers stellt das Signal, das mit jeder Umdrehung des Vorderrades übermittelt wird, eine Rechenzeitanforderung dar, die vom Computer zu bearbeiten ist. Dieses Signal könnte mit einem u (für Umdrehung) gekennzeichnet werden. Eingaben über den Touchscreen sind ebenfalls Rechenzeitanforderungen des technischen Prozesses, die in diesem Fall vom Radfahrer stammen.

Releasetime

In Zeitdiagrammen wird der Zeitpunkt, an dem eine Rechenzeitanforderung auftritt, durch den zugehörigen Buchstaben gekennzeichnet (siehe Abbildung 2-2).

Abbildung 2-2 Rechenzeitanforderungen in Diagrammen

Prozesszeit

Der zeitliche Abstand zwischen zwei Rechenzeitanforderungen (Ereignissen) gleichen Typs ist die Prozesszeit, manchmal auch Periode tP genannt. Einer Rechenzeitanforderung i ist eine Prozesszeit tP,i zugeordnet (siehe Abbildung 2-3).

Abbildung 2-3 Prozesszeit

Prozesszeiten sind selten konstant. Sie schwanken zwischen einem minimalen Wert tPmin,i (es vergeht wenig Zeit, bis die nächste Anforderung kommt) und einem maximalen tPmax,i. tPmax,i repräsentiert das seltene Auftreten einer Rechenzeitanforderung und ist daher für Realzeitsysteme ohne Bedeutung.

Der Kehrwert der Prozesszeit tP,i ist die Rate ri. Relevant ist vor allem die maximale Rate, die den Kehrwert der minimalen Prozesszeit darstellt.

Beispiel 2-2 Bestimmung der minimalen Prozesszeit

Der minimale zeitliche Abstand tPmin,u für die Rechenzeitanforderung u des Fahrradcomputers, also des Signals, das mit jeder Radumdrehung ausgelöst wird, lässt sich auf Basis des Radumfanges und der maximalen Fahrgeschwindigkeit berechnen. Hierzu wird die für eine Umdrehung minimal zurückgelegte Strecke (der minimale Radumfang) durch die maximale Geschwindigkeit dividiert. Das Vorderrad hat typischerweise einen Umfang zwischen 1200 mm bis 2300 mm. Als maximale Geschwindigkeit setzen wir 150 km/h an, also 41.667 m/s.

Übrigens ist die Bestimmung von tPmax,u trivial. Der maximale zeitliche Abstand ergibt sich nämlich, wenn das Fahrrad steht, das Vorderrad sich also nicht dreht; tPmax,u ist dann unendlich.

Zulässige Reaktionszeit (Deadline)

Der technische Prozess legt fest, ab welchem Zeitpunkt auf eine Rechenzeitanforderung i reagiert werden darf (minimale Deadline, tDmin,i) und bis wann auf eine Rechenzeitanforderung durch das Steuerungssystem reagiert worden sein muss (maximale Deadline, tDmax,i).

Mit tDmin,i wird die untere Schranke bezeichnet, vor der keine Reaktion durch das Realzeitsystem erfolgen darf. In vielen technischen Prozessen darf direkt nach Auftreten der Rechenzeitanforderung reagiert werden. Die minimal zulässige Reaktionszeit ist in diesem Fall tDmin,i=0.

Abbildung 2-4 Minimal zulässige Reaktionszeit am Beispiel eines zweistufigen Airbags

Mit tDmax,i wird die obere Schranke bezeichnet, bis zu der die Reaktion auf die Rechenzeitanforderung i erfolgt sein muss. Viele technische Prozesse erwarten eine abgeschlossene Reaktion auf eine Rechenzeitanforderung i spätestens bis die Rechenzeitanforderung i ein zweites Mal auftritt. In diesem Fall ist die maximal zulässige Reaktionszeit tDmax,i ≤ tPmin,i.

Abbildung 2-5 Maximal zulässige Reaktionszeit am Beispiel Airbag

Phase

2.1.2 Beschreibungsgrößen der Rechenprozesse

Die Umwelt wird durch das eigentliche Echtzeitsystem – die Steuerung – beeinflusst. Dazu wird ein Rechner eingesetzt, auf dem für jede Rechenzeitanforderung eine Codesequenz abgearbeitet wird. Die Codesequenz ist meistens als eigenständige Task ausgeprägt, die durch die beiden Parameter Ausführungszeit und Reaktionszeit beschrieben wird.

Ausführungszeit

Die Ausführungszeit tE einer Task ist die Zeit, die benötigt wird, um den Code der Task auf einem definierten Rechner abzuarbeiten. Somit stellt die Ausführungszeit die Summe der CPU-Zyklen dar, die für die Abarbeitung benötigt werden. Handelt es sich bei der Task um eine hundertprozentig CPU-intensive Task und ist diese Task die einzig aktive Task im System, so ergibt sich die Ausführungszeit als Differenz zwischen Endzeit und Startzeit.

Ungewollte und durch das System verursachte Verzögerungen (Latenzzeiten) sowie Zeiträume, in denen sich die Task gewollt schlafen legt, werden nicht zur Ausführungszeit gezählt.

Die Ausführungszeit schwankt zwischen einer Best Case Execution Time (BCET) tEmin (siehe unten) und einer Worst Case Execution Time (WCET) tEmax (siehe Seite 13). Ursachen dafür sind:

Der implementierte Algorithmus: So werden beispielsweise abhängig von den Eingangsparametern unterschiedliche Codepfade durchlaufen.

Caches (Daten- und Instruktionscaches, aber auch Translation Lookaside Buffer): Befindet sich beispielsweise der zur Task gehörende Code im Instructioncache, wird der Code mit sehr hoher Geschwindigkeit abgearbeitet. Muss die CPU den Code jedoch erst vom Hintergrundspeicher laden, wird erheblich mehr Zeit benötigt.

Andere Begriffe für die Ausführungszeit (Execution Time) sind Rechenzeit (Computation Time), Laufzeit oder auch Verarbeitungszeit.

Trägt man die Verarbeitungszeit tE über die Zeit auf, erhält man die sogenannte Rechnerkernbelegung (Abbildung 2-6). Sie gibt Auskunft darüber, zu welchen Zeiten die Verarbeitungseinheit mit welcher Aufgabe betraut ist. Zur einfachen Erstellung der Rechnerkernbelegung ist es sinnvoll, in das Diagramm als Erstes die Zeitpunkte, an denen Rechenzeitanforderungen auftreten (tRelease, Abbildung 2-2), einzutragen.

Abbildung 2-6 Rechnerkernbelegung

Abschätzung der Best Case Execution Time (BCET)

Die Best Case Execution Time einer Task muss bestimmt werden, falls eine Codesequenz nicht vor einer minimal zulässigen Reaktionszeit tDmin,i abgearbeitet worden sein darf.

Wie bei der WCET gibt es zur Bestimmung den analytischen oder den experimentellen Ansatz. Beim analytischen Ansatz wird der vorhandene Code analysiert und der kürzeste Pfad gesucht. Aufgrund der Kenntnisse über die eingesetzte Hardware (CPU, Speicher) kann daraus die Abarbeitungszeit abgeleitet werden.

Beim experimentellen Ansatz wird der Code implementiert und der Entwickler lässt ihn auf der Zielhardware ablaufen. Die einzig vorgenommene Modifikation besteht darin, zu Beginn und zum Ende einen Zeitstempel zu nehmen, sodass per Differenzzeitmessung (siehe Abschnitt 4.4.3) tEmin,i bestimmt werden kann. Wichtig ist dabei, dass das System während der Messung lastfrei und nach Möglichkeit nur der auszumessende Code aktiv ist.

Abschätzung der Worst Case Execution Time (WCET)

Die maximale Verarbeitungszeit tEmax – auch Worst Case Execution Time (WCET) genannt – einer Rechenzeitanforderung ist sehr schwer zu bestimmen. Die WCET hängt insbesondere vom Algorithmus, von der Implementierung des Algorithmus, von der verwendeten Hardware und von den sonstigen Aktivitäten des Systems (den anderen Rechenprozessen) ab. Daher kann die WCET allenfalls abgeschätzt werden.

Prinzipiell werden zwei Methoden zur Bestimmung der WCET unterschieden:

1. das Ausmessen der WCET und

2. die statische Analyse inklusive der daraus erfolgenden Ableitung der WCET.

In der Realität wird zur Abschätzung der WCET einer Task in vielen Fällen die oben genannte Messmethode verwendet. Die statische Analyse ist mehr im akademischen Umfeld verbreitet, rückt aber zunehmend aufgrund des Unsicherheitsfaktors der bisherigen Messmethode in den Fokus der Industrie. Für weitere Informationen siehe auch [LoMa11].

Ausmessen der WCET. Die WCET wird dadurch bestimmt, dass die zugehörige Codesequenz (im Regelfall auf der Zielplattform) abgearbeitet wird. Dabei wird die Zeit zwischen Eintreten der Rechenzeitanforderung und der zugehörigen Ausgabe bestimmt.

Abbildung 2-7 Messprinzip zur Bestimmung der WCET

Zur Messung dieser Zeit lassen sich prinzipiell zwei Verfahren unterscheiden:

1. Messung durch das auszumessende Codestück selbst mithilfe einer Differenzzeitmessung (siehe Abschnitt 4.4.3 und Abbildung 2-7).

Das Codestück wird so ergänzt, dass jedes Mal, wenn eine Rechenzeitanforderung auftritt und wenn die Reaktion erfolgt ist, ein Zeitstempel abgelegt wird. Die Differenz ergibt die aktuelle Ausführungszeit tEmax.

Beim ersten Durchlauf wird diese als WCET abgelegt. Bei den nachfolgenden Durchläufen wird die neu berechnete Zeit mit der abgelegten Zeit verglichen. Ist die neu berechnete Zeit größer als die bisher gemessene WCET, überschreibt der neue Wert die bisherige WCET.

Eventuell kann anstelle der Modifikation des Codestücks auch ein Profiler eingesetzt werden.

2. Externe Messung von Ereignis und Reaktion (Ausgabe) zum Beispiel mithilfe eines Oszilloskops.

Damit eine WCET gemessen werden kann, muss die Codesequenz mit geeigneten Input-Werten versorgt werden. Für jeden Parameter wird der Wertebereich festgelegt. Die Messungen werden daraufhin mit verschiedenen Input-Daten durchlaufen: mit einem Wert, der für jeden Parameter einmal an den Rändern des Wertebereiches und einmal in der Mitte liegt. Darüber hinaus sollte aus Sicherheitsgründen auch eine Messung mit Werten außerhalb des identifizierten Wertebereiches vorgenommen werden.

Um die Ausführungszeiten im schlimmsten Fall zu bestimmen, ist darüber hinaus der Rechner unter Last zu setzen, um damit den Einfluss des Caches mit zu berücksichtigen. Allerdings kommt es durch die Lasterzeugung zu Kernel-Latenzzeiten, die im eigentlichen Sinne nicht Teil der Ausführungszeit sind. In der Praxis ist das jedoch unproblematisch.

Vorteile dieser Methode:

Unabhängig von einer Programmiersprache.

Vergleichsweise einfach realisierbar.

Nachteile der Messmethode:

Die WCET einer Codesequenz kann nicht garantiert werden, da sie von zu vielen Einflussfaktoren (Vorgeschichte, Schleifendurchläufe, Caches, Verzweigungen usw.) abhängt.

Das Messen ist zeitaufwendig und damit letztlich teuer. Das auszumessende Codestück muss theoretisch mit sämtlichen Inputdaten (in jeglicher Kombination) beschickt werden.

Diese Methode kann korrekt nur mit dem produktiven Code auf der Zielplattform durchgeführt werden. Damit ist eine Abschätzung zu einem frühen Zeitpunkt nur bedingt möglich.

Für die Durchführung der Messung muss eine Messumgebung, die die Inputdaten zur Verfügung stellt, geschaffen werden.

Die auszumessende Codesequenz ist unter Umständen zum Ablegen von Zeitstempeln zu modifizieren.

Durch die Messung unter Last kommt es zu ungenauen Ergebnissen, da Kernel-Latenzzeiten mitgemessen werden, die streng genommen nicht zur WCET gehören.

Statische Analyse. Hierbei wird der Code selbst analysiert. Dazu ist ein Analyseprogramm notwendig, welches meist mit dem C-Quellcode, manchmal aber auch mit dem Objektcode gefüttert wird. Außerdem ist eine Hardwarebeschreibung erforderlich. Die Analysewerkzeuge arbeiten so, dass aus dem Code zunächst ein Kontrollgraph erstellt wird. Die Laufzeit der einzelnen Codesequenzen des Kontrollgraphen können abgeschätzt werden. Im Anschluss muss die Anzahl der Schleifendurchläufe berücksichtigt werden.

Komplex wird die Analyse durch die notwendige Abschätzung von sogenannten Cache-Hits und Cache-Misses und des Prozessor-Pipelinings. Cache-Hits und Cache-Misses nennt man den Umstand, dass Code oder Daten bereits im Prozessor zwischengespeichert sind oder eben auch nicht. Sind sie nicht zwischengespeichert, müssen sie erst zeitaufwendig aus dem Hauptspeicher geladen werden. Das Pipelining ist eine Prozessoreigenschaft, die die Abarbeitung dadurch beschleunigt, dass Befehle vor der eigentlichen Ausführung bereits dekodiert werden. Insbesondere bei Verzweigungen ist diese Optimierung manchmal nicht nutzbar.

Unabhängig vom Verfahren gilt prinzipiell, den ausgemessenen Code nicht nachträglich zu verändern und außerdem noch mit einem Sicherheitsaufschlag zu versehen. Als Sicherheitsaufschlag arbeitet der Ingenieur manchmal mit der Zahl π.

Die Bestimmung der WCET von Code, der auf einer Multicore-Maschine abgearbeitet wird, ist besonders schwierig. Hierbei kommen diverse Aspekte, wie beispielsweise die Zeit für die Taskmigration oder die unterschiedlichen Ausführungszeiten durch die Migration (Neubefüllen der Caches), zum Tragen. Erst zur Laufzeit werden aufgrund der Auslastung des Systems Tasks zwischen CPUs migriert. Wie oft dies beim Worst Case der Fall ist, hängt somit von der Auslastung des Gesamtsystems ab.

Reaktionszeit

Unter Reaktionszeit tR wird die Zeit verstanden, die zwischen dem Auftreten einer Rechenzeitanforderung und dem Ende der Bearbeitung vergeht (siehe Abbildung 2-8). Durch die unterschiedlichen Wartezeiten kann sich die Reaktionszeit auch wie in Abbildung 2-9, dargestellt ergeben.

Abbildung 2-8 Reaktionszeit mit zusammenhängender Ausführungszeit

Abbildung 2-9 Reaktionszeit mit unterbrochener Verarbeitungszeit

Die Reaktionszeit wird sehr häufig mit der Interrupt- oder der Task-Latenzzeit verwechselt, die in der Reaktionszeit als Teil einer Wartezeit letztlich enthalten ist:

Die Wartezeit setzt sich zusammen aus Blockierzeiten und Latenzzeiten, die gemäß ihrer jeweiligen Ursache benannt sind (siehe Abschnitt 2.1.3).

Blockierzeiten tB entstehen, wenn eine Task auf Daten oder ein Gerät zugreifen will, welches jedoch gerade exklusiv von einer anderen Task benutzt wird. Dann muss die Task auf die Freigabe der Daten oder des Gerätes warten. Während diese Blockierzeit ungewollt ist, kann tBauch gewollte Anteile enthalten, nämlich wenn sich die Task für eine definierte Zeit schlafen legt.

Je nach Auslastung des Systems ergibt sich eine minimale und eine maximale Reaktionszeit für die Rechenzeitanforderung i (tRmin,i und tRmax,i).

2.1.3 Beschreibungsgrößen der Systemsoftware

Die Systemsoftware ist maßgeblich für das Zeitverhalten des Realzeitsystems mitverantwortlich. Sie wird unter anderem durch die Latenzzeiten (Verzögerungszeiten) gekennzeichnet. Diese können unterschiedliche Ursachen haben. Folgende Latenzzeiten werden unterschieden:

Interrupt-Latenz

Task-Latenz

Kernel-Latenz

Preemption Delay (Verdrängungszeit)

Die Interrupt-Latenzzeit tLIsr ist die Zeit, die zwischen dem Auftreten eines Interrupts und dem Start der zugehörigen Interrupt-Service-Routine vergeht.

Unter der Task-Latenzzeit tLTask versteht man die Zeit, die zwischen dem Auftreten eines Ereignisses – das kann ebenfalls ein Interrupt sein – und dem Start der zugehörigen Task vergeht.

Betriebssysteme werden bezüglich ihres Zeitverhaltens auf einer definierten Hardware primär über die Interrupt-Latenzzeit und die Task-Latenzzeit durch die Hersteller gekennzeichnet.

Kernel-Latenz tLKernel ist die Zeit, die eine Task vor oder während ihrer Ausführung warten muss, weil systembedingt und zumeist innerhalb des Kernels andere Codesequenzen bevorzugt abgearbeitet werden. Gründe für die Kernel-Latenz stellen somit Unterbrechungssperren und die vor parallelem Zugriff geschützten Bereiche innerhalb von Systemfunktionen respektive Systemcalls dar (siehe auch Abschnitt 4.3).

Verdrängungszeiten tLPreempt, auch Preemptionzeiten genannt, entstehen, wenn ein wichtiges Ereignis eine gerade laufende Codesequenz unterbricht.

2.2 Realzeitbedingungen

Die fristgerechte Bearbeitung von Rechenzeitanforderungen ist dann garantiert, wenn die erste und die zweite Realzeitbedingung erfüllt sind: die Auslastungs- und die Rechtzeitigkeitsbedingung. Welche Auswirkungen das Nichteinhalten der Rechtzeitigkeitsbedingung hat, wird in Abschnitt 2.2.3 erläutert.

2.2.1 Gleichzeitigkeit und Auslastung

Jeder im System vorhandene Rechnerkern stellt eine Rechenleistung zur Verfügung, bei der innerhalb eines Zeitfensters eine endliche Anzahl von Befehlen abgearbeitet werden kann. Wird eine Task aktiv, beansprucht sie einen Teil der Rechenleistung.

Abhängig von der Auftrittshäufigkeit einer Rechenzeitanforderung i und der damit anfallenden Ausführungszeit tE,i ist der Rechnerkern (Prozessor) ausgelastet. Die Auslastung ρ durch eine Rechenzeitanforderung ergibt sich damit als Quotient aus notwendiger Verarbeitungszeit und Prozesszeit:

Im Worst Case ist die Auslastung durch die Rechenzeitanforderung i durch Gleichung 2-2 gegeben.

Gleichung 2-2 Auslastung im Worst Case

Ein Realzeitsystem muss in der Lage sein, die auftretenden Rechenzeitanforderungen in der Summe bearbeiten zu können (oft auch als Forderung nach Gleichzeitigkeit, Concurrency, bezeichnet). Mathematisch bedeutet dies, dass die Gesamtauslastung für jeden Rechnerkern kleiner als 100% (also 1) sein muss. Auf Mehrkernmaschinen kann jeder einzelne der c CPU-Kerne bis zu 100% belastet werden, sodass in diesem Fall die Gesamtauslastung kleiner als c mal 100% sein muss (Gleichung 2-3).

Gleichung 2-3 Gesamtauslastung

Abbildung 2-10 Auslastung

Erste Realzeitbedingung

Die Auslastung ρges eines Rechensystems muss kleiner oder gleich der Anzahl der Rechnerkerne sein.

Die Auslastungsbedingung ist eine notwendige, aber keine hinreichende Bedingung. Für eine fristgerechte Bearbeitung ist es also notwendig (Grundvoraussetzung), dass die Auslastungsbedingung erfüllt ist; ohne sie geht es nicht. Andererseits reicht die Erfüllung der Auslastungsbedingung nicht aus, um die fristgerechte Bearbeitung garantieren zu können. Hierfür muss auch die zweite Realzeitbedingung erfüllt sein.

2.2.2 Rechtzeitigkeit

Neben der Korrektheit und der Vollständigkeit der Ausgangsdaten ist die Rechtzeitigkeit beziehungsweise Pünktlichkeit (Timeliness) der Daten von maßgeblicher Bedeutung. Stehen die Daten zu früh (vor tDmin,i) oder zu spät (nach tDmax,i) zur Verfügung, sind sie wertlos. Nur wenn sie dem technischen Prozess innerhalb des von diesem vorgegebenen Zeitfensters tDmin,i und tDmax,i zur Verfügung stehen, kann das gesamte Systemverhalten als korrekt angesehen werden.

Pünktlichkeit oder Rechtzeitigkeit darf nicht mit Schnelligkeit verwechselt werden. Allerdings lassen sich Anforderungen an Pünktlichkeit mit schnellen Systemen leichter erfüllen als mit langsamen. Prinzipiell muss ein Realzeitsystem eine Aufgabe in einem vorgegebenen Zeitfenster erfüllt haben – wie es das tut, ist dabei unwesentlich.

Abbildung 2-11 Reaktionsbereich

Gleichung 2-4 Zweite Realzeitbedingung (Rechtzeitigkeitsbedingung)

tDmin,i ≤ tRmin,i ≤ tRmax,i ≤ tDmax,i

Zweite Realzeitbedingung

Um eine Rechenzeitanforderung i pünktlich (in Realzeit) zu erledigen, muss die Reaktionszeit größer oder gleich der minimal zulässigen Reaktionszeit, aber kleiner oder gleich der maximal zulässigen Reaktionszeit sein. Für alle Rechenzeitanforderungen i muss Gleichung 2-4 gelten.

Hierbei handelt es sich um eine notwendige und hinreichende Bedingung. Wenn diese Bedingung für alle Rechenzeitanforderungen i erfüllt ist, ist eine fristgerechte Bearbeitung gewährleistet.

2.2.3 Harte und weiche Realzeit

Abbildung 2-12 Harte und weiche Realzeit als Kostenfunktion

Die Forderung nach Pünktlichkeit ist nicht bei jedem System gleich stark. Während das nicht rechtzeitige Absprengen der Zusatztanks bei einer Rakete zum Verlust derselbigen führen kann, entstehen durch Verletzung der Rechtzeitigkeitsbedingung bei einem Multimedia-System allenfalls Komfortverluste. Vielfach findet man den Begriff harte Realzeit, wenn die Verletzung der Realzeitanforderungen katastrophale Folgen hat und daher nicht toleriert werden kann. Systeme, bei denen eine Deadline-Verletzung zunächst nur geringe Zusatzkosten aufwirft, bezeichnen wir als weiche Realzeitsysteme. Allerdings legt dieser Begriff nicht fest, wie stark oder wie häufig Deadline-Verletzungen toleriert werden dürfen.

Die Unterschiede bei der Forderung nach Pünktlichkeit werden oft anhand einer Kostenfunktion verdeutlicht. Bei den sogenannten weichen Realzeitsystemen bedeutet das Verletzen der Realzeitbedingung einen leichten Anstieg der Kosten. Bei den sogenannten harten Realzeitsystemen steigen jedoch die Kosten durch die Verletzung der Realzeitbedingung massiv an.

Abbildung 2-13 Nutzenfunktion

Eine andere Art der Darstellung ist die sogenannte Benefit Function (Nutzenfunktion). Hier wird der Nutzen der Reaktion des Realzeitsystems auf die Rechenzeitanforderung über der Zeit aufgetragen. Bei Systemen ohne Realzeitanforderungen ist der Nutzen unabhängig von dem Zeitpunkt der erfolgten Reaktion, also stets bei 100%. Bei einem harten Realzeitsystem ist nur dann ein Nutzen vorhanden, wenn die Reaktion innerhalb des durch tDmin und tDmax aufgestellten Zeitfensters erfolgt. Außerhalb des Zeitfensters ist der Nutzen null. Bei weichen Realzeitsystemen ist auch außerhalb des Zeitfensters ein Nutzen gegeben. Wie stark dieser Nutzen ist, hängt jedoch vom jeweiligen System ab und kann nicht allgemein definiert werden.

2.3 Systemaspekte

Um Realzeitsysteme mit vernünftigem Aufwand realisieren zu können, muss das eingesetzte Betriebssystem einige Voraussetzungen erfüllen. Erstens muss es in der Lage sein, zusammengehörige Codesequenzen (Tasks) in mehrere Abschnitte zu zerteilen und Stück für Stück abzuarbeiten (Preemptibility). Zweitens muss die Systemsoftware Mechanismen zur Verfügung stellen, mit denen die Abarbeitungsreihenfolge unterschiedlicher Codesequenzen zeitlich festgelegt werden kann. Drittens schließlich muss die Systemsoftware Mechanismen zum Umgang mit Ressourcen anbieten. Durch Parallelverarbeitung kommt es nämlich schnell zu Ressourcenkonflikten und sogenannten kritischen Abschnitten.

2.3.1 Unterbrechbarkeit

Unter Unterbrechbarkeit (Preemptibility) versteht man die Eigenschaft beziehungsweise Anforderung an eine Codesequenz, die Abarbeitung in mehrere Abschnitte aufteilen zu können. Diese Abschnitte werden dann in der korrekten Reihenfolge, aber eben mit Unterbrechungen, in denen andere Verarbeitungen stattfinden, ausgeführt. Hierzu ein Beispiel:

Bei linearer Abarbeitung der Aufgabe ohne Unterbrechbarkeit ergibt sich die in Abbildung 2-14 dargestellte Rechnerkernbelegung. Der zum Zeitpunkt 101 ms auftretende Messwert kann bereits nicht mehr erfasst werden. Die zweite Realzeitbedingung ist nicht erfüllt: Es handelt sich um kein Realzeitsystem.

Abbildung 2-14 Messwerterfassung ohne Preemption

Splittet man jedoch die Aufgabe auf in einen Teil, der die eigentliche Messwerterfassung durchführt, und einen Teil, der für die Verarbeitung zuständig ist, und ermöglicht man des Weiteren die Abarbeitung einer Aufgabe in mehreren Schritten, die unterbrochen werden können, ist eine fristgerechte Abarbeitung möglich. Dies zeigt Abbildung 2-15. Um Realzeitaufgaben mit vertretbarem Aufwand lösen zu können, wird daher die Unterbrechbarkeit von Aufgaben, die im Folgenden als Tasks bezeichnet werden sollen, gefordert.

Man spricht von vollständiger Unterbrechbarkeit, wenn eine Task zu jedem beliebigen Zeitpunkt unterbrochen werden kann und keine Abhängigkeit – zum Beispiel über Ressourcen – zu anderen Tasks besteht. Die vollständige Unterbrechbarkeit kommt in der Realität nur selten vor.

Abbildung 2-15 Messwerterfassung mit Preemption

Auch die Unterbrechbarkeit des Betriebssystemcodes entscheidet darüber, wie schnell die Reaktion auf ein Ereignis gestartet werden kann (Interrupt-Latenzzeit). Lange Interruptsperren im Betriebssystemcode verzögern das Starten der Reaktion. Die Unterbrechbarkeit des Betriebssystems selbst stellt somit ebenfalls einen wichtigen Aspekt dar.

2.3.2 Prioritäten

Zur Lösung von Realzeitaufgaben reicht die Forderung nach Unterbrechbarkeit nicht aus. Um die zeitlichen Anforderungen einhalten zu können, muss eine Systemsoftware zusätzlich die Möglichkeit bieten, die Ablaufreihenfolge der Tasks festzulegen. Hierzu gibt es verschiedene Verfahren, die in Klassifizierung der Scheduling-Verfahren (Seite 44) vorgestellt werden. Im Realzeitumfeld weit verbreitet und zugleich einfach nachzuvollziehen ist die Festlegung der Ablaufreihenfolge über die Vergabe von Prioritäten. Es gibt keine einheitliche Definition darüber, wie eine höhere Priorität repräsentiert wird. In manchen Systemen stehen niedrige Zahlen für eine hohe Priorität, in anderen dagegen verhält es sich genau umgekehrt. Im Folgenden wird grundsätzlich eine hohe Priorität über eine niedrige Zahl (1) und eine niedrige Priorität über eine hohe Zahl repräsentiert (siehe hierzu auch Abschnitt 4.3.6).

2.3.3 Ressourcenmanagement

In Realzeitsystemen werden Rechenzeitanforderungen auf Tasks abgebildet, die auf der CPU ablaufen. Aus Gründen der Effizienz (Stromverbrauch) und aus Gründen der übersichtlicheren Entwicklung werden die Tasks gleichzeitig (real oder quasi-parallel) abgearbeitet. Dabei konkurrieren sie um die Ressourcen.

Ressourcen kann man in Hardware- und Software-Ressourcen unterteilen. Der Zugriff auf Hardware-Ressourcen wie z.B. CPU, Speicher und E/A-Geräte wird vom Betriebssystem geregelt. Software-Ressourcen sind typischerweise Synchronisationsprimitive wie Locks und Semaphore.

Unter einer Kooperation ist die Festlegung einer logischen Reihenfolge zu verstehen, in der die Tasks abzuarbeiten sind. Nachfolgende Tasks müssen teilweise auf die Beendigung der vorausgegangenen Task warten. So kann z.B. die Bearbeitung einer Task auf dem Ergebnis einer vorangegangenen Task aufbauen. Diese Art der Abhängigkeit ist in Abbildung 2-16 dargestellt.

Abbildung 2-16 Task-Abhängigkeiten

Konkurrenz tritt auf, wenn Tasks versuchen, gleichzeitig auf gemeinsame Ressourcen zuzugreifen, wie zum Beispiel auf einen gemeinsamen Speicher (Shared Memory). Typischerweise dürfen diese Zugriffe jedoch nicht parallel erfolgen, da es sonst insbesondere bei Schreibzugriffen zu Dateninkonsistenzen kommen kann.

Beispiel 2-3 Inkonsistenz durch parallele Zugriffe

Die fehlerhafte Implementierung einer echo()-Funktion liest ein Zeichen von der Standardeingabe und gibt dieses auf die Standardausgabe aus: char ch;

void echo(){   ch = getchar(); // Zeichen einlesen   putchar(ch);    // Zeichen ausgeben}

Angenommen: Zwei Tasks (genauer: Threads) verwenden diese Funktion und im Eingabepuffer befinden sich die Zeichen »AB«. Arbeitet die CPU die erste Zeile Code (getchar()) im Kontext der ersten Task ab, steht in der globalen Variablen ch der Wert »A«. Wird jetzt die erste Zeile im Kontext der zweiten Task abgearbeitet, überschreibt dies den Wert »A« mit dem »B«. Schließlich handelt es sich bei ch um eine globale Variable. Folglich wird später auf dem Bildschirm das falsche Ergebnis »BB« erscheinen.

Die Codesequenzen, die den Zugriff auf gemeinsame Ressourcen implementieren, werden kritische Abschnitte genannt. Damit es durch die kritischen Abschnitte nicht zu Inkonsistenzen kommt, muss der Programmierer Schutzmechanismen einsetzen. Solche Schutzmechanismen sind beispielsweise Semaphore, Mutexe, Spinlocks oder auch Monitore, wie sie in Abschnitt 4.3