Die grafische Expertensystemschale
EMA-XPS


Softwarebeschreibung

Inhaltsverzeichnis

1. Anlaß dieser Arbeit und Entwicklungsgeschichte der Expertensystemschale Babylon 2. Konzept einer Zwei-Prozeß-Lösung
2.1 Vorgaben und Zwänge im Vorfeld der Konzeptbildung
2.2 UNIX und seine Möglichkeiten der Interprozeßkommunikation
2.3 Interaktive Grafik
2.4 Das X Window System
2.5 Auflösung des Konflikts sequentieller mit ereignisorientierter Programmierung am Beispiel der laboreigenen Liniengrafik xgrf3
2.6 Das Terminalemulationsprogramm xterm
2.7 Notwendigkeit preemptiven Multitaskings zur Vermeidung der Reimplementierung der Inferenzmaschine von Babylon-2
3. Die Schale EMA-XPS v1
3.1 Modularer Aufbau der Schale Babylon-2
3.2 Mensch-Maschine-Schnittstelle von Babylon-2
3.3 Interprozeß-Kommunikation
3.4 Wechselnde Master/Slave Beziehung
3.5 Grafisches Erscheinungsbild
4. Implementierung von EMA-XPS v2
4.1 Toplevelloop von CLtL1 LISP-Implementierungen
4.2 Virtuelle Kanäle
4.3 Zustandsmaschine als Beobachter des LISP-Prozesses
4.4 babylon-3 Emulation
5. Zusammenfassung 6. Ausblick


1. Anlaß dieser Arbeit und Entwicklungsgeschichte der Expertensystemschale Babylon

Im Jahr 1988 wurde von der Forschungsvereinigung Antriebstechnik (FVA), einem Teilbereich des Vereins Deutscher Maschinen- und Anlagenbauer (VDMA), ein Forschungsvorhaben ausgeschrieben, mit dem Ziel, einem projektierenden Ingenieur der Fachrichtung Maschinenbau bei der Auslegung frequenzumrichterbetriebener Drehfeldmotoren Assistenz anzubieten. Zu diesem Zweck sollte ein Expertensystem erstellt werden, mit dem der Ingenieur in einen Dialog tritt. Mittels zeitgemäßer grafischer Darstellungsmöglichkeiten wird Wissen an diesen weitergegeben und ihm bei der Auslegung assistiert. Im Rahmen der FVA betreiben in erster Linie mittelständische Industrieunternehmen Gemeinschaftsforschung. Die Forschungsergebnisse stehen bevorzugt den Mitgliedsfirmen zur Verfügung.
Auf dem Software-Markt haben sich in den letzten Jahren Expertensystemschalen etabliert, die in der Lage sind, große Wissensmengen zu verarbeiten (Tabelle P1). Diese waren bisher bevorzugt im Workstation-Bereich angeboten worden, weil dort die Hardwarevoraussetzungen am ehesten zu erfüllen waren. Mittlerweile ist die Leistungsfähigkeit der Personal Computer derart angestiegen, daß auch Portierungen auf diese Plattformen sinnvoll werden.
Mit dem Beginn des FVA-Vorhabens Ende 1989 waren auf dem PC-Sektor noch keine geeigneten Schalen verfügbar, die die zu erwartenden Wissensmengen hätten handhaben können. Andererseits waren die vorhandenen Hardware-Resourcen in den einzelnen Firmen zu bedienen, um Neuinvestitionen zu vermeiden. Daraus ergab sich die Forderung nach einer leistungsfähigen Expertensystemschale, die im Quelltext frei verfügbar sein sollte, um nötigenfalls selbst Portierungen vornehmen zu können. Weiterhin mußte sie mächtig genug sein, um die Wissensmengen geeignet bearbeiten zu können. Schließlich sollte sie grafikfähig sein, um den Dialog mit dem Benutzer zeitgemäß aufbereitet führen zu können.
Mit der Einschränkung, daß die Quelltexte frei verfügbar sein sollten, war die Auswahlmenge bereits sehr klein geworden. Die Wahl fiel auf die hybride Expertensystemschale Babylon (Version 2.x) der Gesellschaft für Mathematik und Datenverarbeitung (GMD). Sie ist in der Programmiersprache CommonLISP programmiert, modular aufgebaut und bereits an viele LISP-Implementationen angepaßt worden. Allerdings verzichtet Babylon zugunsten der leichten Portierbarkeit auf eine grafische Benutzerkommunikation. Stattdessen verwendet es ausschließlich den Standardein- und den Standardausgabekanal [S2,S3].
Um möglichst wenig Projektzeit für die eigentliche Wissenseingabe zu verlieren, galt es daher, ein Konzept zu entwickeln, mit dem unter Umgehung einer großen Überarbeitung der Quelltexte der Schale diese Grafikfähigkeit ergänzt werden könnte. Dieses Konzept wird in den nächsten beiden Kapiteln dieser Arbeit vorgestellt.
Ende 1990 stellte das Softwarehaus VW-GEDAS, ein Unternehmen der Volkswagen-Gruppe, das Produkt babylon (Version 3.x) vor [S4]. Dieses Programm wird in dieser Arbeit durch Kursivstellung von der GMD-Version unterschieden. Ausgehend von den Quelltexten der Schale Babylon-2 ist dort eine komplette Neuprogrammierung unter der LISP-Implementierung Allegro CL [P8] sowie deren Erweiterungen des Sprachstandards vorgenommen worden. Dies verhindert die Nutzung von LISP-Interpretern anderer Anbieter. Es wurde entschieden, daß für das laufende FVA- Vorhaben sowie für zwei weitere bei der FVA anstehende Projekte babylon zum Einsatz kommen soll, da ein Synergieeffekt für die einzelnen Mitgliedsfirmen abzusehen war und ihnen die Möglichkeit des Langzeitsupports durch GEDAS zur Verfügung stand. Auch der Umstand, daß Volkswagen Mitglied der FVA ist, spielte hierbei eine Rolle.
Damit wurde das Konzept der Grafikerweiterung für das laufende FVA-Vorhaben nicht mehr benötigt. Am Lehrstuhl für elektrische Maschinen und Antriebe ist das Konzept aber weiterentwickelt worden. Diese Arbeiten führten zu der grafischen dialogorientierten hybriden Expertensystemschale EMA-XPS [T1]. Sie stellt in der aktuellen Version 2.1 neben den grafischen Möglichkeiten zur Sitzungslaufzeit auch grafische Editoren zur Wissenseingabe zur Verfügung.
Angesichts der Rezession der letzten Jahre hat man bei VW 1994 entschieden, kostenintensive und wenig gewinnversprechende Projekte nicht länger weiterzuführen. Dazu gehört auch babylon-3. Nun bestand Bedarf für die FVA, zur Sicherung der Ergebnisse aus drei laufenden Vorhaben eine Ersatzschale zu beschaffen. EMA-XPS bot hierfür gute Voraussetzungen. Es mußte dahin erweitert werden, daß es die von der GEDAS eingebrachten Erweiterungen des Leistungsumfangs der Schale nachbilden konnte. Daher ist die Endbenutzerschnittstelle so umgearbeitet worden, daß sie babylon-3 Sitzungen identisch darstellen konnte. Die Babylon-Query-Language (BQL) - ein Datenbankanwendungen ähnlicher Zugriff auf das Faktenwissen - ist realisiert worden. Um im Sinne der Sprachdefinition von babylon-3 Tasks abarbeiten zu können, ist die Babylon-2- Inferenzmaschine um einen Taskprozessor erweitert worden. Da viele Konstrukte nun zwar in EMA-XPS und babylon-3 verfügbar waren, aber unterschiedliche Syntax hatten, war eine Wissensbasisübersetzung notwendig geworden. Diese Übersetzung ist mittlerweile in Form eines automatischen Importfilters realisiert, das heißt, EMA-XPS liest babylon-3 Wissensbasen direkt ein und wandelt ihre Bestandteile bereits beim Laden in Babylon-2 Konstrukte um, sodaß sie zur Sitzungszeit geeignet zur Verfügung stehen.
EMA-XPS ist seit kurzem auch erfolgreich auf leistungsfähige PC-Plattformen unter dem frei verfügbaren UNIX-Derivat Linux 1.2 portiert worden [U2]. Die Schale steht im World Wide Web unter

http://wmwap1.math.uni-wuppertal.de/EMA-XPS/

als Quelltext-Distribution frei zur Verfügung. Weiterhin liegen dort statisch gebundene Binärversionen für Linux und SunOS bereit. Auf diese Weise lassen sich die Lizenzgebühren für OSF/Motif vermeiden. Damit ist EMA-XPS bei Verwendung des ebenfalls frei verfügbaren LISP- Interpreters CLISP komplett befreit von Lizenzgebühren.

Momentan ist ein Entwicklerteam dabei, eine freiverfügbare Nachbildung der Motif-Oberflächenelemente (Widgets) unter dem Namen Lesstif zu erstellen [U6]. Damit würden ebenfalls die Lizenzgebühren für Motif entfallen.
Bei Verzicht auf Motif wird EMA-XPS ein lizenzkostenfreies Produkt. Die Nutzungsrechte sind entsprechend der X-Windows Copyright-Notiz (für X11 und Babylon-2.3), der General Public License (GPL) der Free Software Foundation (EMA-XPS, gcc, clisp und Lesstif) und des Linux-Betriebssystems (größtenteils GPL) geregelt.

Präsentation vollfarbig schwarz/weiß
Sprache deutsch englisch
Leistungsumfang Vollversion resourcenschonendere Laufzeitversion ohne Wissenseingabemöglichkeiten

Tabelle S1: Ausprägungen von EMA-XPS

Tabelle S1 schlüsselt die 8 Ausprägungen auf, in denen EMA-XPS derzeit zur Verfügung steht. Diese reichen von der vollfarbigen, deutschsprachigen Vollversion bis hin zur englischsprachigen Laufzeitversion, optimiert für die Ausgabe auf monochromen Bildschirmen. Speziell die grafische Präsentation sowie die Wahl der Texte wird ausschließlich über die sogenannten Xresourcen kontrolliert. Dabei handelt es sich um eine Eigenschaft des X-Window-Systems, das Aussehen einer grafischen Anwendung nach ihrer Fertigstellung noch zu verändern (Kapitel 2.4). Daher ist es sogar bei Vorliegen einer reinen Binärdistribution der Schale möglich, beispielsweise eine französischsprachige Version nachträglich zu erstellen, ohne C- oder LISP-seitig Änderungen vornehmen zu müssen.

Im nächsten Kapitel wird ausgehend von den bereits angesprochenen Vorgaben an die zu entwickelnde Schale die Konzeptbildung für eine Zwei-Prozeß-Lösung beschrieben. Das daran anschließende Kapitel 3 stellt die Umsetzung dieses Konzepts in Form der ersten Version (v1) von EMA-XPS vor. In Kapitel 4 werden die Erfahrungen im Umgang mit EMA-XPS v1 als Ausgangsbasis für eine stabilere und resourcenschonendere Version der Interprozeßkommunikation genommen. Es hat die eigentliche Implementierung von EMA- XPS v2.1 zum Thema. Ausgehend von dem überarbeiteten Kernbereich der Interprozeßkommunikation werden die Möglichkeiten zur Ausgestaltung einer Endbenutzerschnittstelle vorgestellt. Die Wissenseingabemöglichkeiten und die Einbindung der zugehörigen Editoren in die Konzeption werden beleuchtet.
Schließlich wird auf die Erweiterungen zum Einlesen von babylon-3 Wissensbasen eingegangen.

2. Konzept einer Zwei-Prozeß-Lösung

2.1 Vorgaben und Zwänge im Vorfeld der Konzeptbildung

