Echtzeit: Grundlagen von Echtzeitsystemen

Autor / Redakteur: Prof. Dr. Christian Siemers * / Sebastian Gerstl

Unter Echtzeit versteht man die Anforderung an ein Rechensystem, innerhalb einer kürzesten definierten Zeitspanne korrekt zu reagieren. Weitere wichtige Konzepte sind "harte" und "weiche" Echtzeit sowie Ereignissteuerung und Zeitsteuerung.

Firmen zum Thema

Schnellste Reaktivität in kürzester definierter Zeitspanne: Bei Echtzeitsystemen kommt es auf schlanke. hochpräzise Abläufe an. Dabei wird unter anderem zwischen "harter" und "weicher" Echtzeit unterschieden.
Schnellste Reaktivität in kürzester definierter Zeitspanne: Bei Echtzeitsystemen kommt es auf schlanke. hochpräzise Abläufe an. Dabei wird unter anderem zwischen "harter" und "weicher" Echtzeit unterschieden.
(Bild: gemeinfrei / CC0 )

Echtzeitsysteme sind Systeme, die korrekte Reaktionen innerhalb einer möglichst kleinen definierten Zeitspanne produzieren müssen. Falls die Reaktionen das Zeitlimit überschreiten, führt dies zu Leistungseinbußen, Fehlfunktionen und/oder sogar Gefährdungen für Menschen und Material.

Die DIN 44300 des Deutschen Instituts für Normung beschreibt den Begriff Echtzeit wie folgt:

Unter Echtzeit (real time) versteht man den Betrieb eines Rechensystems, bei dem Programme zur Verarbeitung anfallender Daten ständig betriebsbereit sind, derart, dass die Verarbeitungsergebnisse innerhalb einer vorgegebenen Zeitspanne verfügbar sind. Die Daten können je nach Anwendungsfall nach einer zeitlich zufälligen Verteilung oder zu vorherbestimmten Zeitpunkten anfallen.

Demgegenüber wird im Oxford Dictionary of Computing das Echtzeitsystem wie folgt beschrieben:

Ein Echtzeitsystem (real-time system) ist ein System, bei dem der Zeitpunkt, zu dem Ausgaben vorliegen, bedeutend ist. Das liegt für gewöhnlich daran, dass die Eingabe mit einigen Änderungen der physikalischen Welt korrespondiert und die Ausgabe sich auf diese Änderungen beziehen muss. Die Verzögerung zwischen der Zeit der Eingabe und der Zeit der Ausgabe muss ausreichend klein für eine akzeptable ”Rechtzeitigkeit“ (timeliness) sein.

Je nach Anforderungen wird in der Praxis zwischen "harten" und "weichen" Echtzeitsystemen unterschieden. Diese Unterscheidung wird ausschließlich über die Art der Folgen einer Verletzung der Zeitschranken getroffen.

Ein Echtzeitsystem wird als hartes Echtzeitsystem (hard real-time system) bezeichnet, wenn das Überschreiten der Zeitlimits bei der Reaktion erhebliche Folgen haben kann. Zu diesen Folgen zählen die Gefährdung von Menschen, die Beschädigung von Maschinen, also Auswirkungen auf Gesundheit und Unversehrtheit der Umgebung. Typische Beispiele hierfür sind einige Steuerungssysteme im Flugzeug oder im Auto, z.B. bei der Verbrennungsmaschine.

Eine Verletzung der Ausführungszeiten in einem weichen Echtzeitsystem (soft real-time system) führt ausschließlich zu einer Verminderung der Qualität, nicht jedoch zu einer Beschädigung oder Gefährdung. Beispiele hierfür sind Multimediasysteme, bei denen das gelegentlich Abweichen von einer Abspielrate von 25 Bildern/sek. zu einem Ruckeln o.ä. führt.

Als Anmerkung sei hier beigefügt, dass fast immer nur die oberen Zeitschranken aufgeführt werden. Dies hat seine Ursache darin, dass die Einhaltung einer oberen Zeitschranke im Zweifelsfall einen erheblichen Konstruktionsaufwand erfordert, während eine untere Schranke, d.h. eine Mindestzeit, vor der nicht reagiert werden darf, konstruktiv unbedenklich ist.

