Multitasking ist durch den ATRI ST und den AMIGA als Schlagwort in aller Munde. Die Diskussion, was Multitasking eigentlich sei, dauert jedoch nach wie vor an: Wieviele parallelablaufende Programme oder welche anderen Merkmale kennzeichnen ein Multitasking-fähiges Betriebssystem? Der zweite Teil der Überschrift möchte ein wenig provozieren: Denn daß Multitasking unter TOS einerseits und unter RTOS andererseits mehr als nur ein Buchstabe unterscheidet, soll dieser Beitrag zeigen.
PEARL (’Process and Experiment Automation Real time Language’) ist eine Programmiersprache, die zu Beginn der 70er Jahre in Deutschland, unterstützt durch die Bundesregierung, entwickelt wurde. In ihr sollten sich die Eigenschaften gängiger Hochsprachen mit Echtzeitfähigkeit und Multitasking paaren. Zunächst gab es nur für große Rechenanlagen Compiler; seit Anfang der 80er Jahre entstehen auch für Mikrocomputer PEARL-Compiler. Ein „Geburtsort“ für Compiler ist das Institut für Regelungstechnik an der Universität Hannover. PEARL ist mit den angedeuteten Eigenschaften für Regelungsaufgaben und Prozeßautomatisierung geradezu prädestiniert. Natürlich muß auch die Betriebssystemumgebung für PEARL-Programme Echtzeit- und Multitasking-fähig sein. Deshalb wurde parallel RTOS/UH (’Real Time Operating System / Universität Hannover’) entwickelt, da die verfügbaren Betriebssysteme den Anforderungen nicht genügten.
Seit etwa 1984 werden RTOS/UH und der PEARL-Compiler auch außerhalb der Universität eingesetzt. In der Industrie laufen RTOS-Versionen für verschiedenste VME-Bus- und andere Rechner, die auf dem 68000 basieren. Aber nicht nur in der industriellen Anwendung zeigt das Gespann seine Stärken. Davon konnten sich zuerst die Anwender des c’t 68000-Computers, seit Mitte 1986 aber auch die des ATARI ST überzeugen. So erübrigen sich zum Beispiel Druckerspooler und Ramdisk aufgrund des Konzeptes von RTOS.
Diese Bemerkungen zur Geschichte mögen Verständnis dafür wecken, daß RTOS in 'mausigen’ Zeiten seine Befehle immer noch von der Tastatur erwartet. Wie die Maus unter RTOS trotzdem eingesetzt werden kann, habe ich im Rahmen einer Serie der Zeitschrift c’t (siehe Literaturangaben) beschrieben. Für detailliertere Informationen verweise ich deshalb auf diese Serie. Ich beziehe mich hier auf den Update der ATARI-Version von RTOS, der gerade herausgekommen ist. Deshalb mag dem einen oder anderen Besitzer älterer RTOS-Versionen einiges neu Vorkommen. Dies sind jedoch nur Feinheiten: Das Grundkonzept ist für alle RTOS-Versionen gleich.
Für RTOS ist der Benutzer, der eine Taste drückt, ein Ereignis wie ein durch eine Lichtschranke ausgelöster Interrupt, ein abgelaufener Timer oder die Meldung, die die Tastatur des ATARI bei einer Mausbewegung sendet. Einzige Bedingung für ein Ereignis unter RTOS ist, daß es fähig sein muß, sich mit einem Interrupt bemerkbar zu machen. Alle Aktivitäten von RTOS kann man also als Reaktion auf Interrupte auffassen. Manche Interrupte werden dabei generell vom Betriebssystem abgefangen und von Systemtasks bedient, etwa die der Tastatur, der seriellen und parallelen Schnittstelle oder des Floppy-/DMA-Controllers; andere stehen dem Programmierer frei zur Verfügung. Beispiele hierfür sind der Bildsynchronisationsinterrupt und der Mausinterrupt.
MDDULE-SUMMARY:
TASKS:
(INT)Start (INT)Ende (INT)Rest (INT)Rechnen
VAR(RAM):0000-003F CODE(NO ROM):0040-0378
$0378 BYTES 0 ERRORS,
Bild 1
Solange zwischen zwei Ereignissen immer genügend Zeit für die Reaktion bleibt, gibt es keine Probleme. Sobald dies nicht mehr der Fall ist, muß ein Ereignis auf die Bearbeitung warten. Auch RTOS kann den Prozessor nicht zerteilen, sondern lediglich die Rechenkapazität des Prozessors an verschiedene Aufgaben hintereinander vergeben. Der Unterschied zu anderen Betriebssystemen liegt darin, für wieviele verschiedene Aufgaben die Rechnerkapazität verwaltet werden kann, wie schnell der Prozessor einer neuen Aufgabe zugeteilt wird und wieviel Rechenkapazität diese Verwaltung selber benötigt. So verwaltet RTOS so-viele Tasks, wie im Speicher Platz finden (das können durchaus mehr als 100 sein!), braucht als Reaktionszeit auf Prozeßinterrupte unter PEARL keine 200 Mikrosekunden und schafft einen Taskwechselzyklus A-B-A in weniger als 400 Mikrosekunden (8 Mhz CPU, no waitstates, zum Beispiel ATARI ST).
Es bleibt zunächst die Frage, nach welchem Kriterium die Prozessorkapazität zugeteilt wird, wenn mehrere Aufgaben gleichzeitig anstehen. Dazu hat jede Task eine Priorität, die bei der Programmierung festgelegt wird, beim Aufruf aber noch geändert werden kann. Generell kann man sagen, daß immer diejenige Task den Prozessor bekommt, die unter den lauffähigen die höchste Priorität hat. Dabei bedeutet Lauffähigkeit, daß eine Task aktiviert wurde und keiner der Wartegründe vorliegt. Ein anschauliches Beispiel für einen Wartegrund liefert die Betreuungstask der seriellen Schnittstelle. Wenn ein Zeichen abgeschickt oder empfangen wurde, dauert es bei 9600 Baud etwa 1 Millisekunde, bis das nächste Zeichen an der Reihe ist. 1 Millisekunde ist aber für einen schnellen Prozessor wie den 68000 sehr viel Zeit. Deshalb pausiert diese Task nach jedem Zeichen und gibt den Prozessor für andere Tasks frei. Erst der nächste ’Receive Data Register Full’- oder ’Transmit Data Register Empty’-Interrupt aktiviert diese Task wieder. Im Gegensatz hierzu beschäftigen viele andere Betriebssysteme in dieser Situation den Prozessor vollständig damit, in einer Statusabfrageschleife zu kreisen, bis das nächste Zeichen gesendet oder empfangen werden kann.
Wenn auch die theoretische Betrachtung interessant sein mag, so möchte ich jetzt doch ein praktisches Programmbeispiel (Bild l) bringen, das die gegenseitige Steuerung von Tasks in PEARL demonstriert. Da RTOS als Unterlage für PEARL-Programme entwickelt wurde, sind die Befehle für Aktivierungen und Einplanungen auch auf Kommandoebene zu benutzen. Aber auch sonst lassen sich aus diesem PEARL-Beispiel viele Rückschlüsse auf die Leistungsfähigkeit von RTOS ziehen.
Von der Kommandoebene aus wird die Task 'Start’ aktiviert. Sie teilt in Zeile 48 dem Betriebssystem mit, es möge doch bitte alle 50 Millisekunden die Task 'Rechnen’ aktivieren. Anschließend startet sie in Zeile 49 die Task ’Rest’. Diese beiden Tasks sind jetzt zwar lauffähig, belegen aber den Prozessor noch nicht, weil 'Start’ eine höhere Priorität hat. Erst wenn 'Start’ in Zeile 50 für zwei Sekunden pausiert, bekommt zuerst 'Rechnen’ und dann ’Rest’ den Prozessor. Sind die zwei Sekunden vergangen, wird 'Start’ vom Betriebssystem wieder „geweckt“ und teilt als letzte Aktion in Zeile 51 dem Betriebssystem noch mit, daß drei Sekunden nach diesem Befehl die Task 'Ende’ zu aktivieren ist. Danach hat 'Start’ seine Schuldigkeit getan.
Die Aufgabe von 'Start’ besteht also in der Hauptsache darin, die anderen drei Tasks termingerecht zu aktivieren und einzuplanen. Aber nicht nur in Abhängigkeit von der Zeit können Aktivierungen und Einplanungen geschehen. Ebenso einfach kann dem Betriebssystem aufgetragen werden, eine Task als Reaktion auf einen Interrupt zu aktivieren. Meine oben erwähnte ’Maus-Task’ wird jeweils durch den Mausinterrupt aktiviert, liest die Meldung über die Mausbewegung ein und bewegt entsprechend den Pfeil auf dem Bildschirm. Dabei sind keinerlei Hilfsroutinen in Assembler oder Eingriffe in das Betriebssystem notwendig, alles läßt sich ohne Kunstgriffe in PEARL programmieren.
Doch kommen wir zurück zu dem Moment, in dem 'Start’ pausiert legt und den Prozessor freigibt (Zeile 50). 'Rechnen’ und ’Rest’ sind nun beide lauffähig. Da 'Rechnen’ aber die höhere Priorität hat, wird ihr der Prozessor zugeteilt. Erst wenn 'Rechnen’ fertig sit, bekommt auch ’Rest’ den Prozessor. ’Rest’ kann sich aber nicht lange des Prozessors erfreuen, denn nach 50 Millisekunden aktiviert RTOS wie befohlen wieder 'Rechnen' und entzieht ihr prioritätengerecht den Prozessor. Dieses Spiel wiederholt sich, bis 'Ende' den Kreislauf in den Zeilen 39 und 40 unterbricht. Ebenso einfach, wie in PEARL Tasks zu aktivieren und einzuplanen sind, können sie auch terminiert und ausgeplant werden.
In der Task 'Rest' zeigt sich ein weiterer grundlegender Unterschied zu anderen Betriebssystemen und Programmiersprachen. Eine Endlosschleife, sonst der Schrecken aller Programmierer, wird hier als probates Mittel der Programmierung eingesetzt. ’Rest’ hat die niedrigste Priorität und bekommt somit den Prozessor nur dann, wenn keine andere Aufgabe mehr ansteht. Die Anzahl der Schleifendurchläufe in ’Rest’ ist somit ein indirektes Maß für die freie Rechenkapazität des Prozessors. Die Zahl von über 220000 Schleifendurchläufen innerhalb der 5 Sekunden, die 'Rest1 läuft, zeigt eindrucksvoll, wie wenig Zeit RTOS für 100-mal 'Rechnen’ und die damit verbunden 200 Taskwechsel braucht.
»UH-PEARL-10.2 <c>1987 W.GERTH, HANNOVER
= 1 /*************************************************************/
= 2 /* */
= 3 /* Beispiel fuer gegenseitige Steuerung von Tasks in PEARL */
= 4 /* last update: 05.02.87 22hl0 */
= 5 /* */
= 6 /*************************************************************/
= 7
= 8 MODULE E:-:ample; /* Beginn der umfassenden Blockstruktur */
= 9
= 10 SYSTEM; /* Beschreibung der Betriebssystem-Umgebung--------------*/
= 11 Terminal: Al: /* Al: Datenstation der Terminalemulation */
= 12
= 13 PROBLEM: /* Beginn des Betriebssystem-unabhaengigen Teiles ----*/
= 14 /* SPeCify: Beschreibung der Eigenschaften einer Datenstation */
= 15 SPC Terminal DATION INOUT ALPHIC CONTROL(ALL);
= 16
= 17 /* DeCLare: Vereinbarung von Variablen -------------------*/
= 18 DCL X FLOAT; /* Rechenvariable */
= 19 DCL Leerlauf FIXED(31); /"* Zaehlvariable fuer Restzeit %/
= 20
= 21
= 22
= 23 Rechnen: TASK PRIQ 39: /*----------------------*/
= 24 DCL Y FLOAT; /* Diese Task gibt den Wert, den */
= 25 Y = 1 / X; /* Kehrwert sowie den Sinus von X */
= 26 PUT X, Y, SIN(X) TO Terminal BY F(5),(2)F(10.4),SKIP; /* */
= 27 X = X + 1.0: /* auf dem Bildschirm aus */
= 28 END; /* of task Rechnen ------------*/
= 29
= 30
= 31 Rest: TASK PRIO 40; /*---------------------------*/
= 32 REPEAT /* Beginn einer Endlosschleife */
= 33 ■ Leerlauf = Leerlauf + 1; /* incrementiere Leerlaufindex */
= 34 END; /* Ende der Endlosschleife */
= 35 END; /* of task Rest -----*/
= 36
= 37
= 38 Ende: TASK PPIO 39; /*------------------------*/
= 39 PREVENT Rechnen: /* nimm Rechnen aus zyklischer Einplanung*/
= 40 TERMINATE Rest: /* erloese Rest aus Endlosschleife */
= 41 PUT 'Leerlaufindex: '.Leerlauf TO Terminal BY SKIP, A, F(8). SKIP;
= 42 END; /* of task Ende------------------*/
= 43
= 44
= 45 Start: TASK PRIO 38; /*-----------------------*/
= 46 X = 1.0; /* initialisiere Rechenvariable */
= 47 Leerlauf = 0; /* initialisiere Leerlauf indes: */
= 48 ALL 0.05 SEC ACTIVATE Rechnen; /* plane Rechnen ein */
= 49 ACTIVATE Rest; /* starte Task Rest */
= 50 AFTER 2 SEC RESUME: /* warte 2 Sekunden */
= 51 AFTER 3 SEC ACTIVATE Ende; /* noch 3 Sekunden bis Ende */
= 52 END; /* of task Start ---------------------------------*/
= 53
= 54
= 55 MODEND: * of module E-ample *
Bei diesen Überlegungen ist die Zeit noch unberücksichtigt, die die Terminalemulation des ATARI benötigt. Auch unter RTOS muß jedes Zeichen als Pixelmuster auf den Bildschirm geschrieben werden. Unterdrückt man diese Arbeit, indem man die Ausgabe über die serielle Schnittstelle an ein Terminal oder einen anderen Rechner umleitet, so wächst die Anzahl der Schleifendurchläufe in 'Rest' auf über 520 000, also mehr als 100 000 pro Sekunde an!
Nicht nur Multitasking sondern auch Multi-User
Nicht ganz ohne Absicht habe ich ein Terminal an der seriellen Schnittstelle erwähnt: Unter RTOS kann man den Spaß an einem ATARI auf bis zu drei Nutzer verteilen. Sowohl an die normale serielle Schnittstelle als auch an die MEDI-Schnittstelle kann ein Terminal angeschlossen werden, über das man auf dem ATARI arbeiten kann. Bedingung für das Terminal oder die Terminalemulation auf einem anderen Computer ist, daß es VT 52- oder Televideo-kompatibel sein muß. Natürlich stehen dem zweiten und dritten Nutzer nicht die Graphikfähigkeiten der Terminalemulation des ersten Nutzers (siehe unten) zur Verfügung. Trotzdem eröffnen sich ungeahnte Möglichkeiten. So kann man den Freund, der über ein Terminal oder einen Computer mit Terminalemulation verfügt, mittels Akustikkoppler oder Modem ebenso ohne Probleme als zweiten Nutzer anhän-gen, wie sich selbst, wenn man etwa noch den alten 8-Bitter, der nicht mehr genug leistete, stehen hat und ihn als Terminal 'mißbrauchen' kann. Dann ergibt sich die interessante Möglichkeit, als Nutzer 1 ein Programm zu testen, während man gleichzeitig als Nutzer 2 eventuell gefundene Fehler sofort im Programmtext korrigiert, ohne den Testlauf unterbrechen zu müssen.
Im Gegensatz zu UNIX oder ähnlichen Mehrnutzer-Betriebssystemen schottet RTOS die einzelnen Nutzer nicht gegeneinander ab. So kann durchaus Nutzer 1 die Editortask, mit der
Nutzer 2 gerade an einem Programm schreibt, terminieren, worauf dieser ’abgehängt’ ist. Ein wesentlich ernsthafteres als dieses eher zwischenmenschliche Problem kann sich aber aus dem gleichzeitigen Zugriff auf eine Datei ergeben. Deshalb kann es sinnvoll sein, wenn man mit mehreren Nutzern auf einem Rechner arbeitet, in Rufweite zu bleiben und im Zweifelsfalle kurz zu fragen, ob einer der anderen Nutzer auch gerade an der be-
nötigten Datei arbeitet. Mn kann aber auch über den Rechner die Frage an die anderen Terminals schicken und mittels Tastatur und Bildschirm miteinander kommunizieren.
Wie schon angedeutet, unterstützt die RTOS-Version für den ATARI sowohl die Farbgraphik mit 640 x 200 Pixel als auch den monochromen Bildschirm mit 640 x 400 Pixel. Für den Programmierer stehen Funktionen für Einzelpixel, Linie und Kreis zur Verfügung, Bildausschnitte können in BIT-Variablen kopiert, modifiziert und zurückkopiert werden. Die Auflösung des augenblicklich angeschlossenen Monitors kann im Programm ebenso abgefragt werden wie die Farbe eines jeden Pixels auf dem Bildschirm. Ein besonderes Feature von RTOS ist es, Bereiche für mehrere zusätzliche Bilder im Speicher einrichten zu können. Sowohl von Programm- als auch von Kommandoebene aus kann bestimmt werden, welches der Bilder angezeigt werden soll. Auf diese Weise kann man Bildfolgen programmgesteuert auf dem Bildschirm erscheinen lassen. Jedes Programm kann festlegen, für welches der Bilder die eigenen Graphikaufrufe bestimmt sind. Mehrere Tasks können also parallel an mehreren Graphiken arbeiten, ohne sich gegenseitig zu stören. Die auf Bild 2 dargestellte Graphik wurde mit niedriger Priorität im Hintergrund berechnet, während ich an einem anderen Programm arbeitete. Mit dem Hardcopy-Befehl wurde dann der Ausdruck erzeugt, ohne mein Programmieren zu stören.
Bleibt schließlich zu klären, weshalb weder Ramdisk noch Spooler gebraucht werden. Eine Ramdisk ist überflüssig, weil nicht nur mehrere Programme, sondern auch mehrere Dateien im RAM abgelegt werden können. Auch hier gilt nur die Speichergröße als Grenze. Und ein Spooler erübrigt sich, weil das Ausdrucken nichts anderes ist als das Kopieren einer Datei in die Datenstation Drucker. Diesen Kopiervorgang betreut eine Task, die wie die oben beschriebene Betreuungstask der seriellen Schnittstelle Wartezustände hat und somit den Prozessor für andere Aufgaben freigibt.
Literatur
[1] L. Frevert, Echtzeit-Praxis mit PEARL, B. G. Teubner Verlag, Stuttgart 1985
[2] Carl-Marcus Weitz, Echtzeit-Multitasking mit RTOS/ PEARL, ct 8/86 bis 3/87