9.4 System-V-Interprozesskommunikation
Die drei Interprozesskommunikations-Techniken (Semaphor, Message Queue und Shared Memory) des Systems V nutzen zwar unterschiedliche Konzepte, alle drei verwenden allerdings dieselben systemweiten Ressourcen, die von mehreren Prozessen gemeinsam genutzt werden können. Somit ist mit ihnen eine Kommunikation zwischen nicht verwandten Prozessen möglich. Dabei werden über Systemaufrufe verschiedene Funktionen zur Verfügung gestellt.
9.4.1 Gemeinsamkeiten der SysV-Mechanismen
Damit Prozesse, die unabhängig voneinander sind, untereinander kommunizieren können, wird eine Kennzahl verwendet, die jeder SysV-IPC-Struktur beim Anlegen zugeordnet wird. Dabei handelt es sich um eine vom Kernel intern erzeugte, eindeutige Kennung in Form einer nicht negativen Zahl.
Um die Kennung selbst müssen Sie sich nicht kümmern, wohl aber um den Schlüssel. Der Schlüssel, häufig auch als »magische Nummer« bezeichnet, ist nötig, damit auch nicht verwandte Prozesse über diese Kennung miteinander kommunizieren können. Der Schlüssel wird vom Kernel mit der Kennung verbunden.
Um nichts durcheinander zu bringen! Ich spreche hier von einem Schlüssel (Key) und einer Kennung (Identifiers), also zwei verschiedenen Dingen. Dies sei hier erwähnt, da häufig beides als ein und dasselbe verwendet wird.
Wichtig ist auf jeden Fall die »magische« Nummer. Dieser Schlüssel, den Sie einrichten müssen, ist vom (primitiven) Datentyp key_t (long), der in der Headerdatei <sys/types.h> definiert ist. Sie können diesen Schlüssel jetzt selbst z. B. als symbolische Konstante definieren oder aber dynamisch mit der Funktion ftok() erzeugen lassen. Beim dynamischen Erzeugen haben Sie den Vorteil, dass die Nummer wirklich eindeutig auf dem System ist, was ja bei einer konstanten Angabe nicht gegeben ist. Die Syntax dieser Funktion sieht wie folgt aus:
# include <sys/types.h>
# include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
Bitte beachten Sie, dass diese Funktion nur XPG4-konform ist. Diese Funktion generiert aus dem pathname (der existieren muss) und den letzten 8 Bits von proj_id, wofür Sie auch ein char-Zeichen verwenden können, einen eindeutigen SysV-Schlüssel, der anschließend für die Funktionen msgget(), semget() oder shmget() verwendet werden kann. Bei einem Fehler gibt diese Funktion -1 zurück. Anwenden lässt sich die Funktion zum Erstellen einer »magischen« Nummer folgendermaßen:
/* key_ftok.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
int main(void) {
key_t key1, key2;
key1 = ftok(".", 'a');
key2 = ftok("/usr/include", 'x');
printf("key1: %d key2: %d\n",key1, key2);
return EXIT_SUCCESS;
}
Das Programm bei seiner Ausführung:
$ gcc -Wall -o key_ftok key_ftok.c
$ ./key_ftok
key1: 1627795980 key2: 2013677230
Ebenfalls für die Zugriffsrechte wurde ein einziges Privilegiensystem für die IPC-Objekte verwendet, das ähnlich wie das Zugriffsrechtesystem auf dem Dateizugriff ist. Dabei besitzt jedes Objekt eine Benutzer- und Gruppenidentifikation, die sich danach richtet, unter welcher UID/GID der Prozess läuft, mit dem das Objekt erzeugt wurde. Es können Lese- und Schreibrechte für den Benutzer (User), für die Gruppe (Group) und für alle anderen (Other) gesetzt werden, wie bei einer normalen Datei auch. Die Zugriffsrechte, wie auch die Kennung und der Schlüssel, sind in der Struktur ipc_perm in der Headerdatei <sys/ipc.h> definiert und können mit den entsprechenden IPC-Funktionen msgctl(), semctl() oder shmctl() vom Erzeuger des Objektes oder vom Superuser verändert werden.
9.4.2 Ein Objekt einrichten, eine Verbindung herstellen und das Objekt wieder löschen
Ganz klar, um eines der SysV-IPCs zur realisieren, muss erst ein entsprechendes Objekt erzeugt werden. Erzeugt werden diese mit den entsprechenden ..get()-Funktionen (msgget(), semget() oder shmget()). Dabei müssen Sie als Flag entweder IPC_PRIVATE setzen, womit Sie eine Verbindung zu einem bereits existierenden Schlüssel (key_t) einrichten, oder Sie geben als Flag IPC_CREAT an, um ein noch nicht existierendes Objekt mit dem Schlüssel zu erzeugen.
Da der erste Prozess meistens der Serverprozess ist, können alle anderen Prozesse (Client) mit den entsprechenden ..get()-Funktionen ohne die Angabe von IPC_CREAT, aber mit der Angabe des Schlüssels, eine Verbindung zum Objekt herstellen.
Gelöscht wird ein Objekt mit den entsprechenden IPC-..ctl()-Funktionen (msgctl(), semctl() oder shmctl()), wobei hier den Funktionen das Kommando IPC_RMID (IPC ReMoveIdentifiers) mitgegeben wird. Natürlich setzt dies entsprechende Zugriffsrechte für das Löschen voraus.
9.4.3 Datenaustausch zwischen nicht verwandten Prozessen
Sie haben zwei Möglichkeiten, um ein Objekt zur Kommunikation zwischen zwei Prozessen zu verwenden. Eine Möglichkeit ist, dass Sie ein neues Objekt erstellen, in dem der Schlüssel mit IPC_PRIVATE angegeben und diese Kennung in einer Datei abgespeichert wird. Alle anderen Prozesse können dann diese Kennung aus der Datei lesen und mit den anderen Prozessen kommunizieren. Der Nachteil liegt auf der Hand – jeder Prozess muss erst eine Datei öffnen und aus dieser lesen – was eher ineffizient ist. Daher ist die zweite Möglichkeit die bessere: Man verwendet einfach eine gemeinsame Headerdatei für alle Prozesse, worin sich der Schlüssel befindet. Über den anschließend vom Serverprogramm erzeugten Schlüssel können nun alle Clientprogramme miteinander kommunizieren. Das setzt aber voraus, dass alle Clients diese Headerdatei zur Übersetzungszeit kennen. Somit bleibt die erste Möglichkeit die einzige, zwischen wirklich nicht verwandten Prozessen eine Verbindung herzustellen.
Nachdem nun die wichtigsten Gemeinsamkeiten der drei SysV-IPCs erläutert wurden, sollen jetzt die einzelnen IPCs behandelt werden.
|