Atarium: MiNT 0.96 - »Shared Text« und Debugging

Informationen um MultiTOS fließen recht spärlich. Aber Eric Smith versorgt die ST-Gemeinde über Neues bei der MiNT-Entwicklung.

In Sunnyvale und Raunheim (bzw. Schwalbach) herrscht mittlerweile seit Monaten in Sachen »MultiTOS« Funkstille. Auf Messen (zum Beispiel der Atari-Messe im August) ist es nicht zu sehen, Informationen zu neuen Releases sind auch nicht zu bekommen - außer dem Versprechen, MultiTOS werde mit den Falcons ausgeliefert. Mittlerweile fragen sich die Entwickler, wie das eigentlich weitergehen soll. Warten wir‘s ab es fragt sich nur, wieviel Geduld der Markt letztendlich haben wird. Anders sieht es mit dem Fleiß und der Mitteilsamkeit des MiNT-Entwicklers Eric Smith aus (wir erinnern uns: was der MiNT-Kernel kann, fließt auch früher oder später in MultiTOS ein). Nicht, daß es nur zwei Monate nach unserer letzten Berichterstattung ([1]) bereits wieder Neuigkeiten gibt - Eric Smith erlaubte uns auch, schon jetzt exklusiv über die Neuerungen im nächsten Release 0.96 zu berichten. Doch zunächst zu Dingen, die schon zum Redaktionsschluß fertiggestellt waren. TOS-Programme im Fenster

»TOSWIN« - das Programm, das es erlaubt, mehrere TOS-Programme simultan in GEM-Fenstern laufen zu lassen - ist nun in der Version 1. 1 verfügbar. Neben kleineren Verbesserungen gefiel uns besonders die Möglichkeit, einen »Point to type«-Modus einzustellen. In dieser Betriebsart empfängt immer das Fenster unter dem Mauszeiger die Tastatureingaben, auch wenn es nicht das oberste Fenster ist. Wer häufig an Unix-Rechnern unter »X« arbeitet, wird sich freuen (immerhin erspart es häufiges Wechseln des aktiven Fensters).

Die MiNT-Libraries sind mittlerweile im Patchlevel 24 erhältlich. Neben vielen anderen Änderungen (dazu später mehr) dürfte es für deutsche Entwickler sehr interessant sein, daß die Bibliotheken nunmehr (mehr oder minder) direkt unter »Pure C« eingesetzt werden können. Für die Anpassungen haben Ulf Möller und Michael Hohmuth gesorgt.

Die Neuerungen in MiNT 0.96: Wie man sich denken kann, hat es wieder etliche Detailverbesserungen, Optimierungen und Fehlerkorrekturen gegeben (vielmehr: wird es wieder gegeben haben). Zwei grundlegend neue Eigenschaften stechen jedoch hervor: »Shared Text« und spezieller Support für Debugging.

Shared Text ist wieder einmal ein von Unix-Systemen abgeschautes Konzept (das kennt man ja von MiNT). Der Hintergrund ist, daß in Multitasking-Systemen häufig Programme mehrfach aktiv sind (besonders dann, wenn Mehrbenutzerbetrieb stattfindet). Aber auch schon bei der »normalen« Arbeit in einer Kommando-Shell und einem »make« kommt es schnell vor, daß die Shell zweimal oder noch öfter im Speicher liegt. Offensichtlich ist es erstrebenswert, dieser Speicherverschwendung Einhalt zu gebieten.