Wie in Kapitel 1 einleitend erläutert, war die erste und vordringliche Vorgabe, große Mengen an Wissen zu verarbeiten. Damit war eine Vorentscheidung hin zu leistungsstärkerer Hardware gefallen, die eine Festlegung auf Multitasking-Betriebssysteme wie das proprietäre VMS [U7] oder UNIX [U1] bedeutete. VMS wird ausschließlich auf den VAX-Rechnern der Firma DEC angeboten, die meisten anderen Plattformen werden dagegen mit UNIX-Derivaten betrieben. Die Gesamtzahl der VMS-Installationen ist demgemäß im Verhältnis zu den UNIX-Installationen klein. Dieser Prozentsatz sinkt derzeit weiter, da die Gesamtzahl der Plattformen dieser Leistungsklasse stark ansteigt und Neuinstallationen zumeist UNIX verwenden. Daher galt die erste Beschränkung, im weiteren nur die unterschiedlichen UNIX-Varianten zu berücksichtigen.
Weiterhin sollte eine Schale zum Einsatz kommen, deren Quelltexte vorhanden sind. Dies ist die Voraussetzung, um auf eine Vielzahl unterschiedlicher Plattformen portieren zu können. Die Wahl fiel auf Babylon-2, weil diese Schale bereits portabel programmiert worden war. Babylon-2 verzichtet zugunsten leichter Portabilität auf eine grafische Oberfläche. Im Bemühen, eine grafische Oberfläche zu realisieren, ist man unter UNIX auf das X-Window-System festgelegt. Unter X-Windows gibt es unterschiedliche Fensterbibliotheken, die in typischer Weise die Gestalt einer Anwendung prägen. Neben den frei verfügbaren Athena- Widgets, die Bestand der X-Windows sind, gibt es auch OPEN- LOOK (seit X11R5 ebenfalls Bestandteil der X-Windows- Distribution) und OSF/Motif, für das Lizenzgebühren erhoben werden [U3-U5]. Aufgrund der hohen Akzeptanz der Apple- Macintosh Oberfläche und der MS-Windows für PCs fiel die Entscheidung zugunsten des den MS-Windows nachempfundenen Motif-Widget-Sets.
Die meisten CommonLISP-Interpreter unter UNIX unterstützen die LISP-Schnittstelle zum X-Window-System (CLX), die ebenfalls Bestandteil der X-Windows-Distribution ist. Damit ist man in der Lage, auch in LISP Grafikanwendungen zu erstellen. Leider existiert keine entsprechende Schnittstelle zur Motif-Bibliothek. Andererseits stehen für die Programmiersprache ANSI-C die entsprechenden genormten Funktionsaufrufe zur Verfügung, was für eine leichte Portabilität Voraussetzung ist.
Viele LISP-Interpreter bieten individuelle Erweiterungen des Sprachumfangs an, wie beispielsweise ein Socket-Interface, um direkt das Rechner-Netzwerk ansprechen zu können. Auch sind sogenannte Foreign-Function-Interfaces weit verbreitet, mit deren Hilfe von LISP aus Bibliotheksfunktionen aktiviert werden können, die beispielsweise in ANSI-C erstellt sein mögen. Weil dadurch bei der Programmierung eine Festlegung auf einen bestimmten LISP-Anbieter notwendig geworden wäre - und nicht garantiert werden kann, daß dieser alle in Frage kommenden Plattformen unterstützt - war von derartigen Erweiterungen Abstand genommen worden.
Zu der Zeit, in der Babylon-2 entwickelt worden ist, gab es den CLOS-Standard noch nicht. Bei der GMD wurde auch im Bereich objektorientierter Sprachen geforscht. Man hat dort das Meta Class System (MCS) definiert, eine eigene objektorientierte LISP-Erweiterung [P15]. Das MCS ist Bestandteil der Babylon-Quelltexte. Babylon selbst ist durchgehend objektorientiert programmiert worden. Bedingt durch den Umstand, daß die Quelltexte in einer CLtL1- Umgebung entwickelt worden sind, und weil CLtL1 vereinfacht als eine Untermenge von CLtL2 angesehen werden kann, ist mit der Beschränkung auf die Sprachfestlegung CLtL1 eine größere Zahl von LISP-Interpretern unter EMA-XPS verwendbar. Dies kommt beispielsweise älteren Plattformen zugute, bei denen eine Software-Aufrüstung nicht mehr sinnvoll ist.
Damit sind die Hard- und Softwarevoraussetzungen festgelegt, unter denen das Konzept für EMA-XPS entwickelt worden ist:

  • eine Graphic-Workstation
  • ein Derivat des UNIX Betriebssystems (mit den unter UNIX vorhandenen Möglichkeiten der Interprozeßkommunikation)
  • das X-Window System
  • die OSF/Motif Fensterbibliothek
  • ein ANSI-C Compiler
  • ein CLtL1 kompatibler CommonLISP Interpreter
  • die CommonLISP Quelltexte von Babylon-2.3
  • Tabelle S2: Hard- und Softwarevorraussetzungen von EMA-XPS

    2.2 UNIX und seine Möglichkeiten der Interprozeßkommunikation

    Ende der sechziger Jahre wurde in Zusammenarbeit zwischen dem Massachusetts Institute of Technology (MIT), den Bell Laboratories und General Electric ein Betriebssystem für den Multi-User-Einsatz (MULTICS) geplant und entwickelt. Es sollten mehrere Aufgaben quasi zur gleichen Zeit abgearbeitet werden können. Dies sollte durch Aufteilung der gesamten Rechenleistung in Zeitscheiben erfolgen, in denen der Rechner abwechselnd die einzelnen Aufgaben bearbeitet. Da sich schnell herausstellte, daß MULTICS zu langsam war, wurden die Aktivitäten bei Bell eingestellt. Um ein laufendes Forschungsvorhaben von Bell nicht zu gefährden, mußte K. Thompson einen Ausweg schaffen, indem er die von MULTICS benötigten Teile auf einer DEC PDP-7 implementierte. Der Name für diese Implementierung ergab sich aus UNI (für unified conception) und der Endung CS, die in X verkürzt wurde. Er soll von B. W. Kernighan erdacht worden sein. In 1971 wurde eine Anpassung auf die leistungsstärkere PDP-11 vorgenommen, die in den siebziger Jahren sehr populär war.
    Eine zweite Version des UNIX-Betriebssystems mit Interprozeßkommunikationskanälen erschien 1972. Eine vollständig neu in der eigens dafür entwickelten Hochsprache C geschreibene Version wurde 1973 von D. M. Ritchie und K. Thompson fertiggestellt. Die Prinzipien wurden 1974 veröffentlicht und weckten gerade an den Universitäten großes Interesse an diesem neuen System. Bell entschied sich daher, die nächste Release (gemäß der Versionsnummer der Manuals Version 6 genannt) den Universitäten für ausschließlich wissenschaftliche Nutzung kostenlos zur Verfügung zu stellen. V7 stand den Universitäten ab 1979 zur Verfügung.
    Bereits 1976 begann an der University of California at Berkeley (UCB) ein größeres Entwicklungsvorhaben in der Gruppe um B. Joy, C. Haley und K. Thompson, das eine eigene erweiterte Linie von UNIX Systemen zur Folge hatte. 1978 wurde eine 32-Bit Version des Betriebssystems herausgebracht. 1979 wurden die Ergebnisse dieser Arbeiten unter dem Namen Release 3 BSD (Berkeley Software Distribution) der Öffentlichkeit vorgestellt. 3BSD besaß erstmalig eine virtuelle Speicherverwaltung. Es folgten die Versionen 4BSD, 4.1BSD, 4.2BSD und 4.3BSD. Diese Versionen standen ebenfalls den Universitäten zur Verfügung, waren aber nicht für die kommerzielle Verwendung vorgesehen. Ab Version 4.1 standen ein schnelles Dateisystem, Disk Quotas und das TCP/IP Socket Interface zur Verfügung, 4.3BSD unterstützt auch TCP/IP-Subnetze und Routing [U9, U10, U17].
    AT&T Bell erkannte das kommerzielle Potential und brachte mit System III das erste System heraus, das nicht den Universitäten zur Verfügung gestellt wurde. Dem folgte 1983 das System V. Dieses ist weiterentwickeltworden und steht heute in den Versionen SVR2, SVR3, SVR4, SVR4.1 und SVR4.2 zur Verfügung.
    Auch andere kommerzielle Anbieter brachten UNIX- ähnliche Betriebssysteme heraus, bei denen hauseigene Systembesonderheiten teilweise deutliche Spuren hinterlassen haben. Einige der heute verfügbaren, gängigen Systeme sind: SunOS, Solaris, ULTRIX, AIX, IRIX, HP-UX, NeXTStep, Coherent, XENIX und OSF/1. Diese Vielzahl an plattformoptimierten Systemvarianten hat UNIX seit Mitte der 80er Jahre zum verbreitetsten Betriebssystem für Workstations gemacht.
    Bild S1 verdeutlicht die Entstehungsgeschichte der UNIX-Betriebssystemvarianten [U1, U8, U10, U19].

    Bild S1: Stammbaum der UNIX-Betriebssystemvarianten

    UNIX war von Anfang an als ein Multiuserbetriebssystem konzipiert worden, das preemptives Multitasking verwendet, um unterschiedliche Prozesse der CPU zuzuteilen. Die Prozeßzuteilung regelt der Scheduler nach einer prioritätenorientierten Vergabestrategie. Höherpriorisierte Prozesse werden bevorzugt bedient, gleichwertige Prozesse werden der Reihe nach jeweils maximal für die Dauer einer Zeitscheibe aktiviert und danach wieder unterbrochen, ohne daß die anderen Prozesse davon berührt werden. Dies bewirkt eine pseudoparallele Abarbeitung der unterschiedlichen Aufgaben und unterscheidet sich somit beispielsweise vom kooperativen Multitasking der MS-Windows, bei denen jeder Prozeß selbst entscheidet, wann er die CPU wieder zum Vorteil anderer Prozesse freigibt (siehe auch Kapitel 2.7).
    UNIX hat bereits sehr früh Möglichkeiten der Interprozeßkommunikation zum Informationsaustausch bereitgestellt. Dies schließt die Kommunikation über ein Rechnernetzwerk hinweg mit Prozessen auf anderen Rechnern ein. UNIX beruht auf einem Mehrschichtenmodell, in dessen Kern der Kernel sitzt, der den Zugang zu den Hardwareresourcen kontrolliert. Die Prozesse können Geräte also immer nur indirekt ansprechen, die sich ihnen abstrakt präsentieren. Mit der Einführung des virtuellen Speichermanagements ist die vollständige Entkopplung der Prozesse erreicht worden. Jeder Prozeß existiert in einem eigenen in sich geschlossenen Datenraum. Ihm stehen keine Informationen zur Verfügung, die ihm Informationen über den Zustand eines anderen gerade aktiven Prozesses geben könnten. Die Abarbeitung geschieht asynchron. Da Prozesse mitunter Daten miteinander austauschen und sich aufeinander synchronisieren müssen, ist eine teilweise Aufhebung dieser Entkoppelung vorgesehen worden. Diese Möglichkeiten sollen im weiteren vorgestellt werden.
    Der Scheduler ist als übergeordnete Instanz in der Lage, Signale an die einzelnen Prozesse zu versenden. Dies läßt sich am ehesten mit einem Hardware-Interrupt in einer Einprozeßumgebung vergleichen. Der Prozeß sieht für jedes mögliche Signal ein Antwortverhalten vor. Beispielsweise teilt der Scheduler einem Elternprozeß das Enden eines seiner Kindprozesse mit, also von Prozessen, die von ihm gestartet worden sind. So kann ein Prozeß ein Kind aktivieren, das eine Teilaufgabe erfüllt und auf dessen Ergebnis gewartet wird. Der aufrufende Prozeß erfährt dadurch, wann diese Ergebnisse beispielsweise in Form beschriebener Dateien bereitstehen. Ein Prozeß A kann aber auch einem Prozeß B ein Signal zukommen lassen. Da die Anzahl der unterschiedlichen Signalarten sehr begrenzt ist, ist damit zwar eine schnelle Synchronisierung möglich, der Datenaustausch muß aber mit anderen Mitteln bewerkstelligt werden.
    Das UNIX-Dateisystem ist so organisiert, daß eine Datei, die ein Prozeß zum Schreiben geöffnet hat, nicht von einem anderen Prozeß zum Schreiben geöffnet werden kann. Dieses Filelocking kann ebenfalls für eine Synchronisierung genutzt werden. Da es das langsame Dateisystem benötigt, sollte es nicht für häufiges Synchronisieren verwendet werden. Der Prozeß wird beim Versuch, auf eine verriegelte Datei zuzugreifen, unterbrochen. Erst wenn die Verriegelung aufgehoben ist, wird der Prozeß fortgesetzt.
    Der schnellste Datenaustausch wird dadurch ermöglicht, daß ein Bereich des physikalischen RAM-Speichers der virtuellen Speicherverwaltung entzogen wird und mehreren Prozessen als gemeinsamer Datenbereich (shared memory) zugeordnet wird. Hierin lassen sich beispielsweise FIFOs (First In First Out) in Form von Ringpuffern aufbauen. Zur Synchronisierung muß der Prozeß ständig relevante Änderungen des Speicherinhalts überwachen (polling). Dies erfordert Rechenleistung. Gemeinsam genutzte Datenbereiche sollten nur in kleinen Mengen angefordert werden, weil es den Wirkungsgrad der Speicherverwaltung mindert. Hierbei handelt es sich um Speicher, der explizit an das Betriebssystem zurückgegeben werden muß im Gegensatz zum virtuellen Adressraum jedes Prozesses [U11]. Gemeinsam genutzte Datenbereiche entsprechen am ehesten einem Dual- Port-RAM in reinen Hardwarelösungen. Die neuesten Ausprägungen von UNIX unterscheiden zwischen Prozessen und Threads. Threads entstehen durch Gabelung eines Prozesses in mehrere identische Abbilder, die dann aber den ursprünglich zugewiesenen Adressraum des Prozesses gemeinsam nutzen.
    Eine klassische Form der Prozeßsynchronisierung sind Semaphorvariablen. Sie wurde Mitte der 60er Jahre von E. W. Dijkstra entwickelt [P11]. Dabei handelt es sich um Integer-Variablen in einem Sharable-Memory Bereich des Kernels, die jeweils eine ganzzahlige Zahl enthalten. Es existieren nur 3 erlaubte Operationen: Initialisierung, Signal und Wait. Ist der Wert der Semaphore größer Null, wird er durch ein Wait dekrementiert. Wird der Wert dadurch kleiner oder gleich Null, wird der Prozeß angehalten. Signal degegen überprüft, ob andere Prozesse warten. Ist dies der Fall, darf einer der Prozesse fortfahren, andernfalls wird der Wert inkrementiert. Damit läßt sich die korrekte Abarbeitung kritischer Abschnitte einer komplexen Aufgabe sicherstellen. Andererseits kann eine ungeschickte Verwendung dieses Mechanismus leicht einen Deadlock hervorrufen. Dann warten die betroffenen Prozesse unendlich lange darauf, daß der andere die Freischaltung bewirkt. Ein weiteres Verständnis von Semaphoren wird für diese Arbeit nicht benötigt, daher wird hier auf ein detailiertes Eingehen verzichtet.
    Pipelines sind spezielle Dateien. Sie werden zweimal geöffnet. Einmal nur zum Lesen und einmal nur zum Schreiben. Damit steht auf dem Umweg über das Dateisystem ebenfalls ein FIFO-Mechanismus zur Verfügung. UNIX unterscheidet zwischen named und unnamed Pipes. Named pipes erhalten zusätzlich einen Eintrag in den Verzeichnisbaum. Dies ist vorteilhaft, wenn ein anderer Prozeß ein Ende dieser FIFO öffnen will, der nicht aus dem ersten durch Gabelung (fork) hervorgegangen ist. Pipes werden als Sockets der Adressfamilie AF_UNIX realisiert, die das loopback-Interface nutzen.
    Sockets bieten auf der Basis des Internet-Protokolls (IP) Zugang zum Rechnernetzwerk Internet. UNIX-Rechner, die nicht als Router oder Gateways eingesetzt werden, um Teilnetze miteinander zu verbinden, haben genau eine Rechneradresse der Adressfamilie AF_INET für die Kommunikation mit anderen Rechnern im Netzwerk und die spezielle Adresse 127.0.0.1 für das loopback-Interface (AF_UNIX). Damit können Netzanfragen, die an Ports auf dem eigenen Rechner gerichtet sind, schneller bearbeitet werden. Pro Rechneradresse existieren 216 = 65536 Ports. Die ersten 1024 Ports sind privilegiert und speziellen Aufgaben vorbehalten. Die anderen stehen Anwendungsprogrammieren zur Verfügung. Trotzdem sollten die Portnummern nicht beliebig gewählt werden. Beispielsweise hört der Xserver am Port 6000, ob sich X-Windows-Applikationen anmelden wollen. Detailiertere Informationen - auch zum Transport Control Protocol (TCP), das auf IP aufsetzt - sind in [U9, U10, U17] zu finden.
    Unter System V steht heute auch ein Streams-Interface zur Verfügung, das als ein abstrakterer und eleganterer Zugang zu IPC-Kanälen angesehen werden kann.
    Pseudo-Teletypes stellen eine leistungsfähigere Variante von FIFOs dar. Pseudo-Teletypes bilden das Verhalten von Teletypes nach. Ein Teletype (TTY) ist ein Gerät, hinter dem ein Text-Terminal vermutet wird, wie in Bild S2 dargestellt.

    Bild S2: Mensch-Maschine-Kommunikation über eine Teletype

    UNIX ist als Mehrbenutzersystem konzipiert worden. Demgemäß sollen mehrere Menschen gleichzeitig mit dem System kommunizieren können. Jeder Benutzer benötigt dazu einen eigenen Arbeitsplatz. Dies kann durch Text-Terminals geschehen. Diese werden beispielsweise mittels serieller RS232-Schnittstellen mit dem UNIX-Rechner verbunden. Die SIO-Hardware (Serial Input and Output Device) wird von einem Treiber bedient, der Bestandteil des Kernels ist. Der Prozeß wird durch Öffnen einer Gerätedatei zum Lesen und Schreiben (im Bild /dev/tty1) mit dem Gerät (Device) verbunden. Dies erledigt pro Teletype-Verbindung der getty- Prozeß, ein Kind des Urstart-Prozesses init. Er startet einen login-Prozeß, der wiederum durch einen Kommandozeileninterpreter (hier /bin/sh) ersetzt wird, sobald der Benutzer sich geeignet ausgewiesen hat. Mit dem Beenden dieses Interpreters (Shell) ist eine Sitzung beendet und getty aktiviert erneut login.
    Drückt der Benutzer die Taste "d", wird der Code des Zeichens vom Terminal über die Schnittstelle an den Treiber gesandt. Dieser sendet, sofern er in ECHO-Betriebsart ist, dieses Zeichen an das Terminal zurück, das ein "d" auf dem Display darstellt. In der RAW-Betriebsart wird dieses Zeichen dann auch sofort an den Prozeß weitergeleitet. In COOKED-Einstellung dagegen wird das Zeichen gepuffert, bis eine Zeile komplettiert worden ist, also die Wagenrücklauf- Taste (CR) gedrückt ist. Dann erst werden alle aufgelaufenen Zeichen gesandt und der Puffer geleert. Dies ist die übliche Betriebsart. Wahlweise kann CR als CR, Neue- Zeile (NL) oder CR und NL an den Prozeß weitergeleitet werden. Die Umwandlung von CR in CR-NL ist voreingestellt.
    Bild S2 zeigt die Eingabe des Kommandos dir. Der Interpreter liest das Kommando von seiner Standardeingabe ein und erkennt, daß es sich um die Aufforderung handelt, ein Shell-Skript auszuführen. Er öffnet die Datei und interpretiert, daß er das Programm /bin/ls mit dem Kommandozeilenargument "-al" ausführen soll. Er spaltet einen Prozeß ab, dessen Standardein- und Standardausgabe auf das Teletype gelenkt sind. Dieser schreibt daraufhin den Inhalt des aktuellen Verzeichnisses formatiert in seine Standardausgabe, also zum Gerätetreiber des betroffenen Terminals. Der Treiber sendet die Zeichenfolgen an das Terminal, das diese auf dem Bildschirm darstellt. Im Anschluß daran sendet die Shell, die auf das Terminieren von /bin/ls gewartet hat, eine Prompt-Zeichenfolge (Eingabe aufforderung) und wartet auf weitere Eingaben durch den Benutzer.
    Ein Pseudo-Teletype besteht aus zwei Gerätetreibern (beispielsweise /dev/ttyp0 und /dev/ptyp0). Das ttyXY ist konfigurierbar wie ein Teletypetreiber (RAW/COOKED und dergleichen) und handhabt beispielsweise auch das ECHOing. Anstelle des Zugangs zur Hardware steht dagegen eine bidirektionale FIFO bereit, die die Daten an das ptyXY- Gerät weiterreicht. Ein anderer Prozeß öffnet das Gerät zum Lesen und Schreiben und kann nun beispielsweise das Verhalten des Text-Terminals emulieren. Das Programm xterm ist ein solcher Emulationsprozeß. Durch Verwendung von Pseudo-Teletypes können Programme, die die Kommunikation mit einer Teletype vorraussetzen, auch betrieben werden, wenn keine Teletype zur Verfügung steht [U11, U18].

    2.3 Interaktive Grafik

    Grafische Computerarbeitsplätze unterscheiden sich von Text-Terminals dadurch, daß andere Möglichkeiten der Ein- und Ausgabe für die Mensch-Maschine-Kommunikation bereitstehen.
    Text-Terminals bestehen aus einer Schreibmaschinentastatur (Keyboard) für die Eingaben und einem Bildschirm (Display), auf dem im allgemeinen 25x80 oder 25x132 Zeichen dargestellt werden können. VT100 ist eine mögliche Festlegung des Leistungsumfangs für derartige visuelle Terminals. Visuell steht dabei für die Möglichkeit, nicht mehr nur einen reinen Ausgabestrom - wie beispielsweise mit einem Drucker - darstellen zu können, sondern die Positionierung von Zeichen frei auf der Bildschirmmatrix wählen zu können.

    Bild S3: Ein grafischer Arbeitsplatz mit 2 Bildschirmen, Tastatur und Maus

    Grafikfähige Terminals bieten neben dem Keyboard zusätzlich ein Zeigergerät. Im allgemeinen ist dies eine mit 1 - 3 Knöpfen (Buttons) versehene Maus (Pointer) oder ein Trackball. Für 3D-CAD-Anwendungen stehen oft auch ein Graphic-Tablett, ein Joy-Stick oder ein Light-Pen zur Verfügung [U12]. Bei allen Geräten handelt es sich um grafische Eingabegeräte, die eine geometrische Position an den Rechner weitermelden. Diese Information kann im Zusammenhang mit dem Status der Knöpfe für grafische Eingaben genutzt werden.
    Als Ausgabemedium dienen auch hier Bildschirme mit jeweils einer Matrix von Bildpunkten (Pixels), wobei hier jedes Pixel einzeln ansteuerbar ist. Durch geeignetes Setzen einer bestimmten Menge von Pixels kann dann ebenfalls der Eindruck entstehen, es würde ein Buchstabe dargestellt. Diese Buchstaben sind dabei aber in ihrer Größe veränderbar und innerhalb des darstellbaren Bereichs frei positionierbar. Außerdem können hiermit beispielsweise diagonale Linien und Ellipsen dargestellt werden. Bild S3 zeigt eine mögliche Ausstattung eines grafischen Rechnerarbeitsplatzes.
    Programme, die für die Ausführung auf grafischen Terminals konzipiert sind, unterscheiden sich grundsätzlich von solchen, die Text-Terminals voraussetzen. Die typische Arbeitsweise an Textarbeitsplätzen ist die sequentielle Programmabarbeitung. Dabei wartet der Rechner auf eine Benutzereingabe, die er auswertet und ausführt, um dann auf die nächste Kommandoeingabe zu warten. Mögliche Ereignisse sind Keyboard-Aktionen des Benutzers, die das Programm aber nur auswertet, wenn es der Programmablauf vorsieht. Das Teminal puffert diese bis dahin. Das Programm kennt nur die Funktionen "Zeichen lesen" und "Zeichen schreiben". Beim Einlesen wird ein Zeichen aus dem Puffer geholt und zurückgeliefert. Ist der Puffer leer, wartet das Programm, bis ein Zeichen kommt. Die Zeichenausgabe geschieht dagegen im allgemeinen unmittelbar (Bild S4).
    Grafikfähige Anwendungen stellen deutlich höhere Anforderungen an die Leistungsfähigkeit der vorhandenen Hardware. Es muß hier auch ein sehr viel größerer Aufwand betrieben werden, um die Ein- und Ausgabegeräte zu bedienen. Die größere Zahl von Eingabegeräten macht eine aufwendigere Auswertung unterschiedlicher Eregnistypen nötig. Je nach der Beschaffenheit des Eingabegerätes kann es reichen, den Zustand wiederholt abzufragen (polling). Geräte, die eine große Menge an Informationen bereitstellen, werden diese nicht puffern können. Dann ist der Programmfluß zu unterbrechen (interrupt), um zunächst diese Daten zu retten. Zur Vereinheitlichung der Gerätebedienung empfiehlt es sich daher, einen FIFO- Speicher (Eventqueue) einzurichten, der die Informationen der unterschiedlichen Geräte in einem einheitlichen Datenformat zwischenspeichert. Jedesmal, wenn bei einem Gerät neue Daten eintreffen, wird der Programmfluß unterbrochen und die Art des Ereignisses zusammen mit der aktuellen Uhrzeit vermerkt. Danach wird die Programmabarbeitung wieder aufgenommen [U12, U14].

    Bild S4: Ablauf eines sequentiell arbeitenden Programms

    Bild S5: Ablauf einer ereignisorientiert arbeitenden Anwendung

    Die Flußstruktur des Hauptprogramms bei ereignisorientiert ablaufenden Anwendungen zeigt Bild S5. Die Anwendung initialisiert zunächst die Ein- und Ausgabegeräte, legt die gewünschten Verhaltensweisen fest, die auf bestimmte Ereignisse erfolgen sollen, und geht danach in eine Endlosschleife. Sie wartet auf das Eintreten eines Ereignisses und behandelt es nach geeigneter Zuordnung in der vorab festgelegten Weise.
    Da sich dieses Grundprinzip für alle grafischen Anwendungen wiederholt, empfiehlt es sich, Funktionenbibliotheken bereitzustellen, die einen standardisierten Zugang zu diesen Resourcen ermöglichen. Solche Bibliotheken enthalten auf unterster Ebene Routinen, die die Geräte individuell ansprechen und darauf aufbauend abstraktere Funktionen, die gemäß der linken Hälfte von Bild S6 die Ereignisabarbeitung verwalten.
    In modernen Fenstersystemen wie dem des Apple Macintosh Betriebssystems, den Microsoft Windows oder dem X-Window- System stellt sich weiterhin das Problem, daß mehrere Anwendungen gleichzeitig auf das selbe Grafikterminal zugreifen. Die Fenster einer Anwendung, also der Teil des Bildschirms, der einer Anwendung zugeordnet ist, kann Teile der Fenster anderer Anwendungen überdecken. Daraus ergeben sich zusätzliche Ereignisse, auf die eine Anwendung geeignet reagieren können muß. Beispielsweise muß ein Fenster, das bislang teilweise überdeckt war, neu gezeichnet werden, wenn ein bislang verdeckendes Fenster in den Hintergrund tritt (Expose-Event). Dadurch entstehen zusätzliche, geräteunabhängige Ereignistypen.
    Unter dem Fenstersystem X, das weiter unten vorgestellt wird, ist eine Aufgabenverteilung nach dem Client-Server- Prinzip umgesetzt worden. Die Hardware kann nur noch indirekt über einen Grafikserver, den Xserver, angesprochen werden. Die Anwendungen (Clients) beschreiben dem Server mittel eines Protokolls, das über Interprozeßkommunikationskanäle gesandt wird, in welcher Weise er die Geräte zu beeinflussen hat. Andererseits kann aufgrund der Fenstertechnik die Vielzahl der Ereignisse den unterschiedlichen Anwendungen zugeordnet werden. Beispielsweise kann die Geometrie-information (Lage) des Mauszeigers beim Drücken eines Mausknopfes mit der Lage eines Fensters verglichen werden. Die rechte Hälfte von Bild S6 verdeutlicht die Entwicklung dieses Prinzips.

    Bild S6: Entwicklung der Aufgabenverteilung in grafischen Client-Server-Anwendungen

    2.4 Das X Window System

    Die Geschichte des X Window Systems begann im Jahr 1984, als die Verantwortlichen am Massachusetts Institute of Technoloy (MIT) mit einem Problem konfrontiert waren, das an den Universitäten und in der Industrie gleichermaßen vorhanden war. Über Jahre hatte sich eine gewisse Anzahl unterschiedlichster Rechnersysteme angesammelt, die nicht zueinander kompatibel waren. Die Entwicklungsgeschichte des Betriebssystems UNIX zeigte, daß es möglich ist, unterschiedlichste Rechnerhardware mit einem einheitlichen Betriebssystem zu versehen. Analog war hier das Ziel, zum Zweck der Ausbildung aus diesem Pool ein Netzwerk von grafikfähigfähigen Workstations zu schaffen (Bild S7). In Zusammenarbeit mit IBM und DEC entstand das Projekt Athena. Lokale Applikationen sollten ebenso wie auf anderen Rechnern laufende Applikationen auf ein und demselben Display darstellen können.

    Bild S7: Vernetzte grafische Arbeitsplätze unter dem X Window System

    Als Ausgangsbasis diente die an der Standford University entwickelte Softwareumgebung W. Die erfolgreiche Umsetzung dieser Ziele erhielt den Namen X in der Version 1.0, später kurz als X10 bezeichnet. Mit der Nachfolgeversion X11 brachte das MIT Ende 1987 das Fenstersystem heraus, das zu einer der bedeutendsten Softwaretechnologien der 90er Jahre geworden ist. Ab der Release X11R2 ist die Verantwortung über die Weiterentwicklung dieses netzwerkbasierten grafischen Fenstersystems für Workstations an das 1988 gegründete X Consortium übertragen worden. Diesem gehören eine Vielzahl von Computerherstellern, Softwarehäusern und Universitäten an. Im Januar 1990 ist die Release X11R4 herausgekommen. Die in dieser Arbeit vorgestellten Konzepte benötigen den Leistungsumfang von X11R4. Mit X11R5 und X11R6 sind weitere Erweiterungen wie Fontserver und 3D-Grafik-Unterstützung hinzugekommen. Die Grundkonzepte der Interclient- Kommunikation inklusive Window-Management aber, mit denen X11R4 das X-Protokoll nochmal grundlegend geklärt hat, sind seitdem nicht mehr überarbeitet worden. Mit dem Erscheinen von X11R7 ist in Kürze zu rechnen [U15, U16].

    Bild S8: Kommunikation zwischen Clients und Xserver

    Basierend auf dem weiter oben bereits beschreibenen Client-Server-Konzept ist eine Trennung zwischen den der Display-Hardware nahen Routinen und den abstrakteren Bibliotheksfunktionen vorgenommen worden. Dazwischen ist eine Art Displaybeschreibungssprache festgelegt worden, das X-Protokoll [U13]. Auf diese Weise kann der Xserver, der als einziger die Eigenschaften der dedizierten Grafikhardware kennt, den Bildaufbau handhaben. Die Applikation erhält nur die notwendigen Informationen über das Display bereitgestellt, wie beispielsweise die Auflösung in Pixel und die Farbtiefe. Die Xlib- Bibliotheksfunktionen wandeln die Anforderungen an den Xserver in Protokollsequenzen um, die dann über das Socketinterface des X-Window-Systems unter TCP/IP oder DECnet über das Rechnernetzwerk an den Zielrechner versandt werden. Der Xserver dort hört ebenfalls an einem Socket, um die Nachricht zu empfangen, zu interpretieren und auszuführen. Da es sich bei dem X-Window-System um eine interaktive Grafik handelt, kann der Xserver dem Client ebenfalls Nachrichten schicken. Wenn beispielsweise ein Mausklick im Fenster des Clients erfolgt, wird die Anwendung in der Lage versetzt, darauf geeignet zu reagieren (Bild S8).
    Um die zeitliche Abfolge derartiger Ereignisse (Events) auch dann noch aufrecht erhalten zu können, wenn entweder der Server oder ein Client stark ausgelastet sind, werden diese gemäß Bild S9 zunächst immer in Warteschlangen (Eventqueues) eingereiht [U14].

    Bild S9: Eventqueues

    Zur Erleichterung der Handhabung solcher Grafikaufgaben sind basierend auf dem Leistungsumfang der Xlib die X- Toolkit Intrinsics (Xt) errichtet worden. Diese Bibliothek stellt Funktionen bereit, mit denen häufig vorkommende Verwaltungsaufgaben komfortabler erledigt werden können. Das Toolkit ist intern objektorientiert realisiert worden, auch wenn die Intrinsics-aufrufe nicht objektorientiert erscheinen. Es existieren Objekte, Methoden, Nachrichten, Klassen und Instanzen, sowie Codekapselung [U15]. Die sogenannten Widgets sind Objekte, die dem Applikationsprogrammierer den größten Teil der X-Protokoll- Behandlung abnehmen. Die Applikation sendet Nachrichten an das Widget, das wiederum - vom Programmierer nicht beeinflußbar - die Kommunikation mit dem Xserver übernimmt. Will die Applikation - wie oben als Beispiel gewählt - auf ein Mausereignis reagieren können, muß sie einen Callback registrieren, also eine Prozedur der Applikation, die dann vom Widget aktiviert wird, wenn das betreffende Ereignis eingetroffen ist.
    Bild S10 verdeutlicht, wie die typische Hauptwarteschleife ereignisorientiert arbeitender Applikationen unter dem X-Toolkit realisiert ist. Die Xlib stellt dabei in erster Linie die Funktion XNextEvent bereit, mit deren Hilfe in der Eventqueue des Clients nachgesehen wird, ob Ereignisse aufgelaufen sind. Ist dies der Fall, liefert sie das älteste Ereignis zurück und entfernt es aus der Queue, ansonsten wartet sie auf das Eintreffen eines Events. Durch das Socket-Interfacing des Betriebssystems bedingt wird der Applikationsprozeß in dieser Zeit schlafengelegt (sleep), damit die CPU anderen Prozessen zur Verfügung stehen kann.

    Bild S10: Ereignisabarbeitung bei den Xt-Intrinsics mittels Callbacks

    Diese Widgets sind also nicht mit Fenstern und deren Verwaltungsdaten gleichzusetzen. Im Gegenteil, sie bestehen programmiertechnisch betrachtet größtenteils aus Methoden, also Funktionen. Diese sind wiederum zu einer Bibliothek zusammengebunden. Das ursprüngliche Projekt Athena wurde mit dem Athena-Widget-Set vervollständigt. Mit ihnen ist beispielsweise das xterm-Programm realisiert worden, auf das weiter unten noch näher eingegangen werden wird. Andererseits hat die Open Software Foundation (OSF) eine eigene Widget-Bibliothek (Xm) realisiert, das OSF/Motif Widget-Set. Ziel war hier, ein Look&Feel zu erzielen, das die in ihrer grafischen Präsentation wenig ansprechenden Athena-Widgets ersetzt und eine Bedienung ähnlich den von Microsoft für Personal-Computer entwickelten MS-Windows ermöglicht. Dabei sollte erreicht werden, daß ein Benutzer unabhängig von seinem jeweiligen Rechnerarbeitsplatz, eine zumindestens intuitiv einheitliche Bedienbarkeit vorfindet [U4]. Bild S11 verdeutlicht die Softwarearchitektur einer X-Windows-Applikation.

    Bild S11: Softwarearchitektur Xt-Intrinsics basierter Anwendungen

    Grafische Anwendungen werden über eine Vielzahl von Größen beschrieben. Ein Druckknopf (PushButton) hat eine Ausdehnung, eine Lage relativ zum Elternfenster, auf dem er angeordnet ist, eine Hintergrundfarbe und eine Aufschrift, um nur einige wesentliche Merkmale zu nennen. Unter dem X- Window-System steht nicht nur die Möglichkeit zur Verfügung, im Quelltext der Applikation zu verankern, mit welchen Werten diese Merkmale zu belegen sind. Diese Vorgehensweise heißt Festschreiben (hardcoding). Zunächst bietet der objektorientierte Ansatz des Toolkits die Möglichkeit, Vorgabewerte für Widgets zu vergeben, die auch an Kindwidgets weitervererbt werden können. Danach wird bei jeder Erzeugung eines Widgets der X-Resource-Manager (Xrm) bemüht. Er sucht an unterschiedlichen Orten mit steigender Priorität nach sogenannten Xresourcen. Diese können in speziellen Dateien (teilweise nur mit Supervisorberechtigung beschreibbar, teilweise benutzerindividuell) bereitgestellt sein, vom Xserver erfragt oder über die Kommandozeile des Prozesses eingegeben werden.
    Die höchste Priorität hat natürlich das Festschreiben, weil es jede Vorbelegung überschreibt. Vorteil dieses zusätzlichen Managers ist, daß beispielsweise in einer Applikation, die üblicherweise nur die notwendigsten Merkmalswerte festschreibt, wie beispielsweise die Zeiger auf Callbackfunktionen, auch bei ausschließlichem Vorliegen des ausführbaren Programms Eigenschaften wie die Hintergrundfarbe nachträglich geändert werden können. Das mit den Athena-Widgets realisierte xterm präsentiert sich beispielsweise typischerweise weiß mit schwarzer Schrift, kann aber leicht auf grünblau mit gelber Schrift gesetzt werden. Dazu sind nur an geeigneter Stelle Xresource- Dateien zu verändern. Damit ließen sich beispielsweise die Texte eines Pulldownmenüs benutzerabhängig in englisch und einmal in französisch erstellen. Die Applikation selbst wird davon nicht beeinträchtigt [U4, U14, U15].
    Schließlich ist unter X im InterClient-Communication- Conventions-Manual (ICCCM) genau geregelt, wie Clienten miteinander kommunizieren können. Beispielsweise geschieht das Drag&Drop dadurch, daß eine Anwendung A eine Selektion erstellt, die in einen Puffer des Xservers gelangt. Von dort kann die Applikation B diese Information wieder abholen, sobald geklärt ist, daß sie diese auch bekommen soll [U4, U14, U15].
    Der wohl wichtigste Client einer X-Windows Sitzung ist der Window-Manager. Dieser nutzt die Festlegungen des ICCCM, um die Platzierung der Fenster der einzelnen Anwendungen zu beeinflussen. Ohne ihn würden diese Fenster einmal bei der Kreierung plaziert und könnten dann bis zu ihrem Ende beispielsweise nicht mehr vergrößert, verschoben, im Fensterstack ganz nach oben verlegt oder zu einem kleinen Icon-Fensterchen verwandelt werden. Unter OSF/Motif ist der Motif-Window-Manager (mwm) realisiert worden. Dieser arbeitet nach dem Reparenting-Prinzip, denn er zeichnet um die Fenster der von ihm verwalteten Clients einen Rahmen [U15].
    Der Vollständigkeit halber sei erwähnt, daß es weitere spezielle Kommunikationsformen gibt, wie beispielsweise das X-Display-Manager Control Protocol (XDMCP). Hiermit steuert ein spezieller Client, der X-Display-Manager (xdm), die Entriegelung eines grafischen Arbeitsplatzes, nachdem sich der Benutzer ordnungsgemäß angemeldet (authentifiziert) hat. Dies geschieht üblicherweise mit Hilfe seines Benutzernamens und Passworts. Um anderen Clienten die Überwachung dieses Login-Vorgangs zu verwehren, wird in dieser Zeit die Kommunikation anderer Clienten mit dem Xserver verweigert.

    2.5 Auflösung des Konflikts sequentieller mit ereignisorientierter Programmierung am Beispiel der laboreigenen Liniengrafik xgrf3

    Bereits seit 1981 steht am Labor für elektrische Maschinen und Antriebe ein Programmpaket zur Schaltungssimulation zur Verfügung, das damals auf einem MODCOMP II Prozeßrechner lauffähig war. Für grafische Ausgaben wurde ein HP 7221-Plotter verwendet. Eigene in FORTRAN geschriebene Funktionenbibliotheken standen zur Verfügung, um den Plotter ansprechen zu können. Diese ermöglichten es dem Simulationsprogramm, zweiachsige Diagramme mit beschrifteten Koordinatensystemen und wahlweise gestrichelten Kurvenverläufen zu erstellen. Im Rahmen einer am Lehrstuhl durchgeführten Untersuchung über Störströme im Bahnnetz, ausgelöst durch pulsstromrichterbetriebene Bahnfahrzeuge [G1], wurde die Grafik um die Möglichkeit erweitert, dreiachsige Diagramme mit einer gekrümmten Fläche zu erstellen. Dies wurde unter Berücksichtigung von Teilverdeckungen bei der zweidimensionalen Darstellung räumlich tiefer Szenen erreicht. 1988 ist diese Grafik im Rahmen der Anschlußarbeit [G2] zunächst in die Programmiersprache C überführt worden und war auf PCs mit Hercules-Grafik lauffähig. Diese Version erhielt den internen Namen grf2. Mittlerweile steht sie als grf3 zur Verfügung. Sie unterstützt nunmehr unterschiedliche Ausgabegeräte, zwischen denen gewählt werden kann. Neben dem HP 7221 können beliebige HPGL-fähige Plotter angesteuert werden. Die Bildschirmausgabe erfolgt farbig auf SVGA-Monitoren. Schließlich können Ausgabedateien für HPGL, EPS (encapsulated PostScript) und TEX erstellt werden. Ein Zusatzprogramm kann HPGL-Dateien einlesen und in eines dieser Ausgabegeräte umlenken. Damit ist auch der HP 7221- Plotter HPGL-fähig geworden. Parallel war in der Version für Hercules-Grafik unter Zuhilfenahme einer Maustreiber- Bibliothek Interaktivität erreicht worden. Damit ließ sich beispielsweise in HPGL-Plots hineinzoomen.
    Mit der Beschaffung erster Apollo-Workstations ist eine ähnlich leistungsfähige Liniengrafik unter Nutzung der Apollo-eigenen Grafikroutinen (GPR) erstellt worden. Mit dem Wechsel zum X Window System im Zusammenhang mit der Beschaffung der ersten Sparc-Workstation ist erstmalig bei dem Bildschirmausgabegerät das Verdeckungsproblem durch die Mehrfenstertechnik hinzugekommen. Bislang wurde bei grafischen Ausgaben das Display immer ausschließlich genutzt. Die X-Windows Version dieser Grafik (xgrf3) stellt ebenfalls die Maus-Bibliothek zur Verfügung, die derzeit in der SVGA-Version noch fehlt.
    Die Simulationssoftware ist in den vergangenen Jahren ebenfalls nach C umgeschrieben und weiterentwickelt worden und steht heute als SISABI auf PCs und Workstations gleichermaßen zur Verfügung. SISABI nutzt für seine Ausgaben die grf3-Grafik. Derartige Simulationsprogramme sind typische Beispiele für sequentielle Programmierung. Das Programm startet und liest zunächst eine Datei ein, in der die zu simulierende Schaltung beschrieben wird. Diese Informationen werden in die internen Systemmatrizen überführt. Schließlich wird für ein vorgegebenes Zeitintervall durch Lösen des Differentialgleichungssystems der neue Zustandsvektor berechnet. Die Ergebnisse werden dann Größe für Größe in jeweils eigenen Diagrammen ausgegeben, indem vom letzten Wert zum aktuellen eine gerade Linie gezeichnet wird. Danach wird das Gleichungssystem erneut gelöst und wieder die Ergebnisse dargestellt, bis die Simulation beendet ist. Das Programm rechnet also die meiste Zeit, wartet zu keinem Zeitpunkt auf eine Benutzerinteraktion und zeichnet nur zu bestimmten Zeitpunkten. Regelmäßige Unterbrechungen und das Verharren in einer Ereigniswarteschleife sind hier nicht vorgesehen. Außer unter X ist bei dieser grafischen Anwendung kein ereignisorientierter Programmierstil notwendig.
    Das Fenstersystem X läßt beispielsweise zu, daß sich die Fenster auf einem Display wechselseitig verdecken oder daß das Ausgabefenster der Liniengrafik iconifiziert wird. Wenn verdeckte Fensterbereiche wieder sichtbar werden, sendet der Xserver dem Programm ein Expose-Event, in dem er die Region mitteilt, die der Client zu restaurieren hat. Dies ist ohne eine Veränderung der Quelltexte von SISABI nicht möglich. Andere verfügbare Programme, wie gnuplot [G3], lassen beispielsweise ein Vergrößern oder Verkleinern des Grafikfensters zu. Bei jeder Veränderung wird allerdings der Bildschirm gelöscht. Die alten Informationen gehen verloren.
    Für xgrf3 (Bild S12) ist ein anderer Weg eingeschlagen worden. Das Verdeckungsproblem wird dadurch gelöst, daß zunächst die Größe der bezeichenbaren Fläche (Drawable) festgelegt worden ist. Soll beispielsweise eine Linie gezeichnet werden, geschieht dies zunächst in einer identischen, unsichtbaren Struktur (Pixmap). Dann wird künstlich ein Expose-Event ausgelöst, das den geänderten Bereich umfaßt. Bei jedem Expose-Event werden die entsprechenden Inhalte der Hintergrundpixmap in die Drawable kopiert. Das Vorgehen setzt eine Ereignisorientierung voraus.

    Bild S12: Erscheinungsbild der laboreigenen xgrf3-Liniengrafik

    Dieser Konflikt der notwendigen Koexistenz der sequentiellen und der ereignisorientierten Programmierung wird dadurch gelöst, daß diese unterschiedlichen Aufgaben zwei Prozessen anvertraut werden. Einer ist für die Simulationsaufgaben zuständig, der andere für die grafische Präsentation. Beide kommunizieren aus Geschwindigkeitsgründen miteinander mittels sharable Memory (SHM) und bestimmter Signale.
    Die grf3-Grafik besteht aus abstrakteren Bibliothekseinsprungfunktionen und den für den Anwendungsprogrammierer unsichtbaren hardwarenahen Grafikprimitiven. Die xgrf3-Änderungen sind ausschließlich bei den Primitiven vorgenommen worden. Im Falle der Display- Vffnung wird zunächst ein SHM-Bereich angefordert und darin zwei Ringpuffer (FIFOs) zum bidirektionalen Datenaustausch eingerichtet. Danach wird der xgrf3d-Server als ein Kind der Anwendung abgespaltet (fork/exec). Über die Kommandozeile wird ihm die SHM-Identifizierungsnummer mitgegeben. Mittels dieser kann auch er den SHM-Bereich öffnen. In die server-client-seitige FIFO schreibt er eine Bereitschaftsmeldung und wartet dann an der client-server- seitigen FIFO auf Kommandos. Währenddessen kann er auch Expose-Events und dergleichen behandeln. Im wesentlichen ist nur die Eröffnungssequenz synchronisiert. Alle anderen Teile des Protokolls sind - wie das X-Protokoll - asynchron, um zeitgünstiger zu werden. Es werden also keine Ausführungsbestätigungen vom xgrf3d zurückgesandt (Bild S13). Wichtig ist das korrekte Abmelden des SHM-Bereichs. Wenn beispielsweise die Applikation unerwartet terminiert, muß auch der xgrf3d dies mitbekommen. Hierfür werden Signale eingesetzt.

    Bild S13: Interprozeßkommunikation bei der xgrf3-Liniengrafik

    Weiterhin ist in xgrf3 die Fähigkeit realisiert worden, Mausereignisse in der Grafik zuzulassen. Die Anwendung kann die Maus ein- und ausschalten und zwischen 5 Mauszeigerformen wählen. Sie kann den Zustand der Maus durch periodisches Abfragen (polling) oder mittels Interrupts ermitteln. Dazu steht ein Bereich des SHM zur Verfügung, der aktuelle Informationen über die Lage der Maus enthält und darüber, welche Knöpfe gedrückt sind. Zusätzlich können die Einsprungadressen von "Interruptservice"-Routinen durch die Anwendung angemeldet werden. Ein bestimmtes Signal wird dann vom xgrf3d an seinen Elternprozeß gesandt. Dort wird ein spezieller Signalhandler angesprungen, der wiederum die entsprechende Anwendungsroutine aufruft.
    Schließlich ist zu bemerken, daß es zu Performanceproblemen kommen kann, wenn grafikintensive, rechenzeitarme Aufgaben durchzuführen sind. Dann treffen mehr Zeichenkommandos von der Anwendung beim xgrf3d ein, als er in X-Protokoll-Sequenzen umwandeln und an den Xserver weiterleiten kann. Die Grafikprimitive legen mittels usleep() die Applikation kurzzeitig schlafen und prüfen in Abständen, wann die FIFO wieder Befehle aufnehmen kann. Der xgrf3d seinerseits prüft den Füllstand seiner ausgangsseitigen Eventqueue zum Xserver hin, um festzustellen, wann er mit dem weiteren Interpretieren der anwendungsseitigen Kommandos aufhören muß.

    2.6 Das Terminalemulationsprogramm xterm

    Mit dem Erscheinen des X Window Systems stand zwar ein grafisches Fenstersystem für UNIX-Workstations zur Verfügung. Außer den wenigen Dienstprogrammen der X-Windows Distribution existierten aber noch keine grafischen Anwendungen. Unter UNIX stehen viele kleine Dienstprogramme bereit, die sehr spezialisiert sind und größtenteils nur ein-/ausgabestrom-orientiert arbeiten, wie grep, awk und sort [U19]. Es existieren aber auch maskenorientierte Programme, die unter Nutzung der wahlfreien Positionierung von Zeichen auf dem Display von Text-Terminals bereits ein ansprechendes Maß an Interaktivität und Benutzerführung bereitstellen, wie das Electronic-Mail Frontend elm. Zur Gewährleistung der Akzeptanz des Fenstersystems war es daher die vordringlichste Aufgabe, ein Programm bereitzustellen, das die zu diesem Zeitpunkt üblichen Text- Terminals emuliert. Nur so konnten die vorhandenen Programme weitergenutzt werden, bis grafische Alternativen verfügbar waren.
    Das Terminalemulationsprogramm xterm war demgemäß das erste wichtige Programm der X-Windows Distribution. Mit diesem wurde sogar bis einschließlich X11R3 die Sitzungseröffnung abgewickelt, bis es vom xdm abgelöst wurde. Das xterm kann ein DEC VT 102 und ein Tektronix-4014- Terminal emulieren. Dies geschieht unter Nutzung von Pseudo- Teletypes. Im allgemeinen wird eine Sitzung an einem xterm ähnlich ablaufen wie an einem Text-Terminal. Zunächst wird das xterm gestartet. Dieses initialisiert zunächst seine Grafik, öffnet danach ein pty/tty-Paar und spaltet danach einen Nutzprozeß ab. Im allgemeinen handelt es sich dabei um einen Kommandozeileninterpreter.
    Der nutzende Prozeß arbeitet auf dem UNIX-Gerät /dev/ttyXY in einer Weise, daß er keinerlei Unterschiede feststellen kann. Die Funktion isatty() beispielsweise prüft, ob die Ausgabe in eine Datei umgelenkt ist, oder ob eine interaktive Sitzung am Text-Terminal läuft. Auf der anderen Seite der FIFO (/dev/ptyXY) sitzt der Emulationsprozeß. Dieser plaziert ankommende Zeichen im Bereich seines Grafikfensters und interpretiert Steuersequenzen im Sinne der Leistungsfestlegungen der emulierten Standards. Beispielsweise bedeutet im VT 102 Modus die Steuersequenz "ESC [ 2 J", daß das gesamte Textausgabefenster gelöscht werden soll [U3].

    Bild S14: Mensch-Maschine-Kommunikation bei einem xterm

    Tastatureingaben des Benutzers werden vom Xserver registriert und Keyboard-Events an das xterm weitergereicht. Dieses interpretiert die Tastaturcodes und sendet sie als geeignete ASCII-Zeichen (American Standard Code for Information Interchange) über die bidirektionale FIFO an den nutzenden Prozeß. Auch hier kann eine Uminterpretierung erfolgen. Beispielsweise wird mit der Benutzereingabe Ctrl-Z erreicht, daß das xterm das Signal SIGSTOP an den nutzenden Prozeß sendet. Mittels des Mauszeigers können Selektionen markiert werden, um möglicherweise Ausgabetexte aus einem xterm in ein anderes zu kopieren. Es können aber auch Popup-Menüs erscheinen, mit denen die Einstellungen des xterm-Prozesses interaktiv verändert werden können. Bild S14 verdeutlicht die gegenüber Bild S2 abgewandelte Textein- und -ausgabe beim xterm.

    2.7 Notwendigkeit preemptiven Multitaskings zur Vermeidung der Reimplementierung der Inferenzmaschine von Babylon-2

    Neben dem xterm nutzen auch andere Programme die Möglichkeiten der Pseudo-Teletypes. Das interaktive Debugging-Werkzeug dbx erleichtert die Programmentwicklung. Unter X steht zusätzlich das grafische Frontend xdbx zur Verfügung [U11]. Das Programm dbx arbeitet normalerweise auf einem Text-Terminal oder kann in einem Batch-Modus Befehle von einer Eingabedatei lesen und Ergebnisse in eine Ausgabedatei schreiben. Mittels der Funktion isatty() stellt es fest, ob seine Eingaben von einem Teletype oder aus einer Datei kommen. Bei Dateien ist das Programm zu beenden, sobald das Dateiende erreicht ist. Bei einem Teletype ist beim Ausbleiben weiterer Zeichen eine Eingabeaufforderung (Prompt) zu schreiben und auf Benutzereingaben zu warten.
    Unter X wird dbx an einem Pseudo-Teletype betrieben, an dessen anderem Ende xdbx die Ausgaben von dbx in unterschiedliche Fenster leitet. Mausklicks in diesen Fenstern bewirken das Absetzen von Kommandos über die FIFO an den dbx-Prozeß, die sonst mit der Hand hätten eingegeben werden müssen. Zusätzlich steht in einem Fenster des xdbx die Klartextinformation für den Benutzer nachvollziehbar bereit. Über ein Texteingabefeld kann er auch weiterhin dbx- Kommandos mit der Tastatur eingeben.

    Es kann festgehalten werden, daß die Nachrüstung grafischer Frontends für bereits existierende Prozesse mittels Pseudo-Teletypes ermöglicht werden kann. Der Aufwand bei der Erstellung einer grafischen Anwendung reduziert sich hierbei auf die Oberflächengestaltung. Eine komplette Reimplementierung des Leistungsumfangs kann unterbleiben. Die Funktion isatty(), die von derartigen existierenden Programmen oft genutzt wird, um die Notwendigkeit interaktiver Arbeitsweise festzustellen, kann "überlistet" werden. Bei derartigen Lösungen handelt es sich - wie bei der Liniengrafik xgrf3 - um Zwei-Prozeß-Lösungen.

    Zur Lösung der hier vorliegenden Aufgabe, eine in der Programmiersprache LISP realisierte Expertensystemschale unter Vermeidung einer kompletten Reimplementierung um Grafikfähigkeit zu erweitern, sind zunächst die Möglichkeiten der beteiligten LISP-Welt zu betrachten.
    LISP ist eine interpretative Sprache. Die Sitzungen verlaufen im allgemeinen interaktiv. Der LISP-Interpreter wird gestartet, initialisiert sich und meldet seine Eingabebereitschaft durch Schreiben einer Eingabeaufforderung (Prompt) in den Standardausgabekanal. Danach wartet er auf Eingaben von LISP-Konstrukten seitens des Benutzers über den Standardeingabekanal. Diese werden eingelesen (read), ausgeführt (evaluiert). Schließlich wird das Ergebnis der Operation in die Standardausgabe geschrieben (print). Abschließend schreibt er wieder den Prompt und wartet erneut. Diese Hauptschleife des Interpreters (toplevel loop) wird auch als read-eval-print- loop bezeichnet. Ihr Leistungsumfang ist in CLtL1 und CLtL2 unterschiedlich definiert worden.
    Es ist auch möglich, LISP-Sitzungen im Batch-Betrieb durchzuführen. Dazu werden im allgemeinen der Standardein- und Standardausgabestrom in Dateien umgelenkt. Analog dem oben beschriebenen Verhalten des dbx muß ein Ausbleiben weiterer Zeichen am Eingabekanal den LISP-Prozeß beenden. Andererseits sollten die Ergebnisse, die in die Ausgabedatei geschrieben werden, nicht die Promptsequenzen enthalten. Die meisten LISP-Interpreter für UNIX-Systeme prüfen daher, ob ihr Standardeingabekanal ein Gerät (Teletype) oder eine Datei ist. Es reicht daher beispielsweise nicht, eine unnamed pipe als Interprozeßkommunikationskanal zu verwenden, weil diese als eine Datei erkannt würde. Die Verwendung von Pseudo- Teletypes ist notwendig, weil diese als Geräte gelten. Da das zu erarbeitende Konzept herstellerunabhängig sein soll, reicht es auch nicht, beispielsweise nur einen bestimmten LISP-Anbieter zu bevorzugen, der eventuell keine derartige Geräte-Prüfung vornimmt.
    Die LISP-Quelltexte von Babylon 2.3 sind so entwickelt worden, daß sie nur die Präsentationsmöglichkeiten der Ein- /Ausgabeströme nutzen. Es liegt also eine sequentielle Programmabarbeitung gemäß Bild S4 vor. Die größere Anzahl von Ereignistypen bei der Mehrfenstertechnik würde die Bearbeitung asynchron auftretender Ereignisse notwendig machen. Solange die Schale auf Benutzereingaben wartet, wäre dies sicherlich kein Problem. Bei einem Problemlösungsvorgang von mehreren Minuten kann eine Reaktion erst im Anschluß erfolgen, was die Benutzerfreundlichkeit und damit den Sinn einer grafischen Oberfläche ad absurdum führen würde. Die Abarbeitung einer ereignisorientierten Applikation geschieht in polling- Betriebsart gemäß Bild S5. Das heißt, es werden keine Signale oder Interrupts ausgelöst, auf die die Applikation reagieren könnte. Für diese Arbeitsweise müßte die Inferenzmaschine umgestaltet werden. Beispielsweise könnte nach jeder Regelprüfung einmal die Eventqueue überprüft werden. Dies setzt aber eine detailierte Einarbeitung in die internen Funktionsprinzipien der Schale voraus. Weiterhin wäre bei jedem Releasewechsel, beispielsweise von Babylon 2.2 nach Babylon 2.3, damit zu rechnen, daß ein großer Teil der investierten Arbeit überholt wäre.
    Der andere Weg ist, eine Zwei-Prozeß-Lösung im Sinne des xterm zu erstellen. Dadurch kann die Inferenzmaschine unverändert bleiben. Es werden nur Erweiterungen hinsichtlich der grafischen Ein- und Ausgaben notwendig. Eine Meldung im Zuge des Inferenzprozesses kann dadurch geschehen, daß über den Standardausgabekanal von LISP eine Nachricht an den Grafikprozeß ergeht, eine entsprechende Meldung zu produzieren. LISP wartet dann, bis der Grafikprozeß in seine Standardeingabe die Antwort des Benutzers zurückgibt. Von zwischenzeitlich auftretenden Events bleibt LISP verschont. Der Grafikprozeß handhabt sie geeignet.

    Durch die Zwei-Prozeß-Lösung kann die sequentielle Programmabarbeitung der Expertensystemschale aufrechterhalten werden.

    In einer MS-Windows Umgebung können im Rechner mehrere Prozesse parallel existieren. Aufgrund des dort verwendeten kooperativen Multitaskings ist es aber notwendig, daß jeder Prozeß nach einer gewissen Zeit selbst bereit ist, die Kontrolle über die CPU abzugeben und den anderen Prozessen zur Verfügung zu stellen. Wenn der LISP-Prozeß ein größeres Problem löst, sind - wie bereits beschrieben - derartige Unterbrechungen nicht vorgesehen. Dies setzt ein preemptives Multitasking voraus, bei dem der einzelne Prozeß die Zuteilung zur CPU weder merkt noch beeinflussen kann. Eine übergeordnete Instanz - der Scheduler - sorgt für die pseudo-parallele Abarbeitung mehrerer Prozesse. Betriebssysteme wie OS/2 von IBM oder Windows95 von Microsoft unterstützen preemptives Multitasking. Sie verfügen aber nicht über Pseudo-Teletypes.

    Die angestrebte Zwei-Prozeß-Lösung benötigt ein preemptives Multitasking-Betriebssystem, das Pseudo-Teletypes zur Verfügung stellt.


    Das Betriebssystem UNIX stellt alle genannten Voraussetzungen bereit. Es ist für eine große Zahl unterschiedlicher Hardwareplattformen einschließlich PCs verfügbar. Die Vorgabe, eine auf möglichst vielen Rechnerumgebungen verfügbare Software zu erstellen, ist also ausreichend erfüllt.

    3. Die Schale EMA-XPS v1

    Nach den Vorgaben des einleitend erwähnten FVA- Forschungsvorhabens sollte mit vertretbarem Aufwand eine im Quelltext verfügbare, leicht portierbare Schale erstellt werden. Um die Neuentwicklung einer leistungsfähigen großen, hybriden Expertensystemschale zu vermeiden, sollten bestehende Quelltexte nur in geringem Maße erweitert werden müssen. Die Wahl fiel auf die Schale Babylon-2.

    3.1 Modularer Aufbau der Schale Babylon-2

    Die hybride Expertensystemschale Babylon-2 zeichnet sich - bedingt durch eine durchgehend objektorientierte Programmierung - darin aus, daß Interpretermodule unterschiedlicher Leistungsfähigkeit miteinander verschaltet werden können. Die Leistungsfähigkeit jedes einzelnen Expertensystems kann an den Leistungsbedarf der zugehörigen Wissensbasis angepaßt werden. Für jeden Wissensrepräsentationsformalismus steht ein eigener spezialisierter Wissensinterpreter zur Verfügung. Dabei handelt es sich um Frame-, Regel-, Constraint- und Prologinterpreter. Jeder dieser Interpreter steht in drei Ausbaustufen zur Verfügung. Die "Basic"-Variante stellt alle Grundfunktionalität zur Verfügung, die zum uneingeschränkten Betrieb notwendig sind. In den darauf aufbauenden Varianten "Mini" und schließlich "Normal" kommen Tracer- und Erklärungsmöglichkeiten hinzu. Über den von EMA-XPS genutzten Leitungsumfang von Babylon-2 hinaus steht noch ein Freitextinterpreter zur Verfügung. Ein definierter Zugang zum sequentiell arbeitenden LISP- Bereich, der den Aufruf von LISP-Funktionen beispielsweise aus Regeln heraus ermöglicht, kann zugeschaltet werden. Schließlich existieren Module für die Mensch-Maschine-Kommu nikation.
    Diesen spezialisierten Einzelinterpretern ist als überlagerte Kontroll- und Koordinationsinstanz der sogenannte Metainterpreter vorgesehen. Er kontrolliert den globalen Sitzungsablauf und verweist die einzelnen Anweisungen zur Behandlung an die jeweiligen Wissensinterpreter. Diese können - aufgrund des hybriden Ansatzes - bei der Bearbeitung wiederum auf Anweisungen stoßen, die ihnen fremd sind. Sie geben die betreffenden Teilanweisungen an den Metainterpreter zur geeigneten anderweitigen Zuweisung zurück und erhalten das benötigte Ergebnis der Interpretation später vom Metainterpreter, um die begonnene Teilaufgabe fortführen zu können. Daher genügt es, wenn jeder spezialisierte Interpreter mit dem Metainterpreter kommunizieren kann. Von der Existenz der anderen Spezialisten erfährt er nichts. Bild S15 verdeutlicht die Architektur von Babylon-2 [S2, S3].

    Bild S15: Die hybride Architektur von Babylon-2

    3.2 Mensch-Maschine-Schnittstelle von Babylon-2

    Babylon-2 bietet neben den Wissensinterpretern auch ein Modul für die Mensch-Maschine-Kommunikation an. Dieses existiert ebenfalls in drei Ausprägungen. Das Basic- Interface-Mixin stellt die elementaren Ein- und Ausgabeoperationen zur Verfügung. Sämtliche Kommunikation wird hierüber abgewickelt. Weiterhin wird zwischen unterschiedlichen logischen Ausgabeströmen unterschieden, die aber standardmäßig auf den *terminal-io* Strom, den Standardausgabekanal umgelenkt und zusammengefaßt sind.
    Dementsprechend existieren neben den weiterhin verfügbaren LISP Standardein- und Standardausgabekanal der ebenfalls bidirektionale Sitzungs-Dialog-Strom von Babylon- 2 sowie die jeweils reinen Ausgabekanäle für Erklärungen, die Trace-Informationen des Regel-, Prolog-, Constraint- und Metainterpreters.
    Das Mini-Interface-Mixin stellt - basierend auf dem Modell der Ein-und Ausgabeströme - die Möglichkeit zur Verfügung, Operationen über ein Menü auszuwählen.
    Das Normal-Interface-Mixin ist derzeit nur in der Apple Macintosh Version unter Allegro CommonLISP verfügbar. Es verwendet mehrere Textfenster, um die Informationen der Ausgabeströme geeignet darstellen zu können, und Auswahldialoge für die Systemeinstellungen und Benutzereingaben. Diese Lösung ist nicht portabel. Weiterhin entsprechen die grafischen Möglichkeiten der Macintosh Version nicht der Forderung, für jede Wissensbasis eine individuelle grafische Endbenutzerschnittstelle zu generieren [S2, S3].

    3.3 Interprozeß-Kommunikation

    Die erste Version der grafischen Expertensystemschale EMA-XPS wurde auf ApolloDomain Workstations unter dem dort erhältlichen CLtL1 kompatiblen LISP-Interpreter Lucid CommonLISP entwickelt. Diese Version des Interpreters unterscheidet nicht zwischen interaktiver Sitzung und Batch- Betrieb. Der Prompt erscheint immer. Daher war zu diesem Zeitpunkt die allgemeine Notwendigkeit des Einsatzes eines Pseudo-Teletype-Geräts noch nicht erkannt worden. Vielmehr stand die grundsätzliche Konzeptfindung im Vordergrund der Arbeiten. Bild S16 verdeutlicht den Initialisierungsvorgang der beiden Prozesse von EMA-XPS.
    Ähnlich der Bootphase bei der Liniengrafik xgrf3 werden zunächst von dem in C geschriebenen Grafik-Server-Prozeß die Interprozeßkommunikationskanäle gemäß Tabelle S3 eingerichtet. So kann gewährleistet werden, daß alle Informationen inhaltlich getrennt auf der C-Seite verfügbar sind. Dies entspricht den Möglichkeiten von Babylon-2, kontextbezogen Ausgaben auf unterschiedlichen Strömen auszugeben. Im Anschluß baut der Grafikserver die Verbindung zum Xserver auf und etabliert unter Zuhilfenahme der Xt Intrinsics Funktion XtAddInputHandler für alle lesenden Enden der Pipelines C-seitig Funktionen, die diese Pipes leeren, die Inhalte interpretieren und umsetzen. XtAddInputHandler sorgt dafür, daß die Ereignishauptschleife auch das Vorhandensein von Zeichen prüft und gegebenenfalls - ähnlich den Callbacks - diese Handler startet.
    Schließlich wird mittels fork ein Kindprozeß erzeugt, der zunächst seine Standardeingabe und -ausgabe in die jeweils anderen Enden der Toplevel-Pipe umlenkt. Der Prozeß wird mit exec durch den LISP-Interpreter ersetzt.

    C-Seite
    Name der Pipe
    Richtung
    Handler
    LISP-Seite
    Name des Stroms
    Verwendung
    Toplevel-Pipe <==>
    (1)
    *terminal-io* Standardein-/ausgabe über den Debugger PAD
    Graphic-Pipe <==>
    (2)
    *graphic-stream* Anweisungen zur Erstellung von Popupdialogen
    Dialog-Pipe <==>
    (3)
    *dialog-stream* Sitzungs PAD
    Explain-Pipe <==
    (3)
    *explain-stream* PAD für Erklärungen
    RuleT-Pipe <==
    (3)
    *rule-stream* PAD für die Ausgabe des Regel-Trace
    PrologT-Pipe <==
    (3)
    *prolog-stream* PAD für die Ausgabe des Prolog-Trace
    ConsatT-Pipe <==
    (3)
    *consat-stream* PAD für die Ausgabe des Consat-Trace
    SystemT-Pipe <==
    (3)
    *system-stream* PAD für die Ausgabe des System-Trace
    wobei
    (1) toplevelPipeInputHandler()
    (2) graphicPipeInputHandler()
    (3) readPipe()

    Tabelle S3: Interprozeßkommunikationskanäle von EMA-XPS v1

    Der LISP-Prozeß kann nicht feststellen, daß er aus einer Pipeline liest und in sie schreibt und damit keinen Zugang zu dem Terminal hat, von dem der Grafikserver gestartet worden ist. LISP kann nur noch über diesen Prozeß mit dem Benutzer in Verbindung treten. Die LISP-Welt ist so angelegt, daß sie beim Start bereits den vollständigen Leistungsumfang der Schale Babylon-2 enthält. Der Grafikserver schreibt danach in die Toplevel-Pipe Lisp- Kommandos, wie es im interaktiven Modus der Benutzer getan hätte. Dadurch werden die Dateien nachgeladen, die die grafischen Ergänzungen der Babylon-2-Welt beinhalten. Auf diesem Wege wird die Interprozeßkommunikation auch auf der LISP-Seite etabliert. Den Abschluß der Initialisierungsphase und die zeitliche Synchronisation mit dem LISP-Prozeß kontrolliert der C-Prozeß dadurch, daß er den String "endOfLispInit" in die Standardeingabe von LISP schreibt. Der read-eval-print-loop von LISP schreibt diese Konstante unverändert in die Standardausgabe zurück. Der toplevelPipeInputHandler des Grafikservers erkennt diese Textausgabe. Die Synchonisation ist damit erfolgt, denn der LISP-Prozeß bearbeitet diese Eingabe erst, nachdem er alle vorangegangen Eingaben abgearbeitet hat.

    Bild S16: Die Zwei-Prozeß-Lösung von EMA-XPS mit ihren unterschiedlichen Programmiermodellen

    In der ersten Testversion der Schale wurden alle diese Ausgaben zunächst in PAD-Fenster geleitet. Dabei handelt es sich um mehrzeilige rollbare Textausgabefenster, die - im Falle eines bidirektionalen Stroms - um ein einzeiliges Texteingabefenster erweitert sind.
    Bild S19 zeigt den Debugger PAD, der die Toplevel-Pipe, also die Standardein- und -ausgabe von LISP überwacht. Dargestellt ist die Bootphase. Interessant ist, daß die Kommandos, die der Server nach LISP schickt, nicht dargestellt sind. Nur die Antworten der LISP-Seite sind sichtbar. Da hier keine Pseudo-Teletypes verwendet worden sind, müßten Texteingaben vom Server selbst als Echo zusätzlich in das Textausgabefenster geschrieben werden.
    Auf unterster Ebene der Interprozeßkommunikation sind drei austauschbare Mechanismen getestet worden:
  • shared memory,
  • unnamed pipes und
  • named pipes.
    CommonLISP stellt keine Mechanismen zur Verfügung, bereits vor dem Start des Interpreters geöffnete Dateien zu lesen oder zu beschreiben, ohne sie erneut zu öffnen. LISP verwendet eine eigene Dateiverwaltung. Daher müssen alle Dateien, die unter LISP bearbeitet werden sollen, auch innerhalb dieser Interpretersitzung geöffnet werden. Daher mußte bei den Mechanismen shared memory und unnamed pipes auf das Lucid Foreign-Function-Interface zurückgegriffen werden, das eine Erweiterung des CLtL1-Standards darstellt.
    Dies ist nicht notwendig, wenn named pipes verwendet werden. Beim Erstellen derartiger Pipelines wird ein Eintrag in das Dateisystem vorgenommen. Der C-Prozeß übergibt diese Namen über die Toplevel-Pipe, die in allen drei Fällen als eine unnamed pipe ausgeführt war. LISP kann dann diese "Dateien" zum Lesen oder Erweitern öffnen.
    Bild S17 verdeutlicht die Implementierung der Interprozeßkommunikation an einer bidirektionalen Pipeline.
    Die reguläre Befehlseingabe geschieht dadurch, daß die Anweisungen der Reihe nach in die Standardeingabe von LISP geschrieben werden. Ein Sonderfall ergibt sich, wenn unter LISP ein Fehler auftritt. Dann soll nämlich der Debugger PAD in jedem Fall sichtbar werden, also im Fenster-Stack ganz nach vorne geholt und deikonifiziert werden. Dazu muß erkannt werden, wann der LISP-Interpreter den Debugger startet. Das offensichtlichste Kriterium ist der geänderte Prompttext. Er wechselt bei dem vorhandenen Lucid Interpreter von "> " nach "1. Break> ". Der toplevelPipeInputHandler prüft daher den ankommenden Zeichenstrom nicht nur hinsichtlich der Sequenz "endOfLisp Init", wie bereits beschrieben. Er leitet bei Erkennen einer Sequenz wie "\n%d. Break> " diese Sonderbehandlung ein. Alle anderen Texte werden in das Textausgabefenster des PADs kopiert. Dieses Vorgehen entspricht dem von readPipe. Dieser Handler ist auf die Mehrzahl der Kanäle registriert. Die zugehörigen PADs sind reine Ausgabefenster. Sie werden immer dann sichtbar gemacht, wenn eine Ausgabe über diesen Kanal erfolgt.

    Bild S17: Lesen und Beschreiben der Pipes

    In der Folgeversion von EMA-XPS wurden die Erweiterungen des Mini-Interface-Mixin berücksichtigt. Hierfür sind Popup-Dialoge bereitzustellen. Zusätzlich ist der *graphic-stream* eingeführt worden. Wenn Babylon-2 einen Auswahldialog erstellt, schreibt es eine Liste von Möglichkeiten auf den *dialog-stream*. Das modulare Programmiermodell von Babylon-2 ermöglicht die Ersetzung dieser Funktionalität. Anstelle der Ausgabe wird eine Protokollsequenz der Form

    Schlüsselwort%%Nachrichttext%%endeNachricht%%

    über den *graphic-stream* gesandt. Der C-Prozeß erzeugt einen geeigneten Popup-dialog mit den notwendigen Texteinträgen, die er der Protokollsequenz entnommen hat. LISP wartet mittels read auf eine geeignete Antwort. Nachdem der Benutzer seine Eingaben abgeschlossen hat, schließt der Grafikserver den Dialog und sendet eine Antwortsequenz in die Graphic-Pipe.

    3.4 Wechselnde Master/Slave Beziehung

    Der Begriff Client-Server-Lösung beschreibt die Zwei- Prozeß-Lösung nicht korrekt. Auch wenn aus der Sicht des LISP-Prozesses der C-Prozeß ihm die Grafikaufgaben abnimmt und damit als Server zur Verfügung steht, besteht zwischen den beiden Prozessen eher ein Master-Slave-Beziehung, weil einer auf die Anweisungen des anderen reagiert.
    Dieses Verhältnis kehrt sich aber wiederholt um. Während der Bootphase kontrolliert der C-Prozeß die LISP- Welt. Auch im Anschluß daran unterliegt der LISP-Prozeß der Kontrolle des Grafikservers. Er teilt LISP mit, ob der Benutzer eine Wissensbasis laden möchte oder ob er eine Sitzung starten will.
    Sobald aber die Sitzung läuft, geht die Gesamtkontrolle auf den LISP-Prozeß über. Dann entscheidet dieser, wann der C-Prozeß einen Popupdialog produziert und was in die unterschiedlichen PAD-Fenster zu schreiben ist. Erst mit dem Ende der Sitzung geht die Kontrolle zurück an den C- Prozeß. Um Fehlfunktionen zu vermeiden, ist daher darauf zu achten, daß der C-Prozeß, wenn er im Slave-Modus ist, keine Kommandos in die Toplevel-Pipe schreibt. LISP ist gerade beschäftigt und kann eher eine Benutzereingabe mittels eines read abfragen wollen, als daß es die Eingabe als ein LISP-Kommando auffaßt. Eine wechselseitige Verriegelung beider Prozesse empfiehlt sich.
    EMA-XPS stellt auch grafische Editoren zur Wissenseingabe zur Verfügung und ermöglicht ein abschließendes Speichern dieses Wissens in Wissensbasis- Dateien. Auch hierbei behält der C-Prozeß die Kontrolle. Er fordert beispielsweise alte Regeldefinitionen an, die LISP mit einer geeigneten Protokollsequenz über den *graphic- stream* beantwortet. Eine Quittierung des Empfangs der geänderten Regel durch die LISP-Welt ist nicht erforderlich. Im Unterschied dazu sendet LISP während einer Sitzung als Master eine Grafikanforderung, die die C-Seite mit der Benutzerreaktion quittiert (Bild S16).

    3.5 Grafisches Erscheinungsbild

    Aufbauend auf die beschreibene Interprozeß- Kommunikation ist eine rudimentäre Endbenutzerschnittstelle ähnlich einem PAD vorgesehen. Damit lassen sich textorientierte Sitzungen realisieren. Über einen zusätzlichen PushButton kann der Benutzer das Sitzungsende signalisieren. Dazu wird ein entsprechendes LISP-Kommando in die Toplevel-Pipe geschrieben, das das Abbauen des Sitzungsfensters bewirkt. LISP wertet es aber erst aus, wenn es wieder Eingaben annimmt, also nachdem es die Kontrolle an die C-Seite zurückgegeben hat. Dies ist im allgemeinen erst nach dem in der Wissensbasis vorgesehenen Sitzungsende der Fall.
    Weiterhin stehen spezialisierte grafische Editoren zur Wissenseingabe zur Verfügung. Pro Konstrukttyp ist ein eigenes Editorfenster realisiert. Bild S18 zeigt das Hauptfenster von EMA-XPS. Über das heruntergeklappte Menü können die einzelnen Editoren sichtbar gemacht werden, der LISP-Debugger beispielsweise für die manuelle Eingabe von LISP-Kommandos oder zur Kontrolle des Abarbeitungserfolgs hervorgeholt werden. Schließlich läßt sich eine Wissensbasis laden, speichern und starten.
    Zusätzlich kann über einen speziellen Knopf des Debugger PADs das UNIX-Signal SIGINT an den LISP-Prozeß gesandt werden. Dies entspricht dem Drücken der Tastenkombination Ctrl-C bei einem Text-Terminal oder xterm. Jeder LISP-Interpreter erkennt dieses Signal als einen Keyboard-Interrupt oder User-Break, also eine vom Benutzer gewünschte Unterbrechung der Evaluation. LISP ruft dann den Debugger auf, bietet aber im Gegensatz zum Fehlerfall die Wiederaufnahme der Evaluation an.

    Bild S18: Hauptmenü von EMA-XPS v1

    Bild S19: LISP-Debugger PAD am Ende der Bootphase

    Wird der C-Prozeß kontrolliert beendet, beispielsweise dadurch, daß der Window-Manager dies mittels des ICCCM- Protokolls mitteilt, sendet er vorher ein SIGKILL-Signal an die LISP-Welt, die daraufhin umgehend terminiert. Die C- Seite schließt danach die Interprozeßkommunikationskanäle und terminiert ebenfalls.

    4. Implementierung von EMA-XPS v2

    Mit der Entscheidung, das einleitend erwähnte FVA- Forschungsvorhaben unter Verwendung der verfügbar gewordenen kommerziellen Schale babylon-3 fortzuführen, sind die Arbeiten an EMA-XPS eingestellt worden. Eine SUN- kompatible Sparc-Workstation mußte beschafft werden, um babylon-3 betreiben zu können. babylon-3 ist unter dem CLtL2 kompatiblen Allegro CommonLISP 4.0 entwickelt worden.
    Mit dem unerwarteten Ende der Verfügbarkeit dieser Schale wurde EMA-XPS wieder interessant. Die Rekompilation der C-Quelltexte auf der Sparc-Workstation verlief problemlos, die LISP-Erweiterungen dagegen bereiteten Mühe. Da kein Lucid CommonLISP für SunOS verfügbar war, mußte Ersatz gesucht werden. Das lizenzkostenfreie CLtL1- kompatible CLISP, das bereits Teile der CLtL2 Ergänzungen beinhaltet, stellt eine geeignete Alternative dar.
    CLISP bietet eine andere Foreign-Function Unterstützung als Lucid und wieder eine andere als Allegro. Daher sind bei der Portierung die Lösungen sharable memory und unnamed pipes weggefallen. Nur die named pipes genügten der Portabilitätsforderung, weil sie nur den von CLtL1 garantierten Sprachumfang verwendeten. Trotzdem stellte sich heraus, daß für das Öffnen einer Pipe-Datei zum Schreiben jeder LISP-Interpreter andere Einstellungen benötigte. Pipelines unterscheiden sich von gewöhnlichen Dateien dadurch, daß das Repositionieren der Dateilese- und -schreibzeiger nicht möglich ist.
    Weiterhin ergaben sich Probleme, weil CLISP und Allegro mittels isatty feststellen, ob sie an einer Teletype arbeiten. Dementsprechend fehlt der Prompt, der vom toplevelPipeInputHandler überwacht wird. Die Interprozeß- Kommunikation kommt gelegentlich sogar außer Tritt. Daher muß ein stabileres und portableres Grundkonzept für die Interprozeßkommunikation gefunden werden.
    Es kommt hinzu, daß die unter babylon-3 entwickelten Wissensbasen in ihrem Bestand gefährdet waren. Eine Emulation setzt neben der Nachbildung der unterschiedlichen Wissensbeschreibungssprachen in den Wissenbasis-Dateien auch eine leistungsfähigere Endbenutzerschnittstelle voraus. Diese Probleme sind in der Version 2 der Schale EMA- XPS gelöst worden.

    4.1 Toplevelloop von CLtL1 LISP-Implementierungen

    Die Quelltexte der modular konzipierten Schale Babylon- 2 sind in dem damals gültigen LISP-Standard CLtL1 realisiert worden. Babylon ist ausschließlich objektorientiert realisiert. Dazu ist das in Kapitel 2.1 erwähnte Meta Class System (MCS) verwendet worden.
    Derzeit unterstützen noch nicht alle LISP-Anbieter den vollen Umfang des CLtL2-Standards. Diese zweite Festlegung des Sprachstandards definiert sehr leistungsfähige Möglichkeiten, den Prompt-Text zu beeinflussen und den Einsprung in das LISP-eigene Fehlerwerkzeug, den Debugger, zu kontrollieren. Aus Gründen der größtmöglichen Kompatibilität soll hier aber weitestgehend mit den Möglichkeiten der CLtL1 Implementierungen ausgekommen werden.
    Ein Debugger ist in den meisten Interpreter-Sprachen vorgesehen, wenn auch mehr oder weniger rudimentär. Unter LISP stellt er einen definierten Wiedereintrittspunkt in die interaktive Betriebsart nach einem Fehler dar. Er stellt die Möglichkeit zur Verfügung, das Auslösen der Fehlerbedingung zurückzuverfolgen. Beispielsweise kann der Funktionsstack mit Aufrufparametern sowie eine große Zahl von Variableninhalten erfragt werden, was die Fehlersuche bei der Programmentwicklung unterstützt.
    Neben dem bereits beschriebenen Unterschieds bei der interaktiven Betriebsart eines LISP-Interpreters, bei der eine Eingabeaufforderung geschrieben wird und dem Batch- Betrieb, bei dem dieser Prompt unterbleibt, ist eine weitergehende Betrachtung des read-eval-print-loops von Interesse.
    Die LISP-Funktion read wertet einen kompletten LISP- Ausdruck aus und gibt ihn in der typischen Listenschreibweise zurück. Eine Liste wird durch eine `(', eine von Leerzeichen getrennte Reihe von LISP-Ausdrücken, und eine `)' beschrieben. Dabei darf sich der Ausdruck durchaus über mehrere Zeilen erstrecken. Demgemäß muß read bereits ein Grundverständnis der Sprache besitzen. Beispielsweise wertet diese Funktion bereits Kommentare und Zeichenketten (Strings) aus. Klammern in Strings dürfen dabei die einzulesende Listenhierarchie nicht verletzen. Zusätzlich können Makrozeichen definiert werden.
    Im Rahmen der babylon-3 Emulation ist darauf zurückgegriffen worden. Eine Liste der Form "[a b c]" wird unter Nutzung dieser Makrozeichen-Expansion von read als eine Liste der Form ($PRED A B C) zurückgegeben.
    Der Rückgabewert von read dient als Eingabe der Funktion eval. Diese prüft zunächst, ob der Übergabewert eine Liste oder ein einfacher Ausdruck ist. Konstanten (eine Zahl, ein String oder ein Schlüsselwort) werden direkt zurückgegeben, Symbole werden als Variable interpretiert und es wird mittels symbol-value versucht, ihren Wert zu bestimmen und zurückzugeben. Im Falle einer Liste wird zunächst geprüft, ob das erste Element der Liste ein Symbol ist. Ist das erste Element eine Liste, wird sofort ein Syntax-Fehler ausgelöst, weil dies laut dem Lambda-Kalkül nicht zulässig ist. Danach wird festgestellt, ob das Symbol auf eine Makrodefinition verweist. In diesem Fall wird das Makro zunächst expandiert und eval erneut auf das Resultat angewandt. Zuletzt verbleibt nur noch die Möglichkeit, daß das Symbol auf eine Funktionsdefinition verweist. Dieser wird mittels der Funktion apply die Argumentliste, also die verbleibenden Elemente der von read übergebenen Liste, übergeben.

    Bild S20: Flußlaufplan des LISP-Toplevelloops

    Diese Standardvorgehensweise kann beeinflußt werden. Zu diesem Zweck stehen verschiedene Hook-Funktionalitäten zur Verfügung. In globalen Variablen werden Zeiger auf benutzerdefinierte Funktionen eingetragen, die einzelne Operationen ersetzen oder ergänzen sollen. Enthalten diese Variablen den Wert NIL oder existieren sie erst gar nicht, wird das Standardverhalten durchgeführt. Tabelle S4 zeigt die Variablennamen und deren Bedeutung auf.

    *evalhook* alternative Evaluations-Funktion
    *applyhook* beeinflußt die Anbindung der Argumentliste an eine Funktion
    *macroexpand-hook* anderes Vorgehen bei der Makro-Expansion
    *debugger-hook* eine Alternative zum Einsprung in den Debugger (erst in CLtL2 festgeschrieben, von etlichen CLtL1-Interpretern aber bereits als Erweiterung angeboten)

    Tabelle S4: Möglichkeiten der Beeinflussung des Toplevelloops

    Eval gibt das Evaluationsergebnis des übergebenen Ausdrucks zurück, das mittels print in den Standardausgabekanal geschrieben wird. Das LISP-Konstrukt für die Endlosschleife, loop, sorgt für die Wiederholung des Vorgangs. Der Toplevelloop läßt sich vereinfacht wie folgt beschreiben:

    (loop (print (eval (read))))

    Bild S20 zeigt prinzipiell den Flußlaufplan des LISP- Toplevelloops auf. Die Möglichkeiten der Einflußnahme sind für die Emulation der Wissensrepräsentationsmechanimen von babylon-3, sowie zur Implementierung der virtuellen Kanäle von EMA-XPS v2 genutzt worden.

    4.2 Virtuelle Kanäle

    Das Konzept der logischen Interprozeßkommunikationskanäle von EMA-XPS v1 ist eine Weiterentwicklung der Mechanismen der xgrf3 Grafik. Das unübiche Verhalten des Lucid LISP-Interpreters, den Prompt immer zu schreiben, hatte dazu geführt, daß pro Kanal und pro Richtung eine named pipe geöffnet wurde. Pipes werden als spezielle Geräte über den Kernel realisiert. Dieser stellt nur eine begrenzte Anzahl solcher Gerätetreiber zur Verfügung. Unter SunOS ist diese Zahl auf 32 begrenzt. Daher konnte EMA-XPS nie mehr als zweimal gleichzeitig auf einem Rechner betrieben werden. Dies stellt eine unerwünschte Verschwendung knapper Resourcen dar.
    Bei Verwendung von Pseudo-Teletypes als bidirektionale Pipelines, die das Erscheinen des LISP-Prompts garantieren, sind pro EMA-XPS Sitzung 8 Geräte zu belegen. Da aber auch andere Applikationen, wie das xterm, diese Geräte benötigen, ist hier ebenfalls die Zahl der verfügbaren Geräte (48 unter SunOS) schnell ausgeschöpft. Daher müssen hier Einsparungen vorgenommen werden.
    Dazu muß zunächst die Kanalauslastung in den unterschiedlichen Betriebssituationen von EMA-XPS untersucht werden. Tabelle S3 ist zu entnehmen, daß - aus der Sicht des LISP-Prozesses - 3 Eingabekanäle und 8 Ausgabekanäle existieren. Über die Ströme *explain-stream*, *rule-stream*, *prolog-stream*, *consat-stream* und *system- stream* schreibt die Inferenzmaschine von Babylon-2 Klartextinformationen in einzelne PADs.
  • Für die Explain-Pipe empfiehlt sich sicherlich, alle erklärenden Ausgaben der Inferenzmaschine in einem eigenen Ausgabefenster zusammengefaßt zu haben.
  • Die anderen vier Ströme enthalten alle ausschließlich Trace-Informationen. Tracer sind Entwicklungshilfen, mit deren Hilfe der Ablauf der Wissensverarbeitung sichtbar gemacht werden kann. Der Wissensingenieur wird bei der Erstellung eines Expertensystems Tracer nutzen, wenn er beispielsweise auf der Suche nach Fehlern ist oder die Problemlösung beschleunigen will. Dazu ist eine chronologische Listung der Trace-Ausgaben geeigneter als eine thematische Trennung. Dementsprechend lassen sich die vier Trace-Ströme in einen einzigen unidirektionalen Kanal zusammenfassen.
  • Mit der Entscheidung, die nicht mehr zeitgemäßen rein textstromorientierten Sitzungsabläufe nicht länger zu unterstützen, konnte auf den *dialog-stream* und den Sitzungs PAD komplett verzichtet werden. Stattdessen steht mittlerweile eine Minimalversion der grafischen Endbenutzerschnittstelle zur Verfügung, mit der derartige Sitzungen dennoch noch nachempfunden werden können.
  • Die Toplevel-Pipe ist unverzichtbar, weil die komplette Bootsequenz und die Debuggerbedienung im Fehlerfall nur hierüber abgewickelt werden können.
  • Die Graphic-Pipe ist zur Erstellung der Popupdialoge eingeführt worden und kontrolliert mittlerweile auch die Kommunikation bei den Editoren und dem Endbenutzerbildschirm. Die Vielfalt der Aufgaben hat hier von Anfang an eine Protokollfestlegung erfordert.
    Es verbleiben somit LISP-seitig die Standardein- und Standardausgabe, ein Ausgabestrom für Grafikprotokollsequenzen, die Trace-Ausgabe und die Er klärungsausgabe. Weiterhin werden die C-seitigen Rückmeldungen über den *graphic-stream* gesandt. Wenn man andererseits berücksichtigt, daß die Graphic-Pipe bereits unterschiedliche Fenstertypen bedient, in dem sie eine Protokolleröffnungssequenz mit Nachrichtentyperkennung sendet, danach eine Nachricht und schließlich die Protokollendesequenz, können auch Trace-Ausgaben und Erklärungen über die Graphic-Pipe abgewickelt werden.

    Die Graphic-Pipe kann dann auf die Standardausgabe gelegt werden, wenn das Grafik-Protokoll als ununterbrechbar definiert wird. Während der Initialisierungsphase sendet LISP nur Standardausgaben. Sobald eine Grafik-Nachricht zu übertragen ist, wird die Protokolleröffnungssequenz geschrieben. Der modifizierte toplevelPipeInputHandler erkennt, daß eine Nachricht folgt und schreibt die empfangenen Zeichen nicht mehr in den Debugger PAD, sondern leitet bis zur Protokollendesequenz alle Zeichen der grafischen Auswertung zu.
    Das Protokoll kommt außer Tritt, wenn zwischen Eröffnungs- und Endesequenz protokollfremde (Standard-)Ausgaben geschrieben werden.

    Der Vorteil der zwei Kanäle, an denen LISP hört, ist, daß ein neues LISP-Kommando bereits vom C-Prozeß abgesetzt werden kann (beispielsweise "hole Regeldefinition"), während eine Sitzung noch läuft und ein Popupdialog noch geöffnet ist. Die korrekte Abarbeitung der Eingaben ist gewährleistet. Werden beide Kanäle zusammengelegt, muß der C-Prozeß erkennen, daß die Quittierung des Popups vor das bereits abgesetzte LISP-Kommando gereiht werden muß.

    Durch Einbringen der C-seitigen Leistungserweiterung, die Eingabewarteschlange für LISP-Befehle umsortieren zu können, kann trotz einer Beschränkung auf einen einzigen LISP-seitigen Lesekanal die Funktionsfähigkeit aufrecht erhalten werden.

    Diese Schlüsse lassen unter Beachtung der geforderten Disziplin eine Reduzierung auf den immer vorhandenen Standardein- und -ausgabekanal zu. Damit kann die Zwei- Prozeß-Lösung EMA-XPS v2 - ähnlich dem xterm - mit einer einzigen Pseudo-Teletype auskommen. Die Quelltexte des xterm sind frei verfügbar. Daher lag es nah, die Geräteöffnung der Pseudo-Teletypes ähnlich den Kernroutinen des xterm durchzuführen. Dieses Vorgehen ist vorteilhaft, weil sich erfahrungsgemäß Probleme bei der Portierung auf andere Plattformen - wenn überhaupt - nur im Bereich der untersten Ebene der Interprozeßkommunikation einstellen. Und da in jedem Fall das xterm auf diesen neuen Plattformen existieren wird, kann ein Blick in die Datei main.c des xterm helfen, das Problem zu lösen.
    Das xterm unterstützt die VT100 Steuersequenzen. Diese beginnen mit dem ASCII-Code ESC (Escape, Fluchtsymbol) und einer definierten Folge von weiteren Zeichen. Bei der Festlegung des Protokolls von EMA-XPS v2 ist dies aufgegriffen worden. ESC wird bei zeichenstromorientierten Programmen wie Babylon-2 nicht verwendet, um nicht versehentlich eine VT 100 Steuersequenz zu initiieren. Es eignet sich daher besonders für die Kanalumschaltung. Da die PADs keine VT100 Escapesequenzen kennen und erwarten, ist das Zeichen auch frei für eine derartige Nutzung.
    Das Protokoll der Version 1 begann mit einer 10 bis 20 Zeichen langen Kanalkennung und einem abschließenden %%, wie in Kapitel 3.3 vorgestellt. Die Interprozeßkommunikation kann schnell zum Flaschenhals werden, wenn viele Informationen ausgetauscht werden müssen. Daher sollte der Protokoll-Overhead klein gehalten werden. Aus diesem Grund folgen dem ESC immer drei Ziffern (0-9). Das vierte Zeichen nach dem ESC ist also immer das erste Zeichen der Nachricht. Es stehen damit maximal 1000 unterschiedliche Nachrichtentypen oder virtuelle Interprozeßkommunikationskanäle zur Verfügung. Per Konvention sind die Kanalnummern 000 bis 009 besonderen Aufgaben vorbehalten. Darauf wird im folgenden Kapitel näher eingegangen. Als Protokollendesequenz ist das Umschalten auf einen dieser privilegierten Kanäle festgelegt worden.
    Eine Nachricht könnte damit beispielsweise die folgende Form haben:

    ESC 0 1 0 Z u g r i f f _ v e r w e i g e r t ! ESC 0 0 1

    In der derzeitigen Implementierung ist der Kanal 010 gleichbedeutend ist mit der Aufforderung an die C-Seite, einen Informationsdialog mit dem Text "Zugriff verweigert!" und einem Bestätigungs-Knopf zu erstellen (Bild S21) und LISP bis zur Quittierung durch den Benutzer warten zu lassen.

    Bild S21: Ein Informationsdialog von EMA-XPS v2

    Jede Grafikprotokollsequenz beginnt also mit einer Kanalnummer größer oder gleich 10 und endet mit einer Nummer kleiner 10. Die Protokolldisziplin verlangt, daß dazwischen keine protokollfremden Zeichen übertragen werden dürfen. Für jede verwendete Kanalnummer ist eine Handlerroutine zu registrieren, die die notwendigen Aktionen durchführt.

    4.3 Zustandsmaschine als Beobachter des LISP-Prozesses

    Der Forderung nach einer Fähigkeit der C-Seite, die Reihenfolge der Eingaben für die LISP-Seite vertauschen zu können, wird dadurch Rechnung getragen, daß zunächst eine Funktion zur Verfügung steht, die ein Kommando direkt absetzt. LISP_sndReply() erwartet als einziges Argument einen kompletten, eventuell mehrzeiligen LISP-Ausdruck. Dieser wird - inklusive eines abschließenden NEWLINE - direkt in die Standardeingabe von LISP kopiert. Dieser Funktion überlagert existiert LISP_sndCmd(), die ebenfalls einen kompletten LISP-Ausdruck erwartet. LISP_sndCmd reiht diesen Ausdruck aber nur in eine Befehlswarteschlange (Queue) ein. Der C-Prozeß prüft wiederholt, ob LISP sich in einem Zustand befindet, in dem neue Kommandos eingegeben werden können. Das sind die Eingabebereitschaft beim Verharren im Toplevelloop beziehungsweise im Debugger. Wenn LISP eingabebereit ist, wird geprüft, ob in dieser Befehlsqueue wenigstens eine Anweisung anliegt. Nach dem FIFO-Prinzip wird die älteste Eintragung mittels LISP_sndReply in die LISP-Standardeingabe kopiert und der Eintrag in der FIFO gelöscht.
    Das im letzten Kapitel beschriebene Problem, daß bei einem Popupdialog gemäß Bild S21 eine Quittierung vor den eventuell bereits aufgelaufenen Kommandos in die Standardeingabe geschrieben werden muß, ist damit gelöst. Während LISP auf die Quittierung wartet, ist es nicht eingabebereit im oben beschriebenen Sinne. Damit werden die Kommandos zurückgehalten. Die Quittierung dagegen wird mittels LISP_sndReply direkt abgesetzt (daher auch der Name dieser Funktion).

    Das Funktionieren dieses Konzepts setzt eine C-seitige Kenntnis des aktuellen Zustands des LISP-Interpreters voraus. Eine geeignete Beobachtung ist zu ermöglichen. Zustandswechsel sind daher C zu signalisieren.

    Der häufigste Fall ist, daß LISP sich im Toplevelloop befindet und Eingaben erwartet. Das heißt, LISP hat das letzte Kommando erfolgreich evaluiert und das Ergebnis in die Standardausgabe geschrieben. Danach wird der Prompt ausgegeben. Dieser Zustand soll als eingabebereit oder RDY (ready) definiert werden. Sobald ein Kommando eingegeben und die Eingabe mit einem NEWLINE-Zeichen (Zeilenumbruch) abgeschlossen ist, wertet read die Eingabe aus und leitet sie eval zu. Bis zur erfolgreichen Ausgabe des Ergebnisses sei LISP beschäftigt oder BSY (busy).
    Wie bereits erwähnt, sind die virtuellen Kanäle 0-9 besonderen Aufgaben vorbehalten. Ein erweiterter Evalhook- Handler kontrolliert das Versenden der Synchronisierungsmitteilungen an die C-Seite. Bild S22 zeigt den LISP-Quelltext des verwendeten Handlers.

    (defun emaxps-evalhook (form &optional env) (let (vals)
    (emaxps-is-busy);; sendet ESC 0 0 1 für BSY

    ;; rufe den original LISP evalhook-Handler
    ;; selbst-rekursiv auf, sodaß bei möglichen
    ;; Rekursionen während der Evaluation keine
    ;; irreführenden Escapesequenzen gesendet
    ;; werden!
    (setf vals (multiple-value-list
    (evalhook form nil nil env)))

    (emaxps-is-ready) ;; sendet ESC 0 0 0 für RDY

    ;; gebe die Ergebnisse des original LISP-
    ;; Handlers zurück
    (values-list vals)
    );let
    )

    Bild S22: Toplevel Evalhook-Handler von EMA-XPS

    Sobald read eine form an eval weiterleitet, erhält C durch Umschalten in den Kanal 001 die Information BSY mitgeteilt. Nachdem eval komplettiert hat, wird in den Kanal 000 (RDY) zurückgeschaltet. Beide Kanäle erwarten keine anschließenden Nachrichten. Die Ausgabe der Ergebnisse von eval durch print kann im Falle einer ausgedehnten Liste sehr lange dauern. Da C aber bereits den Zustand RDY detektiert hat, wird es eventuell schon ein neues Kommando absetzen. Dies behindert nicht das korrekte Arbeiten der LISP-Seite, kann aber zu vermischten Ausgaben im Debugger PAD führen.
    Bei Verwendung der kompletten Möglichkeiten der CLtL2 Festlegung könnte die RDY-Sequenz erst zusammen mit der Eingabeaufforderung geschrieben werden. Der Prompt kann dort frei gewählt werden. Damit ließe sich auch leicht eine Unterscheidung zwischen der Eingabebereitschaft des Toplevelloops und der des Debuggers erreichen.
    Hier soll den eingeschränkten Möglichkeiten der CLtL1 Implementierungen Rechnung getragen werden. Der Prompt ist als implementierungsabhängig vorgegeben und nicht beeinflußbar anzunehmen. Der C-seitige Beobachter prüft bei Erhalt der RDY-Nachricht in kurzen Abständen, ob LISP noch Zeichen schreibt. Erst wenn print LISP-seitig beendet und der Prompt geschrieben worden ist, wird auch C-seitig die Eingabebereitschaft (RDY) angenommen.
    Die nächste Grundsituation im Betrieb des LISP- Interpreters ist, daß beim Evaluieren einer Anweisung ein Fehler erkannt wird und die Abarbeitung unterbrochen wird. Dann wird implementationsabhängig eine Fehlermeldung geschrieben und der Debugger angesprungen. Der Debugger besitzt eine ähnliche Hauptschleife wie der Toplevel. Äußerlich unterscheiden sie sich in erster Linie durch die unterschiedliche Eingabeaufforderung.
    Um hier ein portables Vorgehen bei der Zustandserkennung zu schaffen, ist eine Ausnahme von der Regel gemacht worden, nur CLtL1 Festlegungen zu nutzen. Da es keine Vorschriften über das Aussehen und den Leistungsumfang eines Debuggers gibt, müßte hier pro LISP- Implementierung eine geeignete Erkennung vorgesehen werden. Die Abfrage der Variablen *debugger-hook* ist erst in CLtL2 definiert. Sie garantiert die Möglichkeit, beim Debuggereinsprung eine Nachricht an die C-Seite abzusetzen. Diese Vorgehensweise ist nur deshalb möglich, weil der derzeit favorisierte LISP-Interpreter CLISP zwar CLtL1 konform ist, aber einige CLtL2 Erweiterungen bereits enthält. Dazu gehört auch diese Eigenschaft. CLISP ist bei der Entwicklung in die engere Wahl genommen worden, weil es lizenzkostenfrei und im Quelltext verfügbar ist und bereits auf eine Vielzahl von Plattformen erfolgreich portiert wurde.

    EMA-XPS v2.1 setzt die Verwendung eines LISP-Interpreters voraus, der CLtL1-konform ist und darüberhinaus die CLtL2- Erweiterung des debuggerhook bereitstellt.

    Der debuggerhook-Handler ruft vor jedem Einsprung in den Debugger die Funktion (emaxps-invoke-debugger) auf. Diese setzt die Nachricht ESC 0 0 2 (DBG) ab. Der C-Prozeß macht - falls noch nicht geschehen - den Debugger PAD sichtbar und löscht die Befehlswarteschlange. Falls dieses Ereignis während der Übertragung einer Grafik-Nachricht eingetreten ist, wird durch die Kanalnummer kleiner 10 die Nachrichtenübertragung korrekt beendet. Die Auswertung durch den registrierten Handler wird aber verhindert und der empfangene Nachrichtentext gelöscht. Im Fehlerfall löscht LISP sämtliche registrierten Hooks, also auch den evalhook. Daher installiert der debuggerhook den evalhook erneut, um auch während der Sitzung im Debugger die C-Seite geeignet informieren zu können, und wechselt schließlich in den Zustand RDY, um Eingabebereitschaft zu signalisieren.

    Als grafische Rückmeldung des aktuellen Zustands der LISP- Welt wird immer dann, wenn der Interpreter nicht RDY ist, die Form des Mauszeigers von dem üblichen Pfeil in eine Uhr verwandelt.

    Die nächste Sonderbehandlung ist beim Verlassen des Debuggers zu berücksichtigen. Im Fehlerfall wird der alte Zustand der LISP-Welt auf einem Stack gerettet und eine neue, teilbereinigte Umgebung aus dem alten Zustand erzeugt. In diesem Zusammenhang ist das Rücksetzen der Hooks zu nennen. Wird nun das Kommando zum Verlassen des Debuggers eingegeben, wird kein BSY gesendet, da der Debuggerloop gleichzeitig aufhört, zu existieren. Beim Verlassen des Debuggers wird die alte Umgebung wiederhergestellt, also beispielsweise auch der alte evalhook. Die wiederhergestellte Toplevelschleife wartet auf Eingaben, bevor sie ein erneutes BSY senden wird. Bei diesem Rücksprung wird demgemäß weder ein BSY noch ein RDY gesendet. C blockiert die Weiterleitung von Kommandos.
    Ein Deadlock ist entstanden. Jedesmal, wenn ein Kommando an die LISP-Seite gesandt wird, wird daher zusätzlich eine Flag-Variable gesetzt. Nach einer gewissen Zeit, in der diese Flag-Variable gesetzt ist, ist mit mindestens einem Kanalwechsel (nämlich dem nach BSY) zu rechnen. Jeder Kanalwechsel setzt dieses Flag zurück. Unterbleibt dieser, ist davon auszugehen, daß der Sonderfall "Rückkehr aus dem Debugger" vorliegt. Es genügt, die Zustandsmaschine explizit in den Zustand RDY zu überführen und das Flag zurückzusetzen.
    Grafiknachrichten werden von der LISP-Seite nur gesandt, nachdem der Zustand BSY erreicht worden ist. Aufgrund der vorausgesetzten Disziplin werden sie immer korrekt mit einem Zurückschalten nach BSY beendet. Ein Sonderfall ist auch hierzu beachten. Die derzeit beschriebenen Mechanismen verhindern eine erfolgreiche Verwendung der LISP-Funktion read. Read erwartet einen LISP- Ausdruck an der Standardeingabe. Das Umschalten nach BSY vor der Ausführung von read verhindert, daß die Eingabe des Benutzers über das Texteingabefenster des Debugger PADs an read weitergeleitet wird. C geht davon aus, daß es sich dabei um ein weiteres Kommando handelt, das zunächst in die Befehlsqueue eingereiht wird. Daher steht eine Ersatzfunktion (emaxps-read) zur Verfügung, die vor dem Aufrufen von read auf Kanal 003 umschaltet. Diese Nachricht veranlaßt C, die nächste Eingabe statt mit LISP_sndCmd, mit LISP_sndReply weiterzuleiten. Abschließend wird ein BSY geschrieben.

    Bild S23: Zustandsmaschine als Beobachter des LISP-Prozesses

    Das Anfordern von Popupdialogen durch die LISP-Seite ist bereits beschrieben worden. Aufgrund der verwendeten Pseudo-Teletypes werden auch die Echos dieser Replies ausgegeben. Um das Textausgabefenster des Debugger PADs, das alle LISP-seitigen Ausgaben protokolliert, nicht zu überfluten, wird die Grafiknachricht, die den Aufbau des Popups bewirkt, nicht mit BSY beendet, sondern mit einen Wechsel in den Kanal 004. Erst nach Erhalt der Quittung wird nach BSY zurückgeschaltet. In der Zwischenzeit wird die Ausgabe in den PAD C-seitig unterdrückt.
    Die Bootphase ist gegenüber der ersten Version von EMA- XPS erweitert worden. Im Falle einer Weiterentwicklung der Schale wird nach der Abspaltung des LISP-Prozesses zunächst das Laden einer LISP-Datei initiiert, die wiederum das Laden der Erweiterungsmodule bewirkt. Im regulären Betrieb sind diese Erweiterungen bereits Bestandteil der aktivierten LISP-Welt. In jedem Fall ist das letzte Kommando dieses Teils der Bootphase (emaxps-end-of-boot-phase). Diese Funktion sendet ESC 0 0 9 (EOI, End of Initialisation) als Synchronisierungsnachricht an die C- Seite.
    Bild S23 zeigt die zur Beobachtung der LISP-Seite realisierte Zustandmaschine mit allen möglichen Zustandsübergängen auf.
    Schließlich verbleibt zu erwähnen, daß Kanal 008 reserviert worden ist, um sämtliche Änderungen der Gültigkeit von Wissensbasen in der LISP-Welt der C-Seite bekanntzugeben. C weiß zu jedem Zeitpunkt, wieviele und welche Wissensbasen gerade bekannt sind und inwieweit sie in Wissenseditoren geändert worden sind. Diese Funktionalität könnte über eine nicht privilegierte Kanalnummer abgewickelt werden. Da sie aber eine sehr enge Abstimmung der Prozesse aufeinander bewirkt, ist sie gegenüber anderen Nachrichtentypen ausgezeichnet worden. Eine ähnliche Auszeichnung ist für die in der LISP-Welt bekannten Prologklauselmengen beabsichtigt, da diese andere Gültigkeitsdauern als die anderen Wissensrepräsenationsmechanismen haben [S2, S3].

    4.4 babylon-3 Emulation

    Die Entwicklung eines Mechanismus, Wissensbasen, die unter der Expertensystemschale babylon-3 erstellt worden sind, unter EMA-XPS nutzen zu können, wird dadurch erleichtert, daß babylon-3 und EMA-XPS gleichermaßen aus Babylon-2 hervorgegangen sind. babylon-3 ist allerdings vollständig reimplemetiert worden. Dabei sind Änderungen und Straffungen des gewachsenen Codes von Babylon-2 für die angestrebte Industrietauglichkeit als empfehlenswert erachtet worden.
    babylon-3 weicht in den folgenden Punkten von Babylon-2 ab:
  • Konfigurationsmöglichkeiten des Leistungsumfangs der Inferenzmaschine beschränken sich auf die Wahl zwischen einer textorientierten und einer grafikfähigen Kommunikation mit dem Endbenutzer, sowie der optionalen Aufrüstmöglichkeit, mittels Embedded SQL auf Datenbanken zugreifen zu können [P7, S4].
  • Es gibt keinen Prolog- und keinen Freitextinterpreter.
  • Der Leistungsumfang des Metainterpreters ist für den Wissensingenieur unsichtbar und unerreichbar.
  • Eine leistungsfähige Erklärungskomponente ist realisiert. Das Maß an Erklärung kann in weiten Bereichen gewählt werden.
  • In Anlehnung an die SQL ist die Babylon Query Language (BQL) für einen datanbankartigen Zugriff auf das Faktenwissen realisiert worden. Frame-, Regel- und Constraintmechanismen greifen auf die BQL zurück.
  • Behaviors werden ähnlich LISP-Funktionen aufgerufen.
  • Regelkonflikte werden durch die Vergabe von Prioritäten gelöst.
  • Es existiert pro Expertensystem nur ein einziges Constraintnetz, das nur während des Sitzungsstarts aktiv ist. Nach Eintreten in den interaktiven Zustand bleibt es ausgeschaltet.
  • Die Eingabe von LISP-Befehlen in Regeln und dergleichen erfolgt in BabylonLISP. Diese Sprache ist gegenüber CommonLISP stark im Leistungsumfang reduziert und bietet teilweise andere Funktionaliäten an.
  • Es existiert eine Programmierschnittstelle zur Definition eigener Wissenseditoren und damit zur Erweiterung einer Wissensbasis zur Sitzungszeit.
    Eine vorangegangene Untersuchung der für die FVA entwickelten Wissensbasen ergab, daß keines der Expertensysteme Datenbankzugriffe verwendet. Alle Expertensysteme benötigen eine grafische Endbenutzerschnittstelle. Die Möglichkeiten der Erklärungskomponente sind nicht in Anspruch genommen worden. Da die Wissensbasen im Zuge einer Sitzung nicht erweitert werden sollten, sind auch keine sitzungsspezifischen Wissenseditoren erstellt worden.
    Der notwendige Umwandlungsaufwand ist zunächst mittels eines speziellen Cross-Compiler-Programms, ab Version 2.1 mittels Emulation von Funktionalität und Postprocessing im Anschluß an das Laden der zu importierenden babylon-3 Dateien realisiert worden. Der Aufwand läßt sich folgendermaßen kategorisieren:
  • im Leistungsumfang identische Funktionalität bei BabylonLISP und CommonLISP wird durchgereicht,
  • für im Leistungsumfang vergleichbare Funktionalität sind Filterfunktionen geschrieben worden, die die entsprechenden Babylon-2 Kommandos mit geeignet modifizierten Übergabeparametern aufrufen. Hier sind vordringlich die Definitionsformen für Wissensgrundelemente und Objekte der Endbenutzerschnittstelle zu nennen.
  • Der Leistungsumfang der BQL wurde bis hin zur Namensgebung und Notationserweiterungen vollständig eingebracht. Hier sind die Umsetzung der Mengenschreibweise {1 2 3} und die Prädikationen besonders zu erwähnen. [A B C] wird bereits beim Einlesen in ($pred A B C) verwandelt.
  • Regelsortierung nach babylon-3 Prioritäten erfolgt durch einen nachgeschalteten Postprozessor, der die Hinweise der Regeldefinitionsformen nutzt.
  • Auch die Generierung des Constraintnetzes erfolgt durch einen Postprozessor.
  • Die unter babylon-3 übliche Initialisierung der grafischen Endbenutzerschnittstelle mittels der speziellen Funktion make-kb-interface kann zu einen Namenskonflikt führen, wenn mehrere babylon-3 Wissensbasen gleichzeitig in der LISP-Welt existieren. Dann besteht die Gefahr, daß eine Sitzung mit dem Expertensystem A die Endbenutzerschnittstelle von B generiert. Dieser Konflikt wird durch Umwandlung in eine Task gelöst. Dazu ist ein spezieller Evalhook während des Ladevorgangs eingerichtet worden.
  • Durch Generierung spezieller Startermakros kann den Besonderheiten bei der Aktivierung von Behaviors Rechnung getragen werden. Babylon-2 Behaviors werden ähnlich den Tasks mittels eines Starters aktiviert:

    ($send instanz :nachricht argumente)

    unter babylon-3 dagegen eher wie Funktionen:

    (nachricht argumente)

    Um in den Körpern von Regeln, Constraints und dergleichen nicht nach Behavioraufrufen suchen zu müssen, um sie mit Startern zu versehen, werden für jedes Behavior Makros folgender Form definiert:

    (defmacro nachricht (instanz &rest args)
    `($send ,instanz :nachricht ,instanz ,@args))

    babylon-3 verwendet jeden Namen nur einmal je Wissensbasis. Doppeldeutigkeiten sind damit ausgeschlossen. Wenn zwei babylon-3 Wissensbasen gleichnamige Behaviors haben, werden die erzeugten Makros gleiche Namen und gleiche Körper besitzen. Die Wirkung des in Kapitel 4.8.1 aufgeführten Problems des Überschreibens beim Laden der Wissensbasen ist damit aufgehoben.

    Bild S24 zeigt die Ausgaben auf dem Debugger PAD von EMA-XPS v2.1 beim Laden einer unter babylon-3 entwickelten Wissensbasis. Protokollausgaben des Ladezeit-Evalhook sowie der Postprozessoren sind erkennbar.

    Bild S24: Protokollausgaben beim Importieren von babylon-3 Wissensbasen

    Die realisierte Emulation dient in erster Linie der Migration von babylon-3 Wissensbasen. Nur benötigte Leistungen sind nachgebildet worden.

    5. Zusammenfassung

    Die Schale EMA-XPS v2.1 ist eine Zwei-Prozeß-Lösung mit einer wechselnden Master-Slave-Beziehung. Sie verfügt im Gegensatz zur ersten Version der Schale nur noch über einen einzigen bidirektionalen Interprozeßkommunikationskanal. Um trotzdem die unterschiedlichen Arten von Informationen schlüssig austauschen zu können, sind virtuelle Kanäle realisiert worden, die auf einen physikalischen Kanal abgebildet werden. Zur korrekten Behandlung von LISP- Kommandos und Antworten der C-Seite stehen Mechanismen zur Verfügung, die Kenntnis über den aktuellen Zustand des LISP- Prozesses benötigen. Als Prozeßbeobachter wird eine Zustandsmaschine verwendet. Über den Debugger PAD steht dem Benutzer weiterhin die Möglichkeit offen, LISP-Kommandos direkt einzugeben und den Interpreter textstromorientiert zu bedienen.
    Neben einer leistungsfähigen, frei konfigurierbaren grafischen Endbenutzerschnittstelle stehen dem Wissensingenieur bei der Erstellung und Überarbeitung von Wissensbasen grafische Editoren zur Verfügung. Bedingt durch die wechselhafte Geschichte des einleitend erwähnten FVA-Forschungsvorhabens ist eine Möglichkeit geschaffen worden, Wissensbasen der Expertensystemschale babylon-3 einzulesen. Die Wissensrepräsentationsmechanismen von babylon-3 werden über Emulationsfunktionen in Konstrukte von EMA-XPS v2.1 überführt. Weitere für die FVA entwickelte Wissensbasen laufen unter babylon-3 und EMA-XPS v2.1 gleichartig ab. Auch die Abarbeitungsgeschwindigkeit der Inferenzmaschine ist hierin eingeschlossen.

    6. Ausblick

    Das am Beispiel der dialogorientierten grafischen hybriden Expertensystemschale EMA-XPS v2.1 vorgestellte Konzept einer Zwei-Prozeß-Lösung mit gemultiplexter Informationsübertragung und einer wechselnden Master-Slave- Beziehung kann für eine Vielzahl anderer Anwendungsfälle genutzt werden. Leicht wäre eine Grafikerweiterung für beliebige CommonLISP-Interpreter realisierbar, bei der nur die Möglichkeiten der grafischen Endbenutzerschnittstelle und der Popupdialoge genutzt werden. Der Partnerprozeß muß aber nicht notwendigerweise eine LISP-Welt sein. Jede umfangreichere für sequentielle Abarbeitung ausgelegte Anwendung, die umzuschreiben ein hohes Maß an Zeitaufwand im Zuge der Einarbeitung und Programmierung bedeuten würde, kann in erster Linie durch inhaltliche Änderungen der bereits vorhandenen Textausgaben leicht grafikfähig gemacht werden. Der Grafikserverprozeß sollte diese geänderten Ausgaben als ein Protokoll verstehen, das ihn zu geeigneten Aktionen veranlaßt.
    Die hier vorgestellte Schale stellt eine Alternative zu großen heute am Markt verfügbaren Systemen dar. Aufgrund der erst vor wenigen Monaten erfolgten Veröffentlichung von EMA-XPS v2.1 stehen noch keine Wissensbasen zur Verfügung, die unter der Schale entwickelt worden sind. Mittels eines in LISP realisierten Importfilters sowie durch Emulationsroutinen können Wissensbasen der Schale babylon-3 eingelesen und ausgeführt werden. Derartige Wissensbasen befinden sich bereits im industriellen Einsatz. Sie werden dort unter EMA-XPS auf PCs unter dem UNIX-Derivat Linux 1.2 betrieben.

    Mit Erreichen der Versionsnummer 2.1 ist die Entwicklung der Expertensystemschale EMA-XPS sicherlich noch nicht abgeschlossen. Sie ist aber in einen veröffentlichungsfähigen Zustand gekommen. Als eine freie - also offene - Software sollte sie der Ausgangspunkt für zeitgemäße Erweiterungen sein.
    Vordringlichstes Ziel der Weiterentwicklung ist sicherlich die Verbesserung der Erklärungskomponente. Durch eine Trennung der Nutzinformation in einem erklärenden Babylon-2 Text von der Präsentation sowie die Aufhebung der Beschränkung, nur Ausgaben in das Erklärungsfenster zuzulassen, können leistungsfähigere Erklärungen vom Wissensingenieur vorgesehen werden. Dies könnte durch Übergabe der Nutzinformationen als Argumente an eine Handlerfunktion erreicht werden. Ein Defaulthandler produziert daraus die gewohnten Ausgaben. Alternative Handler könnten registriert werden, die diese Nutzinformationen beispielsweise uminterpretieren und danach grafische aufbereiten, beispielsweise als Popupdialoge.
    Der modulare Ansatz von Babylon-2 und EMA-XPS v2.1 unterstützt bei Leistungserweiterungen im Bereich der Inferenzmaschine. Die Implementierung einer Fuzzy-Inferenz wäre denkbar. Dazu sollten C-seitig Editoren zur Bearbeitung von Zugehörigkeitsfunktionen erstellt werden. LISP-seitig wäre eine Erweiterung des Regelinterpreters notwendig. Eine Regelabarbeitungsstrategie :FUZZY wäre zu erarbeiten.


    Zurück zum Inhaltsverzeichnis