Ein Beispiel für ein System, bei dem beide Werte wichtig sind, ist die Steuerung des Zündzeitpunkts bei der Verbrennungsmaschine: Dieser darf nur in einem eng begrenzten Zündintervall kommen.

Ereignissteuerung oder Zeitsteuerung?

Es stellt sich nun unmittelbar die Frage, wie die harten Echtzeitsysteme denn konzipiert sein können. Hier kann konkret zwischen zwei verschiedenen Konzeptionen unterschieden werden, die in der Praxis natürlich auch gemischt auftreten: Ereignisgesteuerte (event triggered) und zeitgesteuerte (time triggered) Systeme.

Ereignisgesteuerte Systeme werden durch Unterbrechungen gesteuert: Liegt an einem Sensor ein Ereignis (was das ist, muss natürlich definiert sein) vor, dann kann er eine Unterbrechungsanforderung (interrupt request) an den Prozessor senden und damit auf seinen Bedienungswunsch aufmerksam machen.

Eine asynchrone Unterbrechung (Asynchronous Interrupt Request, IRQ) ist ein durch das Prozessor-externe Umfeld generiertes Signal, das einen Zustand anzeigt und/oder eine Behandlung durch den Prozessor anfordert. Dieses Signal ist nicht mit dem Programmlauf synchronisiert. Die Behandlung der Unterbrechung erfolgt im Rahmen der Interrupt Service Routine.

Bei zeitgesteuerten Systemen erfolgt keine Reaktion auf Eingabeereignisse, die Unterbrechungen werden lediglich durch einen, ggf. mehrere periodische Zeitgeber (Timer) ausgelöst. Sensoren werden dann vom Steuergerät aktiv abgefragt. Dieses Verfahren hat den großen Vorteil, dass das Verhalten sämtlicher Systemaktivitäten zur Compilezeit vollständig planbar. Dies ist gerade für den Einsatz in Echtzeitsystemen ein erheblicher Vorteil, da á priori überprüft werden kann, ob Echtzeitanforderungen eingehalten werden.

Der Vorgänger des zeitgesteuerten Designs wurde Polling genannt. Hierunter wird das ständige (quasi-zyklische), im Programm verankerte Abfragen von Prozess-zuständen oder Werten verstanden, während das zeitgesteuerte Verfahren nicht ständig (also durch den Programmlauf bestimmte), sondern zu festgelegten Zeiten abfragt. Man beachte hierbei die Unterscheidung zwischen realer Zeit und Programmlaufzeit.

Das Design dieser Zeitsteuerung muss allerdings sehr präzise durchgeführt werden, um die Ereignisse zeitlich korrekt aufzunehmen und zu verarbeiten. Ggf. müssen auch Zwischenpufferungen (z.B. bei einer schnellen Datenfolge) eingefügt werden. Um den zeitlichen Ablauf und seine Bedingungen quantifizieren zu können, seien folgende Zeiten definiert:

Die Latenzzeit (Latency Time) ist diejenige vom Auftreten eines Ereignisses bis zum Start der Behandlungsroutine. Diese Zeit kann auf den Einzelfall bezogen werden, sie kann auch als allgemeine Angabe (Minimum, Maximum, Durchschnittswert mit Streuung) gewählt werden.

Die Ausführungszeit (Service Time) ist die Zeit zur reinen Berechnung einer Reaktion auf ein externes Ereignis. In einem deterministischen System kann diese Zeit bei gegebener Rechengeschwindigkeit prinzipiell vorherbestimmt werden.

Die Reaktionszeit (Reaction Time) ist diejenige Zeit, die vom Anlegen eines Satzes von Eingangsgrößen an ein System bis zum Erscheinen eines entsprechenden Satzes von Ausgangsgrößen benötigt wird. Die Reaktionszeit setzt sich aus der Summe der Latenzzeit und der Ausführungszeit zusammen, falls die Service Routine nicht selbst noch unterbrochen wird.