Während es bekannte Unix-Versionen wie »SunOS« einfach haben (sie können grundsätzlich die Hilfe einer PMMU in Anspruch nehmen), mußte bei MiNT härter gearbeitet werden. Der Lohn der Anstrengung ist allerdings, daß alle Rechner auch die ohne 68030 in den Genuß der Verbesserung kommen. Klären wir zunächst die Frage, was »geshared« wird und was man beachten muß: Daten- und BSS-Segment müssen natürlich für jede »Instanz« des Programms separat verwaltet werden (manche Programmierer sind zwar der Meinung, daß Variablen im Data-Segment als konstant betrachtet werden müssen, das ist allerdings schlichtweg falsch). Gemeinsam ist jedoch allen Instanzen der Programmtext. Damit verbietet sich logischerweise jeder Schreibzugriff auf das Textsegment. Selbstmodifizierende Programme können also nicht »geshared« werden (dazu gehören auch die meisten Programme, die Vektoren per XBRA verbiegen - andererseits sind diese sowieso kaum fürs »Mehrfachladen« geeignet). Wenn ein Programm ein zweites Mal geladen wird, kann natürlich das Datensegment beim besten Willen nicht mehr direkt an das Textsegment anschließen (s. Abb. 3). Die meisten Programmiersprachen gehen jedoch davon aus und sprechen Variablen im Daten- und BSS-Segment grundsätzlich mit festen Offsets relativ zur Basepage an (Beispiel für eine Ausnahme ist »Megamax-C«.

Um in den Genuß der Platzeinsparung zu kommen, muß das Programm also tatsächlich den Zeiger auf dem Beginn des Datensegments beachten. Das geht am einfachsten, wenn dieser Wert zu Programmstart in ein Adreßregister übertragen wird und dann alle Variablenzugriffe nur noch relativ zu diesem Adreßregister erfolgen.

Relative Adressierung

Wer den 68000er Befehlssatz kennt, der weiß, daß eine schnelle, adreßregisterrelative Adressierung nur dann möglich ist, wenn der Offset in einen 16-Bit-Wert paßt (anders ist es ab dem 68020er). Einfach und damit schnell genug ist die relative Adressierung also nur dann, wenn Datensegment und BSS-Segment in 64 KByte passen. Bei Durchsicht eigener Programme ist man überrascht, wie wenig Platz teilweise für diese Segmente benötigt wird (Beispiel: die erste Compilerphase des GNU-C-Compilers - selbst über 800 KByte lang - hat nur 48 KByte Daten und BSS). Mit einem kleinen Trick kann man das Datensegment noch weiter verkleinern: dazu legt man beispielsweise die String-Konstanten im Textsegment ab. So macht es »gcc« (siehe auch unsere GNU-Serie der vergangenen Monate, [2]). Auch in anderer Hinsicht ist die aktuelle Version des GNUC-Compilers bereits jetzt (Version 2.2.2) auf das neue MiNT vorbereitet: die Änderungen in MiNT wurden gleichzeitig mit den fälligen Anpassungen im Compiler und im Linker vorgenommen (Jwahar Bammi und Howard Chu haben sich darum und um die Anpassungen in der MiNT-Library gekümmert). Nützlicher Nebeneffekt: die relative 16-Bit-Adressierung erbringt gegenüber absoluter Adressierung - einen bescheidenen, aber immerhin doch merklichen Geschwindigkeitgewinn (in einem Beispiel waren es etwa fünf Prozent). Wie wir gesehen haben, können nur besonders dafür geeignete Programme »geshared« werden. MiNT erkennt solche Programme an einem neuen Bit im Programm-Header (s. Abb. 2). Normalerweise sollte ein Anwender niemals in die Verlegenheit kommen, dieses Bit verstellen zu müssen darum sollte sich der Linker kümmern, der die Programmdatei erzeugt hat.

Dennoch kann ein kleines Problem auftreten: hier und da gibt es Programmdateien, bei denen die bislang reservierten Programm-Flags auf Zufallswerten stehen (alte Versionen des Turbo-C-Linkers haben sich beispielsweise dieses Vergehens schuldig gemacht). Der MiNT-Kernel sieht‘s normalerweise gelassen und verweigert den Programmstart mit einer Fehlermeldung.

Die andere wichtige Neuigkeit im MiNT 0.96 sind die Kernel-Erweiterungen zum Debuggen anderer Prozesse. Doch wozu braucht man dafür Kernel-Unterstützung? Das ging und geht doch mit jedem residenten Debugger...

Es ist in einem Multitasking-System prinzipiell unerwünscht, daß sich Prozesse in die Exception-Vektoren der CPU einklinken. Und wer dies schon einmal unter MiNT versucht hat, kennt auch die möglichen Probleme. Doch damit nicht genug: sobald MiNT besondere Eigenschaften der PMMU nutzt, muß man erheblich mehr Schwierigkeiten umschiffen. Bei Benutzung von »Memory Protection« (die es in Ataris MiNT-Version bereits gibt), sind jegliche Zugriffe auf Daten anderer Prozesse unmöglich (Ausnahme: Der Prozeß ist durch spezielle Einstellungen in den Programm-Flags davon ausgenommen). Ferner kann es bei Benutzung eines Virtual-Memory-Systems passieren, daß jeder Prozeß ein anderes »Bild« vom Rechner hat - gleiche Speicheradressen in verschiedenen Prozessen also nicht mehr den gleichen Wert haben müssen (das kann man sogar soweit führen, daß alle Prozesse an der gleichen Basisadresse laufen). Wie so etwas implementiert werden könnte, kann und soll hier nicht beschrieben werden. Was uns interessiert, sind die Folgen.

Ähnlich wie bei der Einführung von »Shared Memory« [1]) müssen also auch hier neue Betriebssystemaufrufe implementiert werden, über die man an die Informationen des betroffenen Prozesses herankommt. MiNT stellt dafür schon immer das spezielle Dateisystem »U:\PROC« zu Verfügung, das für jeden laufenden Prozeß eine Datei enthält. So konnte man - die notwendigen Zugriffsrechte vorausgesetzt - Daten aus diesen Dateien lesen und schreiben (damit wäre also schon einmal, die Problematik der möglicherweise unterschiedlichen Adreßräume gelöst). Breakpoints werden dadurch gesetzt, daß an die passende Stelle im Programmcode eine Break-Instruktion geschrieben wird. Zusätzlich gab es bereits spezielle »Fcntl()«-Aufrufe, mit denen man die Adressen der Basepage und der MiNT-Prozeßstruktur ermitteln konnte. Neu sind Funktionen, mit denen man spezielle Traceflags einstellen und die Prozessorregister abfragen bzw. verändern kann.

