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

Aufgabe 15
Verwalten Sie mit einem Shell-Skript log ein permanentes Log-Fenster, in dem Fehlermeldungen (von anderen Kommandos) erscheinen.

log soll das ihm übergebene Kommando ausführen und dessen Fehlerkanal in das Log-Fenster umleiten. Die Standard-Ausgabe soll nicht umgelenkt werden.

  • log soll nur dann ein neues xterm-Fenster für die späteren Fehlermeldungen erzeugen, wenn es noch kein solches gibt. Das Fenster soll danach permanent (bis zu einem CTRL-C) geöffnet bleiben.

  • log soll immer zunächst im Log-Fenster ausgeben, welches Kommando die folgenden Meldungen erzeugt, dann erst das Kommando ausführen.

    Bei einem gcc-Aufruf könnte also folgendes im Log-Fenster erscheinen:

    *** error messages from "gcc xxx.c" *** xxx.c: In function `main': xxx.c:15: `j' undeclared (first use this function) ...
    Wenn kein Kommando angegeben wird (also nur "log") soll diese Ausgabe unterdrückt werden. Dieser Aufruf dient dann nur dazu, ggf. das Log-Fenster zu erzeugen.

Sie brauchen (und dürfen) keine Hilfsskripte verwenden. Sie kommen mit ganz wenigen Zeilen Shell-Skript aus.

Die Kommunikation zwischen log und dem Fenster soll mit einer FIFO "$HOME/errfifo" realisiert werden. Es soll immer genau so lange ein Log-Fenster offen sein, wie die FIFO existiert.

  • Wenn die FIFO noch nicht existiert, soll log sie anlegen und ein neues xterm-Fenster erzeugen.

  • Mit der Option `-e' führt xterm das dahinter angegebene Kommando aus. Geben Sie dort die Shell an, die mit der Option `-c' die wiederum dahinter angegebenen Kommandos ausführt. Dort soll in einer Endlosschleife mittels `cat' der Inhalt der FIFO ausgegeben werden.

  • Wenn bei aktivem xterm-Fenster ein CTRL-C gedrückt wird, wird diese Shell beendet und damit das Fenster geschlossen. Sie müssen dann auch die FIFO löschen! Dazu müssen Sie eine trap-Anweisung in die Shell-Kommandos einbauen.

Weitere hier nützliche xterm-Optionen sind "-T titel" (Titel setzen) und "-sb" (Scrollbalken aktivieren).

Aufgabe 16
Erweitern Sie die UNIX-Semaphor-Lösung zum Philosophen-Problem aus der Vorlesung wie folgt:

  1. Erreichen Sie durch geeignete Signal-Handler, daß der Tod eines Philosophen das Ende des Programms bewirkt. Der Elter muß dazu alle seine noch laufenden Kinder abbrechen. Die belegten Ressourcen (Lockfile und Semaphore) sollen bei jedem möglichen Programmende (außer durch SIGKILL) freigegeben werden!

    Beachten Sie, daß die Kind-Prozesse vor der Freigabe der Semaphore im Elter beendet werden sollten, da die Kinder sich sonst über deren Entzug beschweren.

  2. Erzeugen Sie im C++-Programm dieselbe Status-Ausgabe wie in der Version mit dem JAVA-Monitor ("thinking", "hungry", "eating" in Tabellenform, etc.).

    Verfassen Sie einfach das C++-Analogon zu der JAVA-Funktion show und rufen Sie sie nach jedem Status-Wechsel auf.

    Denken Sie daran, daß die Philosophen in fünf verschiedenen Prozessen laufen und daher bisher nicht den genauen Status ihrer Nachbarn kennen können!

    Legen Sie also mit Hilfe eines Shared-Memory-Segments ein Array mit den Status-Informationen an, auf das alle fünf Prozesse zugreifen können! Schützen Sie das Array durch (zumindest) einen Semaphor, damit Sie nicht in ungünstigen Momenten inkorrekte ("gemischte") Ausgaben erzeugen.

Hinweis: Auf den SUNs ist der Typ union semun für die Semaphoren in den Header-Files vergessen worden! Sie müssen ihn explizit selbst definieren (z.B. in semarray.h):
union semun { int val; struct semid_ds *buf; ushort_t *array; };

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