Die Frist (Dead Line) kennzeichnet den Zeitpunkt, zu dem die entsprechende Reaktion am Prozess spätestens zur Wirkung kommen muss. Diese Fristen stellen eine der wesentlichen Randbedingungen des Umgebungsprozesses dar.

Dies bedeutet also, dass zu jedem zu den Echtzeitkriterien zählenden Ereignis eine Frist definiert sein muss, innerhalb derer die Reaktion vorliegen muss. Folglich ist nicht die Schnelligkeit entscheidend, es ist Determinismus im Zeitsinn gefragt.

Bemerkungen zu weichen und harten Echtzeitsystemen

Bild 1: Darstellung verschiedener Applikationsklassen.
Bild 1: Darstellung verschiedener Applikationsklassen.
(Bild: Siemers)

Die Konzeption eines harten Echtzeitsystems und vor allem der Nachweis dieser Fähigkeit ist außerordentlich schwierig, insbesondere, wenn man bedenkt, dass die Unterschiede im Laufzeitbedarf für einzelne Aufgaben sehr hoch sein können (für Fußball-spielende Roboter wird von 1:1000 berichtet). Es muss also auf den Maximalfall ausrichtet werden, wenn das System wirklich in jedem Fall in festgelegten Zeiten reagieren soll.

Man muss allerdings auch sagen, dass dieses Echtzeitkriterium aufweichbar ist (was auch z.B. von Anbietern der Echtzeit-Betriebssysteme gemacht wird):

Kann die vollständige, harte Reaktion nicht eingehalten werden, so bietet sich die Wege A und B in Bild 1 an. Weg A gilt dabei für Systeme bzw. Ereignisse, bei denen aus einer verspäteten Reaktion Schädigungen bis zur Zerstörung resultieren können. Hier wird nicht mit dem vollständig berechneten Ergebnis gehandelt, sondern mit einem ungefähren Wert, also eine Art rechtzeitige Notreaktion.

Weg B ist der gewöhnliche Ausweg. Hier werden Systeme vorausgesetzt, bei denen eine zeitliche Überschreitung zu einer Güteverminderung (Soft Degradation), nicht jedoch zu einer Schädigung führt. Wie bereits erwähnt bezeichnet man dies dann als Soft Real-Time. Dies wird gerne für Betriebssysteme genutzt.

Nebenläufigkeit

Nebenläufigkeit bildet das Grundmodell für Multiprocessing und Multithreading. Zwei Prozesse bzw. Threads sind dann nebenläufig, wenn sie unabhängig voneinander arbeiten können und es keine Rolle spielt, welcher der beiden Prozes-se/ Threads zuerst ausgeführt oder beendet wird. Indirekt können diese Prozesse dennoch voneinander abhängig sein, da sie möglicherweise gemeinsame Ressour-cen beanspruchen und untereinander Nachrichten austauschen.

Hieraus kann eine Synchronisation an bestimmten Knotenpunkten im Programm resultieren. Hier liegt eine Fehlerquelle, denn es kann hier zu schwerwiegenden Fehlern, Verklemmungen (deadlocks) und damit zu einem Programmabsturz kommen.

Die Hauptargumente, warum es trotz der Probleme (sprich: neue Fehlermöglichkeiten für Softwareentwickler) sinnvoll ist, Programme nebenläufig zu entwickeln, sind:

Die Modellierung vieler Probleme wird dadurch vereinfacht, indem sie als mehr oder weniger unabhängige Aktivitäten verstanden werden und entsprechend durch Sprachkonstrukte umgesetzt werden können. Jede Aktivität kann dann isoliert betrachtet werden, nur die Kommunikation und Synchronisation ist zu beachten. Nebenläufigkeit führt hier zu einer abstrakteren Modellierung, und ob die entstandene Nebenläufigkeit dann wirklich zu einer gleichzeitigen Bearbeitung führt, ist nebensächlich.

