ATARIs und ATARIaner sind überall, auch noch im Jahr 1996. Dies bestätigte sich erst jüngst wieder, als ich auf dem Straßenbasar von Assuan einen No-Name-Nachbau der 2600er-Spielkonsole sichtete. Und ein paar Tage später bin ich dann auch noch in der Grabkammer der vermutlich 4500 Jahre alten Mykerinos-Pyramide von Gizeh Oliver Buchmann von Application Systems Heidelberg begegnet...
Zurück in Deutschland stand ein Ausflug auf die CeBIT auf dem Plan. Trotz der erhöhten Eintrittspreise war es schon am ersten Tag recht voll. ATARIs habe ich keine gesehen, wohl aber einige 68K-Amigas auf dem Stand von Escom und bei Motorola Computersysteme(!). Dort konnte man auch allerlei PowerPC-Syste-me sehen, sowohl von Apple, Motorola als auch von anderen Herstellern. Als Betriebssysteme fehlten bei flüchtiger Suche OS/2 für PowerPC (gestorben?) und Linux (noch zu früh). Apple zeigte „Pippin", die von BanDai entwickelte Spielkonsole auf PowerMac-Basis. Sie soll das billige Internet-Terminal werden, auf das die gesamte Branche mit Ausnahme von Bill Gates wartet.
Ansonsten wurde die Messe von Telekommunikation und dem Thema Internet bestimmt. Wer hätte noch vor drei bis vier Jahren geahnt, daß das Internet das dominante Thema und Mosaic bzw. Netscape seine „Killerapplikation" werden würden?
Auch zum Thema ATARI gab es im vergangenen Monat ein paar neue Informationsbröckchen, wenn auch nicht auf der CeBIT: von ATARI-offizieller Seite wurde bestätigt, daß auch künftig die Jaguar-Projekte weitergeführt würden (innerhalb der Firma JTS und dem ATARl-Logo). Man wird sehen.
Nun möchte ich mich aber endlich mal wieder einem "richtig" technischen Thema zuwenden. Eine wichtige Eigenschaft eines leistungsfähigen Multitaskingsystems ist die Fähigkeit, Prozesse untereinander kommunizieren zu lassen und auf ,von außen' auftretende Ereignisse zu reagieren. Wer schon mal unter GEM programmiert hat, kennt natürlich die verschiedenen AES-Ereignisse oder auch die Möglichkeiten zum Message Passing mittels appl_write(). Diese Funktionen nutzen jedoch nichts in TOS-Programmen, und so bietet MiNT auch GEM-losen Programmen einige Alternativen.
Die wichtigste Rolle spielen dabei die .Signale', die fast unverändert aus BSD-Unix und dem POSIX-Standard (P1003.1) übernommen wurden. Unter einem MiNT-Signal stellt man sich am Besten einen Mittelweg zwischen einem AES-Ereignis und einem Flag vor. Mit ersterem hat es gemeinsam, daß es entweder vom Kernel oder von einer anderen Applikation geschickt worden sein kann. Dabei transportiert es selbst allerdings keine weitere Information, zu deutsch: mittels des Signals erfährt man nur, daß es etwas passiert ist. Genauere Details muß man dann über andere Mechanismen erfragen. Einweiterer wichtiger Unterschied ist, daß man die Signale nicht etwa selbst erfragt (wie bei den AES-Event-Funktionen), sondern der Kernel selbsttätig eine passende Signalbehandlungsroutine im eigenen Programm aufruft: den Signal-Handler.
Insgesamt gibt es 32 verschiedene Signale, von denen die meisten mit festen Bedeutungen vorbelegt sind. Für jedes Signal kommen verschiedene Aktionen in Betracht: Ignorieren (beispielsweise Signal 0 ,SIG-NULL'), Programm beenden (Beispiel: Signal 9 ,SIG-KILL') oder eigene Signal-Routinen aufrufen (je nach Programm).
Die Signal-Nummern entsprechen übrigens genau der Option, die man auch dem Unix-Kommando .kill' auf den Weg gibt (ATARI-Version in meiner Sammlung von MiNT-Tools: minttl*.tos in Maus Münster 2, bzw. per ftp://ftp.uni-muenster.de /pub/atari/Gemini). Das berüchtigte ,kill 9 ‹process-id›‘ verschickt also das Signal SIGKILL, das vom Prozeß nicht abgefangen werden kann und den Prozeß terminiert. ,kill ‹process-id›‘ hingegen sendet das Signal SIGTERM (15), das vom Prozeß selbst behandelt werden kann.Auch das Löschen einer Datei in "u:\proc" führt dazu, daß der Kernel dieses Signal verschickt.
Die Kontrolle über die Beendigungen Prozessen ist in der Tat eine der wichtigsten Aufgaben für die Signale. Weitere Signalnummern in diesem Zusammenhang sind: SIGHUP (Signal 1: Terminalverbindung wurde beendet), SIGINT (Signal 2: Unterbrechung per Control-C), SIGQUIT (3: eine schärfere Version von SIGINT), SIGSTOP und SIGTSTP (17 und 18: Prozeß schlafen legen) und SIGCONT (19: Prozeß fortsetzen).
Andere Signale befassen sich mit den fatalen Fehlern, die in der Regel zu einem Absturz führen. Unter MiNT hingegen kann man sie in der Regel abfangen und gezielt behandeln. Beispiele sind etwa SIGBUS (10: Bus Error) oder SIGS-EGV (11: Illegal memory reference).
In meinem Programmbeispiel (siehe Listing) will ich allerdings einen .Exoten' unter den Signalen benutzen: SIGWINCH (28: Window Change) wird von Window Managern wie MiniWin verschickt, wenn sich die Fenstergröße geändert hat. TOS-Programme wie ,more‘ oder ein TOSEditor können diese Information nutzen, um mit einem speziellen Fcntl-Aufruf die neuen Ausmaße des Terminals zu erfragen. Ein gutes Beispiel für eine solche Signalbehandlung findet sich auch in der "Mupfel": immer, wenn SIGWINCH eintrifft, werden die Environmentvariablen ROWS und COLUMNS aktualisiert.
Schließlich will ich mich noch der Frage zuwenden, auf welche Weise man denn AES-Ereignisse und Signalbehandlung kombinieren kann. Die Antwort lautet leider „nur schlecht“. Ein gutes Beispiel wäre eine GEM-Anwendung, die auf SIGTERM genauso reagieren soll wie auf das AES-Ereignis APTERM, denn dann könnte man es per Löschen aus ,u:\proc' auf saubere Art und Weise beenden. Leider kann man aus dem Signal-Handler für SIGTERM keine AES-Aufrufe machen, und so bleibt nur die Möglichkeit, eine globale Variable zu setzen und diese zyklisch aus der evnt_multi-Schleife heraus abzufragen.
Weitere Informationen zum Thema MiNT-Signale befinden sich in der Datei MINT.DOC aus dem MiNT-Dokument-Archiv (mint 112d.zoo) sowie in den Manual-Pages zu den einzelnen GEMDOS-Signal-Funktionen. Soviel für diesen Monat - und nächsten Monat gibt es dann das 100. ATARIUM!
Julian Reschke
1: /*
2: (C)1996 MAXON Computer
3: **Autor:** Julian Reschke
4: Beispielprogramm zur Signal-
5: Programmierung
6: */
7:
8: #include <stdio.h>
9: #include <tos.h>
10:
11: #define TIOCGWINSZ (('T'« 8) | 11)
12:
13: struct winsize {
14: short ws_row;
15: short ws_col;
16: short ws_xpixel;
17: short ws_ypixel;
18: };
19:
20: static void
21: report size (void)
22: {
23: struct winsize win;
24: long ret;
25:
26: ret = Fcntl (-1, (long)&win, TIOCGWINSZ);
27:
28: if (ret == 0)
29: printf ("rows: %d, columns: %d\n",
30: win.ws_row,
31: win.ws_col);
32: else
33: printf ("error %ld on Fcntl\n", ret);
34: }
35:
36: static void cdecl
37: sigwinch_handler (long Big)
38: {
39: (void) sig; /* unused */
40:
41: report_size();
42: }
43:
44: void
45: main (void)
46: {
47: Psignal (SIGWINCH, (void *) sigwinch_handler);
48:
49: report_size ();
50:
51: while (1)
52: Syield ();
53: }