\documentclass[a4paper]{article} \usepackage[utf-8]{inputenc} \usepackage[german]{babel} \usepackage{url} \usepackage{alltt} \usepackage{multicol} \title{Dictionary im Filesystem} \author{Matthias Trute} \begin{document} \maketitle \section{Zusammenfassung} Es wird ein alternativer Ansatz für die Implementierung von Forth--Dictionarys beschrieben. Es gibt keinen Code oder eine lauffähige Implementierung. Dieser Artikel soll eine Diskussion über Implementierungsstategien von Forth--Systemen anregen. \begin{multicols}{2} \section{Ausgangspunkt} Aktuelle Embedded--Systeme bieten die Möglichkeit, Standardbetriebssysteme zu betreiben, namentlich Linux. Anstelle von Festplatten dient hier Flashspeicher als Speichermedium, zusammen mit dafür optimierten Filesystemen. Auf diesen Systemen den alten Forth-Ansatz, alles selbst zu machen, umzusetzen, scheint angesichts der Komplexität der Aufgabe, eine Vielzahl an Treibern und Basisdiensten zu erstellen und in der doch kleinen Nutzergemeinde auch zu testen, nicht empfehlenswert. Es ist sinnvoller, die bereits getane Arbeit für das Betriebssystem auch zu nutzen und die Stärken von Forth auszuspielen. Üblicherweise ist RAM bei diesen Systemen knapp bemessen. Da es nicht so einfach wie bei einem PC ist, RAM nachzurüsten, sollte RAM als Ressource für die Applikation und nicht für die Hausaufgaben des Systems betrachtet werden. Das geht am einfachsten, wenn man das, was im RAM liegt, und sich nicht wesentlich ändert, anderweitig unterbringt. Dieses "`nicht wesentlich"' ist ein Schlüsselwort. Flashspeicher kann einige Male (i.allg. sind das einige tausend Male) neu beschrieben werden. Damit wird Flashspeicher für alles interessant, was nur einige Male geändert wird. Bei Forth sind dies wesentliche Teile des Dictionaries: Die (Colon--) Worte. Ein weiterer Aspekt kommt hinzu. Flash ist deutlich schneller als andere Speichermedien namentlich Festplatten. Besonders deutlich ist dies beim Faktor Zugriffszeit. Bis eine Festplatte den Lesekopf positioniert hat, dauert es eine Weile. Flash, wie auch RAM, kennen diesen Parameter (fast) nicht. Beim Datentransfer vom Flash zur CPU ist das geringere Tempo des Flash gegenüber dem RAM zu beachten, spielt aber bei embedded Systemen mit bestenfalls einigen Hundert MHz keine herausragende Rolle. Das Ziel ist damit umschrieben: Das Dictionary soll im Flashspeicher liegen. Dieser Flashspeicher wird vom Betriebssystem in einem Filesystem verwaltet. Dieses berücksichtigt nebenbei auch den bereits erwähnten Effekt, das Flash nur eine begrenzte Zahl von Löschzyklen machen kann und verteilt die Zugriffe entsprechend. Direkter Zugriff auf die Blöcke mit dem BLOCKS word set aus dem Standard verbietet sich weitgehend, da ja schon ein Filesystem vorhanden ist. Eine Variante ist ein großes Einzelfile, das mehr oder weniger ein Hauptspeicherabbild des kompletten Dictionarys ist. Dies ist sicherlich einfach umzusetzen. Eine andere Idee wird nachfolgend skizziert. Dabei wird ausgenutzt, dass ein Dictionary nicht nur ein binärer Klumpen von Bits und Bytes ist, sondern eine wohldefinierte Struktur aufweist, die viele Parallelen zu einem Filesystem hat. Ebenso wird die Funktionsweise des Forth--Interpreters mit einer Shell in Bezug gesetzt. \section{Strukturen} Das Forth--Dictionary besteht bekanntlich aus einzelnen Vocabularys. In jedem einzelnen ist eine Menge von Worten enthalten, die man in erster Näherung als ausführbare Programme ansehen kann. Um die Vocabularys zu nutzen, wird eine Suchreihenfolge definiert. Zusätzlich gibt es eine Art aktuelles Vocabulary, in das alle neu definierten Worte gelangen. Wird ein Wort gesucht, werden die Vocabularys in der festgelegten Reihenfolge duchsucht und das erste Wort, das passt wird aufgerufen. Das ist nicht anders bei der Shell. Sie mustert Verzeichnisse gemäß der in der Umgebungsvariablen \verb|PATH| festgelegten Reihenfolge und das erste (ausführbare) Programm wird gestartet. Legt man gedanklich diese beiden Strukturen übereinander, wird aus einem Vocabulary ein Verzeichnis und aus einem Forth--Wort eine ausführbare Datei. Der Forthheader wird der Directoryeintrag mit dem Dateinamen und den Attributen, das Datafield wird der Dateiinhalt. Was Forthworte von Shellbefehlen unterscheidet, ist die gemeinsame Nutzung von zwei (oder mehr) Stacks für die Parameterübergabe. \section{Auswirkungen} \subsection{Flags} Das Forth--Dictionary hat einige Flags, die problemlos auf die Filesystempermissionflags abgebildet werden können: Das x--Bit könnte das Smudge--Flag werden (nur mit der umgekehrten Wertbedeutung), Das s--Bit kann für IMMEDIATE genutzt werden, R und W können ihre Bedeutung behalten. \subsection{Suchreihenfolge} Mit dem Ansatz, die Worte vom Filesystem verwalten zu lassen, gibt man die Herrschaft über die Reihenfolge, in der die Worte innerhalb eines Vocabularys gesucht werden, auf. Wo ist das ein Problem? Nur bei Worten, die redefiniert wurden. Alle anderen sind nur einmal vorhanden. Und das Redefinieren von Worten ist spätestens seit DEFER/IS als eine veraltete Programmiertechnik einzustufen. Wer es aber haben will, kann über den Einsatz eines versionierenden Filesystems nachdenken, auch hierfür gibt es lange Erfahrungen (VAX). \subsection{Dateinamen und Wortnamen} Forthworte als Dateinamen gehen "`fast immer"'. Auch wenn es in der Unixshell einiger Vorkehrungen bedarf, um Dateien wie \verb|<#| oder \verb|?| anzulegen: \begin{verbatim} mt@forthy:~/dforth/FORTH$ ls <# ! ? @ #> abort mt@forthy:~/dforth/FORTH$ \end{verbatim} Einzig zwei Zeichen sind in Dateinamen nicht zulässig: Das Null-Byte und der Directory--Separator \verb|/|. Ersteres ist keine wirkliche Einschränkung, der \verb|/| schon. Denn damit sind Worte wie \verb|/| oder \verb|UM/MOD| nicht erlaubt. Dies ließe sich durch einige Tricks umgehen: Das in Forth--Worten nicht zulässige Leerzeichen kann als Ersatz herhalten, oder der Dateiinhalt wird komplexer, was den Dateinamen nicht mehr zwingend zum Wortnamen macht. Ein dritter Aspekt ist die Groß/Kleinschreibung. Hier wird das Forth vollständig abhängig vom zugrundeliegenden System: Linux--Filesysteme sind in der Regel case sensitive, Windows speichert zwar die Schreibweise, beachtet aber Groß-Kleinschreibung nicht. \subsubsection{Neue Möglichkeiten} Wenn die Forth-Worte nicht mehr dicht an dicht im Dictionary liegen, sondern praktisch unabhängig voneinander sind, ergeben sich neue Programmieransätze. Forth Worte können zur Laufzeit redefiniert werden und die neuen Worte haben auch Wirkung auf die bereits bestehenden (so als ob jedes Wort mit DEFER angelegt würde). Ist der Directoryeintrag eine komplexere Datenstruktur (etwa die Geburtstage aus einer der letzten VD), kann er problemlos erweitert werden. Es gibt kein Wort, das durch das Anhängen von Daten an ein bestehendes Wort überschrieben werden könnte. Ein weiterer Aspekt sind Usernamen und Gruppenrechte. In komplexeren Konstellationen könnten sie zur Absicherung von Bibliotheken genutzt werden. \section{Implementierung} Wie eingangs erwähnt, gibt es derzeit keine Implementierung. Einige Überlegungen sollen aber dennoch angestellt werden. Hier werden auch mögliche Showstopper diskutiert. \subsection{Dateiinhalt} Der Dateiinhalt der Einzelworte ist im Wesentlichen der Inhalt des klassischen Datafields. Eine weitere Möglichkeit bietet sich für (Just--In--Time--)Compiler. Der Dateiinhalt kann komplexer strukturiert werden, um generierten Maschinencode anstelle oder zusätzlich zu Execution--Tokens vorzuhalten. Bei den Gerätedateien im Verzeichnis \verb|/dev| sind natürlich die betreffenden Geräte angesprochen. \subsection{Execution--Token} Das Execution--Token ist ein offener Punkt. Es wird bei Worten wie \verb|'| (TICK), \verb|EXECUTE|, \verb|FIND| benutzt und ist zugleich Bestandteil des Datafields innerhalb der Colon--Definitionen. Da das Execution--Token sowohl zur Identifikation eines Wortes dient, als auch als "`Zwischencode"' vom Compiler verarbeitet wird, ist hier Kreativität gefordert. Eine naheliegende Idee ist der Einsatz eines Caches, der die Worte in den Dictionarys beim Start analysiert und so eine Art temporäres Execution--Token bereitstellen kann. \subsection{Handhabung} Wie kann man mit den Worten umgehen? Ein einfacher Ansatz ist das FILE Extension Wordset. Es bietet alle Möglichkeiten, Dateien zu manipulieren. Die Umsetzung von Worten wie \verb|:| oder \verb|CURRENT| ist nicht weiter kompliziert, spannender wird \verb|:NONAME|, da es ja keine namenlosen Files gibt. Interessant werden \verb|,| und \verb|@|/\verb|!|, die (auch) mit den Dictionaryeinträgen operieren. Da sie gleichzeitig benötigt werden, um auf RAM zuzugreifen, sind sie nicht eben trivial. Ein Ansatz könnte der von einigen Forth--lern propagierte Ansatz mit XDATA/UDATA sein, mit dem der Speicherbereich, auf den die erwähnten Worte operieren, umgeschaltet wird. \subsection{Housekeeping} Die gerne während der Entwicklung genutzten Worte \verb|FORGET| und \verb|MARKER| müssen auf Dateiattribute zugreifen, um alle Worte zu finden, die es zu entfernen gilt. Alternativ kann \verb|FORGET| zu neuen Ehren kommen: Es kann jetzt gezielt \emph{ein} Wort löschen. Hier ist natürlich zu beachten, das es kein Wort trifft, das von einem anderen Wort genutzt wird \dots \section{Fazit} Dieser Artikel ist als Diskussionspapier gedacht. Die Ideen erheben nicht den Anspruch, zu einem ANS94--konformen System zu führen. Es ist auch noch offen, ob der Ansatz Filesystem als Dictionary wirklich benutzbar ist, Literaturquellen scheint es jedenfalls keine zu geben. \end{multicols} \end{document}