Die Anzahl der ausführenden Einheiten in einem Rechner kann durchaus > 1 sein. Im Zeitalter von Hardware/Software Co-Design, Multi- und Manyprozessorcores, konfigurierbaren Prozessoren, Prozessoren mit eigenem Peripherieprozessor usw. können Aufgaben auf verschiedene Teile abgebildet werden, und dazu müssen sie auch dergestalt modelliert sein. Hier wird die Performance des Systems entscheidend verbessert, wenn die parallelen Möglichkeiten auch wirklich ausgenutzt werden.

Multiprocessing und Multithreading

Mit Multitasking wird allgemein die Fähigkeit von Software (beispielsweise Betriebssystemen) bezeichnet, mehrere Aufgaben scheinbar gleichzeitig zu erfüllen. Dabei werden die verschiedenen Tasks in so kurzen Abständen immer abwechselnd aktiviert, dass für den Beobachter der Eindruck der Gleichzeitigkeit entsteht. Man spricht hier auch oft von Quasi-Parallelität, aber mikroskopisch wird natürlich nichts wirklich parallel zueinander bearbeitet.

Doch was ist eine Task? Dies wird üblicherweise als allgemeiner Überbegriff für Prozesse und Threads (= Leichtgewichtsprozesse) genannt. Nun sind auch diese beiden schwer zu unterscheiden (zumindest präzise zu unterscheiden), aber meist reicht auch schon eine etwas unscharfe Definition.

Ein Prozess (process) ist ein komplettes, gerade ablaufendes Programm. Zu diesem Prozess gehören der gesamte Code und die statischen und dynamisch angelegten Datenbereiche einschließlich Stack, Heap und Register. Der Code wiederum kann mehrere Teile enthalten, die unabhängig voneinander arbeiten können. Solche Teile werden Threads (Aktivitätsfäden) genannt.

Ein Thread ist ein Aktivitätsträger eines Prozesses mit minimalem eigenem Kontext. Mit Aktivitätsträger wird ein in sich geschlossener Bearbeitungsstrang bezeichnet. Der minimale Kontext betrifft diejenigen Daten bzw. Speichereinheiten (Register), die ausschließlich dem Thread zur Verfügung stehen.

Welche Formen des Multiprocessing oder Multithreading gibt es denn? Das am häufigsten angewandte Konzept ist das präemptive Multiprocessing. Hier wird von einem Betriebssystem(kern) der aktive Prozess nach einer Weile verdrängt, zu Gunsten der anderen. Diese Umschaltung wird Scheduling genannt.

Die andere Form ist das kooperative Multiprocessing, das von jedem Prozess erwartet, dass dieser die Kontrolle an den Kern von sich aus zurückgibt. Letztere Version birgt die Gefahr in sich, dass bei nicht-kooperativen Prozessen bzw. Fehlern das gesamte System blockiert wird. Andererseits ist das kooperative Multiprocessing sehr einfach zu implementieren, auch innerhalb einer Applikation.

Beim Multithreading ist es ähnlich, wobei allerdings die Instanz, die über das Scheduling der Threads entscheidet, auch im Programm liegen kann (Beispiel: Java-Umgebung). Das Umschalten zwischen Threads eines Prozesses ist dabei wesentlich weniger aufwändig, verglichen mit Prozessumschaltung, weil im gleichen Adressraum verweilt wird. Allerdings sind auch die Daten des gesamten Prozesses durch alle Threads manipulierbar.

Prozesssynchronisation und –kommunikation

Die Prozesssynchronisation dient dem Ablauf der nebenläufigen Programmteile und ermöglicht eine Form der Wechselwirkung zwischen diesen. Das Warten eines Prozesses auf ein Ereignis, das ein anderer auslöst, ist die einfachste Form dieser Prozesssynchronisation (gleiches gilt auch für Threads).

Die Prozesskommunikation erweitert die Prozesssynchronisation und stellt somit dessen Verallgemeinerung dar. Hier muss es neben den Ereignissen auch Möglichkeiten geben, die Daten zu übertragen. Die praktische Implementierung ist dann z.B. durch ein Semaphoren/Mailbox-System gegeben: Über Semaphoren wird kommuniziert, ob eine Nachricht vorliegt, in der Mailbox selbst liegt dann die Nachricht. Für ein Multithreadingsystem kann dies direkt ohne Nutzung eines Betriebssystems implementiert werden, da alle Threads auf den gesamten Adressraum zugreifen können. Dies gilt nicht für Multiprocessingsysteme, hier muss ein Betriebssystem zur Implementierung der Mailbox und der Semaphoren verwendet werden.

