=============================================== Prozesse mit der Organisation eines Token-Rings [TOC] =============================================== Das Vorlesungsbeispiel _pingpong.c_ lässt sich erweitern, indem nicht nur zwei Prozesse sich einander den Ball zuspielen, sondern $n$ Prozesse beteiligt sind. Dabei kennt jeder der $n$ Prozesse den nachfolgenden Prozess, wobei die Prozesse in einem Ring organisiert sind. D.h. bei den Prozessen $P_0, \dots, P_{n-1}$ hat $P_1$ den Prozess $P_0$ als Nachfolger, $P_2$ den Prozess $P_1$ und $P_0$ den Prozess $P_{n-1}$. Wie lässt sich der Ring organisieren? Zunächst wird $P_0$ erzeugt. Dieser wiederum erzeugt die Kinder $P_1, \dots, P_{n-1}$. Jedem der Kindprozesse wird der Nachfolger mitgeteilt. Am Ende akzeptiert $P_0$ den zuletzt erzeugten Prozess $P_{n-1}$ als Nachfolger, womit der Ring geschlossen ist. Es gibt nun genau ein Token, der zu Beginn bei $P_0$ liegt, der über das Signal _SIGUSR1_ an $P_{n-1}$ übergibt, der das wiederum an $P_{n-2}$ übermittelt etc. bis schließlich $P_1$ das Signal an $P_0$ übermittelt, womit eine Runde geschlossen ist. Aufgabe ======= Entwickeln Sie eine Funktion _tokenring_ mit folgender Schnittstelle: ---- CODE (type=c) ------------------------------------------------------------ pid_t create_tokenring(unsigned int members); ------------------------------------------------------------------------------- Der Parameter _members_ spezifiziert $n$, zurückzugeben ist dabei die Prozess-ID von $P_0$. Der Ring soll über _SIGUSR1_ das Token im untereinander wie beschrieben weitergeben. Zu Beginn soll dies wie im originalen _pingpong.c_ dadurch terminiert werden, dass das Token nicht mehr als zehnmal weitergegeben wird. Sollte der Nachfolger nicht mehr existieren, wird ebenfalls sofort aufgehört. Ergänzen Sie das mit einem Testprogramm, das die Funktion aufruft und anschließend mit _waitpid_ darauf wartet, dass $P_0$ terminiert. Damit Sie mitbekommen, ob der Ring funktioniert, sollten Sie eine Testausgabe hinzufügen, die ein Prozess zusammen mit der Prozess-ID ausgibt, sobald der Prozess im Besitz des Tokens ist. Im Fehlerfalle sollten die neu erzeugten Prozesse mit dem Exit-Code 255 terminieren. Fragen dazu =========== * Wer sollte wann den Signalbehandler für _SIGUSR1_ einsetzen? Beachten Sie dabei, dass der Hauptprozess einen Signalbehandler hierfür nicht benötigt. * Wie erfährt ein Prozess aus dem Ring, dass der Nachfolger nicht existiert? Vorlage ======= Hier ist das Beispiel aus der Vorlesung. Es wäre aber angemessen, statt _signal_ die Funktion _sigaction_ zu verwenden. Es genügt ein traditioneller Signalbehandler mit einem Parameter. Entsprechend ist in der `struct sigaction` die Komponente `sa_handler` zu initialisieren. :import: session03/pingpong.c [fold] :navigate: up -> doc:index next -> doc:session03/page02