============================================== Organisation des Token-Rings als Prozessgruppe [TOC] ============================================== Damit sich der Token-Ring leichter kontrollieren lässt, wäre es sinnvoll, hierfür eine Prozessgruppe anzulegen mit $P_0$ als Repräsentanten der Prozessgruppe. Zur Erinnerung: Ein Prozess (erster Parameter) wird mit dem Systemaufruf _setpgid_ einer Prozessgruppe zugeordnet. Wenn der zweite Parameter 0 ist, wird eine neue Prozessgruppe erzeugt, die von dem im ersten Parameter identifizierten Prozess repräsentiert wird: ---- CODE (type=c) ------------------------------------------------------------ int setpgid(pid_t pid, pid_t pgid); ------------------------------------------------------------------------------- Prozessgruppen können nicht nur bei _waitpid_ angegeben werden, sondern auch bei _kill_. Das ermöglicht es, ein Signal an die gesamte Prozessgruppe zu leiten. Aufgabe ======= Entwickeln Sie Ihre Lösung dahingehend weiter, dass * der Prozess $P_0$ zum Repräsentanten einer Prozessgruppe wird, der die Prozesse $P_0, \dots, P_{n-1}$ angehören, * die Zahl der Runden nicht mehr begrenzt ist und stattdessen der Erzeuger von $P_0$ eine Sekunde nach dem Aufruf von `create_tokenring` das Signal _SIGTERM_ an die Prozessgruppe des Rings sendet, * keine Ausgabe mehr erfolgt, wenn ein Prozess ein Token erhält, * die Zahl der eingegangenen _SIGUSR1_-Signale gezählt wird und * $P_0$ einen Signalbehandler für _SIGTERM_ einrichtet, ohne diesen weiter zu vererben, * beim Eintreffen von _SIGTERM_ $P_0$ kontrolliert die Schleife beendet, während $P_1, \dots, P_{n-1}$ ganz normal mit _SIGTERM_ beendet werden und * $P_0$ am Ende noch vor dem _exit_ die Zahl der eingegangenen _SIGUSR1_-Signale ausgibt. Fragen ====== * Wenn der Hauptprozess nach der Rückkehr von `create_tokenring` _SIGTERM_ an die Prozessgruppe schickt, könnte es sein, dass $P_0$ den entsprechenden Signalbehandler noch nicht eingesetzt hat. Wie könnte dieses Fenster geschlossen werden? * Wie kann der Abbau der Prozessgruppe wohldefiniert erfolgen? Bedenken Sie, dass zwischen einer Abfrage, ob _SIGTERM_ bereits eingegangen ist und dem Aufruf von _pause_ möglicherweise _SIGTERM_ eingeht und der Prozess anschließend in _pause_ auf Dauer hängt, weil keine weiteren Signale kommen. Um das Problem zu lösen, ist es sinnvoll, neben _sighold_ und _sigrelse_ auch die Funktion _sigsuspend_ in Betracht zu ziehen, die wie _pause_ funktioniert, aber mit der gegebenen Menge während des Wartens blockierter Signale arbeitet: ---- CODE (type=c) --------------------------------------------------------- int sigsuspend(const sigset_t *mask); ---------------------------------------------------------------------------- Das kann dann etwa so genutzt werden, indem _sigsuspend_ eine leere Maske erhält: ---- CODE (type=c) --------------------------------------------------------- sighold(SIG...); if (/*...*/) { sigset_t empty_set; sigemptyset(&empty_set); sigsuspend(&empty_set); /* we can be interrupted by SIG... */ } sigrelse(SIG...); ---------------------------------------------------------------------------- :navigate: up -> doc:index back -> doc:session03/page02 next -> doc:session03/page04