Bei dieser Kommunikation wie auch der einfachen Synchronisation kann es zu Verklemmungen kommen. Eine Menge von Threads (Prozessen) heißt verklemmt, wenn jeder Thread (Prozess) dieser Menge auf ein Ereignis im Zustand „blockiert“ wartet, das nur durch einen anderen Thread (Prozess) dieser Menge ausgelöst werden kann. Dies ist im einfachsten Fall mit zwei Threads (Prozessen) möglich: Jeder Thread wartet blockierend auf ein Ereignis des anderen.

Im Fall der Prozess- oder Threadkommunikation kann dies gelöst werden, indem nicht-blockierend kommuniziert wird: Die Threads (Prozesse) senden einander Meldungen und Daten zu, warten aber nicht darauf, dass der andere sie auch abholt. Dies ist auch notwendig für die Echtzeitfähigkeit. Allerdings sollte nicht übersehen werden, dass hierdurch Daten auch verloren gehen können.

Grundlegende Modelle für die Nebenläufigkeit

Bezüglich der Zeit für das Aufbauen der Kommunikation zwischen zwei Prozessen (Threads) gibt es drei Grundannahmen: Asynchron, perfekt synchron (mit Null-Zeit) und synchron (mit konstanter Zeit). Asynchrone Kommunikation bedeutet in diesem Fall, dass die Kommunikationspartner sozusagen zufällig in Kontakt treten (wie Moleküle in einem Gas) und dann wechselwirken. Dieses Modell, als chemisches Modell bezeichnet, ist daher nichtdeterministisch und für eingebettete Systeme unbrauchbar.

(Anmerkung: Spricht man im Zusammenhang von Network-on-Chip (NoC) von asynchroner Kommunikation, so ist damit selbst-synchronisierende Kommunikation gemeint. Für RS232, auch eine „asynchrone“ Schnittstelle, bedeutet asynchron, dass der Beginn einer Aussendung für den Empfänger spontan erfolgt. Auf höherer Ebene ist diese Kommunikation natürlich nicht zufällig, sondern geplant.)

Das perfekt synchrone Modell geht davon aus, dass Kommunikation keine Zeit kostet, sondern ständig erfolgt. Dies lehnt sich an die Planetenbewegung an, wo die Gravitation untereinander und mit der Sonne zu den Bahnen führt, und wird deshalb auch Newtonsches Modell genannt. Die so genannten synchronen Sprachen basieren auf diesem Modell.

Das dritte Modell, das synchron, aber mit konstanter Zeitverzögerung kommuniziert, wird auch Vibrationsmodell genannt. Dieser Name entstammt der Analogie zur Kristallgitterschwingung, bei der eine Anregung sich über den Austausch von Phononen fortpflanzt.

Wozu dienen diese Kommunikationsmodelle? Der Hintergrund hierzu besteht darin, Kommunikation und Betrieb in nebenläufigen, ggf. auch verteilten Systemen modellieren zu können. Die Annahme einer perfekt synchronen Kommunikation beinhaltet eigentlich nicht, dass „Null-Zeit“ benötigt wird, vielmehr ist die Übertragungszeit einer Nachricht kleiner als die Zeitspanne zur Bestimmung eines neuen Zustands im Empfänger. Dies bedeutet, dass sich das gesamte System auf diese Meldungen synchronisieren kann und die Kommunikation keinen Beitrag zu Wartezeiten leistet.

Hinweis: Dieser Beitrag ist ein Auszug aus dem Handbuch „Embedded Systems Engineering“. Es ist auch als kostenlose PDF-Version verfügbar.

* Prof. Dr. Christian Siemers lehrt an der Technische Universität Clausthal und arbeitet dort am Institut für Elektrische Informationstechnik (IEI).

(ID:45034849)