Besonders wichtig ist natürlich die Behandlung von Signalen (zu denen ja auch die Prozessor-Exceptions gehören). Beim Debugging unter MiNT gehört zu jedem getraceten Programm ein tracendes Programm. Tritt ein Signal auf, wird das getracete Programm zunächst gestoppt und der Tracer erhält die Möglichkeit, den Prozeß zu inspizieren und gegebenfalls Veränderungen vorzunehmen. Danach kann er in verschiedenen Modi fortgesetzt werden (normales Fortsetzen, nur die nächste Instruktion, bis zur nächsten Verzweigung (erst ab 68020) oder Programmabbruch).

Diese Implementation des Tracings unterscheidet sich erheblich vom klassischen »ptrace()«-Aufruf, wie man ihn beispielsweise in »Unix System V« findet. Die in MiNT implementierte Methode ist allerdings keineswegs eine komplette Eigenschöpfung - ähnliche Methoden und ihre Vorteile sind beispielsweise im bekannten Buch von Maurice Bach ([4]) beschrieben: das System ist erheblich effizienter (Fread()/ Fwrite() können »beliebig« viel Daten in einem Aufruf transportieren, ptrace() hingegen immer nur ein Speicherwort) und es können beliebige Prozesse untersucht werden (nicht nur solche, die man selbst gestartet hat).

Mit dieser Ausgabe ist der fünfte Atariums-Jahrgang vollständig. Obwohl Atari zur Zeit in einer Krise steckt, die hoffentlich bald vorübergeht, kann man wohl mit Recht sagen, daß die Softwareentwicklung auf dem Atari schon lange nicht mehr (oder gar noch nie?) so interessant war, wie jetzt. (uw)

Quellennachweis:
[1] Julian E Reschke, »MiNT 0.95 - 5% vor Fertigstellung«, ST-Magazin 10/1992, Seite 104
[2] Bjarne Pohlers, »Keine Angst vorm GNU«, ST-Magazin 8/1992, Seite 44 (und folgende Ausgaben)
[3] Eric Smith, »Writing debuggers for MiNT«
[4] Maurice J. Bach: »The Design ofthe UNIX Operating System«, Prentice-Hall, Inc., New Jersey, 1986, ISBN 0-13-201799-7 Ein Beispiel für einen ProgrammHeader fürs Sharing

typedef struct
{
    WORD ph_branch; /* 0x601A */
    LONG ph_tlen;   /* Länge des TEXT-Abschnitts */
    LONG ph_dlen;   /* Länge des DATA-Abschnitts */
    LONG ph_blen;   /* Länge des BSS-Abschnitts  */
    LONG ph_slen;   /* Länge der Symboltabelle   */
    LONG ph_res1;   /* Reserviert, muß 0 sein */
    struct      /* Bitfeld für Pure C, sonst nachprüfen */
    {
        unsigned tpasize:    4; /* Bit 28...31 */
        unsigned res1:      12; /* Bit 16...27 */
        unsigned res2:       4; /* Bit 12...15 */
        unsigned shared:     1; /* Bit 11      */
        unsigned res3:       3; /* Bit 8...10  */
        unsigned protection: 4; /* Bit 4...7   */
        unsigned res4:       1; /* Bit 3       */
        unsigned malt:       1; /* Bit 2       */
        unsigned lalt:       1; /* Bit 1       */
        unsigned fload:      1; /* Bit 0       */
    } ph_prgflags;
    WORD ph_absflag;    /* 0: Relozierungsinformationen vorhanden */
} PH;

Julian F. Reschke
Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]