BUGH Wuppertal Fachbereich 7 - Mathematik Axel Rogat
Betriebssysteme und betriebssystemnahes Programmieren
Übungsblatt 5

Aufgabe 11
Schreiben Sie ein C-Programm, das in der Titelzeile des xterm-Fensters, in dem die Shell läuft, eine Zeitanzeige darstellt, die jede Sekunde aktualisiert wird.

Das Format der Anzeige soll "hh:mm:ss" (Stunde, Minute, Sekunde) sein. Während der Zeitanzeige soll eine Kopie der Standard-Shell laufen. Wenn diese (z.B. durch "exit") beendet wird, soll auch die Zeitansage zuende sein, und in der Titelzeile soll wieder "xterm" erscheinen.

Hinweise:

  • xterm-Steuersequenzen werden später in der Vorlesung besprochen. Die Sequenz zum Setzen des Titels lautet
    "<ESC>]2;text<CTRL-G>"
    In der Shell können Sie also den Titel wie folgt verändern:
    echo "<CTRL-V><ESC>]2;text<CTRL-V><CTRL-G>"
    Benutzen Sie im Programm beispielsweise folgende Funktion:
    void xterm_settitle(const char *s) { write(1,"\033]2;",4); write(1,s,strlen(s)); write(1,"\007",1); }
  • Starten Sie die neue Shell einfach durch einen system-Funktionsaufruf. Den Pfad der Standard-Shell erhalten Sie aus der Umgebungsvariablen SHELL.

    Achtung: Auf den SUNs müssen Sie vor dem system-Aufruf die Standard-Eingabe mit fsync(0) zurücksetzen, da sich die aufgerufene Shell sonst sofort wieder verabschiedet!

  • Benutzen Sie die Intervall-Timer (mittels setitimer), um sich jede Sekunde ein Signal schicken zu lassen.

  • Damit Sie den Handler nicht immer wieder neu setzen müssen, verwenden Sie die Funktion sigaction, um die Signal-Behandlung zu definieren.

    Vorsicht bei der Initialisierung der Struktur sigact auf den SUNs: Die Member-Reihenfolge ist dort anders als in der Version im Skript und entspricht auch nicht der Auflistung in der man-Page. Schauen Sie in /usr/include/sys/signal.h nach!

  • Die aktuelle Zeit erfahren Sie mit den Funktionen time und localtime (aus time.h, genaueres siehe die man-Pages), beispielsweise wie folgt:
    time_t t=time(0); struct tm *lt=localtime(&t); cout << lt->tm_hour << ',' << lt->tm_min << ',' << lt->tm_sec << endl;

Aufgabe 12
a)  Schreiben Sie ein C-Programm, das mit fork genau fünf neue Prozesse erzeugt. Zum Testen sollen alle sechs Prozesse ihre PID ausgeben.

Wenn Sie es geschickt anstellen, kommen Sie für die Verzweigung mit einem Befehl (und ohne Schleife) aus!

b)  Realisieren Sie in C eine Pipeline aus fünf einzelnen Pipes, die sechs Programme verbinden. Gehen Sie vor wie im folgenden beschrieben.

Ihr Programm soll genau folgendem Shell-Skript topwords entsprechen. Es gibt die n am häufigsten vorkommenden Worte in den als Argumente angegebenen Dateien (und ihre exakte Anzahl) aus:

if test $# -ge 2 ; then num=$1 if test $num -gt 0 2>/dev/null ; then shift 1 cat $* | tr -sc A-Za-z '\012' | sort | uniq -c | sort -rn | sed ${num}q fi fi
Achtung: Das tr auf den SUNs funktioniert nicht korrekt. Benutzen Sie dort bitte die GNU-Version aus "/opt/share/gnu/bin"!

Zu den sechs Bestandteilen der Pipeline:

  • cat gibt alle angegebenen Dateien auf seine Standard-Ausgabe aus;

  • tr verwandelt Folgen von Nicht-Buchstaben in einen Zeilenumbruch, so daß es seine Standard-Eingabe in Worte zerlegt und diese zeilenweise weitergibt;

  • sort sortiert diese Wortliste, so daß gleiche Worte in aufeinanderfolgenden Zeilen erscheinen;

  • uniq löscht Mehrfachzeilen und stellt der überlebenden Zeile die Vielfachheit voran

  • sort sortiert absteigend numerisch nach der ersten Spalte (also der Vielfachheit);

  • sed gibt genau die ersten $num Zeilen aus.

Angewandt auf den HTML-Quelltext dieses Übungsblatts ("topwords 5 ueb5.html" oder "cat ueb5.html | topwords 5") wird beispielsweise folgende Ausgabe erzeugt:

135 B 99 TT 29 Sie 25 die 23 lt
Hinweise:

  • Überprüfen Sie zu Beginn, ob die Maximalanzahl n angegeben wurde (und größer 0 ist), und melden Sie sonst einen Fehler.

    Stellen Sie außerdem mit stat- und access-Aufrufen fest, ob es die ggf. angegebenen Dateien überhaupt gibt, und ob es sich um lesbare reguläre Dateien handelt (ansonsten würde der cat-Befehl eine eigene Fehlermeldung ausgeben).

  • Erzeugen Sie in einer Schleife mit fork die notwendigen fünf neuen Prozesse. Passen Sie aber auf, daß Sie nicht versehentlich zu viele Prozesse erzeugen!

  • Legen Sie mit pipe und dup2 die Pipelines, analog zum Beispiel im Skript. Vergessen Sie nicht, den jeweils nicht benutzten Kanal und den nicht mehr benötigten Standard-Kanal zu schließen!

  • Laden Sie die sechs neuen Programme jeweils mit execlp-Aufrufen. Beachten Sie, daß beim sed-Aufruf die Anzahl in das Aufrufargument eingesetzt werden muß (z.B. mit sprintf).

    Für das cat eignet sich ein execvp-Aufruf besser, da die Aufrufargumente (die angegebenen Dateinamen) so direkt weitergegeben werden können.

  • Überprüfen Sie, daß das ganze Programm wieder als Filter in andere Pipelines eingesetzt werden kann!

email: axel@math.uni-wuppertal.de Zurück Abgabe: 31.5.1999
 

© 1999 Axel Rogat