Anhang 1 Philosophen-Lösung aus der Vorlesung philo.cpp semarray.cpp semarray.h

#include <sys/types.h> #include <stdio.h> #include <iostream.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <wait.h> #include <vector.h> #include "semarray.h" semarray *chopsticks; void sigint_handler(int) { delete chopsticks; } int main() { chopsticks=new semarray("/tmp/philolock",5,1); signal(SIGINT,sigint_handler); int i; for (i=0;i<4;++i) if (fork()==0) break; if (i!=4) chopsticks=new semarray("/tmp/philolock"); srandom(time(0)+i); for (;;) { cout << i << " thinking" << endl; sleep(random()&7); cout << i << " hungry" << endl; chopsticks->sdown(2,i,(i+1)%5); cout << i << " eating" << endl; sleep(random()&7); chopsticks->sup(2,i,(i+1)%5); } }
Anhang 2 Philosophen-Monitor in JAVA dining_philosophers.java
import java.util.Random; public class dining_philosophers // Startklasse { public static void main(String[] args) // "Hauptprogramm" { Philosopher[] p=new Philosopher[5]; // Array aus Referenzen Ph_Monitor mon=new Ph_Monitor(p); for (int i=0;i<5;++i) p[i]=new Philosopher(i,mon,p); Philosopher.show(); // erste Anzeige } } class Ph_Monitor { final boolean[] chopstick; final Philosopher[] p; Ph_Monitor(Philosopher[] parr) { p=parr; chopstick=new boolean[p.length]; } synchronized void hungry(int i) throws InterruptedException { p[i].state=Philosopher.hungry; Philosopher.show(); while (chopstick[i]||chopstick[(i+1)%p.length]) wait(); chopstick[i]=chopstick[(i+1)%p.length]=true; p[i].state=Philosopher.eating; Philosopher.show(); } synchronized void full(int i) { p[i].state=Philosopher.thinking; Philosopher.show(); chopstick[i]=chopstick[(i+1)%p.length]=false; int count=0; if (p[(i+p.length-1)%p.length].state==Philosopher.hungry) ++count; if (p[(i+1)%p.length].state==Philosopher.hungry) ++count; while (count-->0) notify(); } } class Philosopher extends Thread { static final int thinking=0, hungry=1, eating=2; static final String[] s_msg={ "thinking", " hungry ", " eating " }; static Random rangen=new Random(); static Philosopher p[]; // Array aller Philosophen int state=thinking; // Zustand Ph_Monitor mon; // Monitor int num; // Numerierung Philosopher(int i, Ph_Monitor m, Philosopher[] parr) { num=i; mon=m; p=parr; start(); } public void run() // Einsprung für den Thread { try // Interrupt abfangen { for (;;) { sleep(100+rangen.nextInt()&1023); // denken mon.hungry(num); // hungrig werden sleep(100+rangen.nextInt()&1023); // essen mon.full(num); // satt sein } } catch (InterruptedException e) { } } static synchronized void show() // Anzeige aller fünf P. { int n=p.length; for (int i=0;i<n;++i) { System.out.print( (p[i].state==eating || p[(i+n-1)%n].state==eating)?"X ":"| "); System.out.print(s_msg[p[i].state]+" "); } System.out.println( (p[0].state==eating || p[n-1].state==eating)?"X ":"| "); } }
Beispielausgabe:
| thinking | thinking | thinking | thinking | thinking | | thinking | thinking | thinking | thinking | hungry | X thinking | thinking | thinking | thinking X eating X X thinking | thinking | thinking | hungry X eating X X thinking | hungry | thinking | hungry X eating X X thinking X eating X thinking | hungry X eating X X thinking X eating X hungry | hungry X eating X X thinking | thinking | hungry | hungry X eating X | thinking | thinking | hungry | hungry | thinking | | thinking | thinking X eating X hungry | thinking | | thinking | thinking | thinking | hungry | thinking | | thinking | thinking | thinking X eating X thinking | | hungry | thinking | thinking X eating X thinking | X eating X thinking | thinking X eating X thinking X
 
© 1999 Axel Rogat