Das Paket Interprozesskommunikation umfasst drei Mechanismen:
Nachrichten (messages) sind formatgebundene Datenströme, die von Prozessen an beliebige andere Prozesse gesendet werden können (dazu werden folgende Systemaufrufe verwendet:
msgget()
,msgsnd()
,msgrcv()
,msgctl()
).Gemeinsam nutzbare Speicherbereiche (shared memory) erlauben, dass Prozesse Teile ihres virtuellen Adressraumes mit anderen Prozessen teilen (dazu werden folgende Systemaufrufe verwendet:
shmget()
,shmat()
,shmdt()
,shmctl()
).Semaphoren ermöglichen die Synchronisation der Ausführung von Prozessen (dazu werden folgende Systemaufrufe verwendet:
semget()
,semop()
,semctl()
).
Die den drei Mechanismen gemeinsamen Aspekte werden nachfolgend beschrieben. Die Beschreibung gliedert sich in die Abschnitte:
Einrichten eines Kommunikationselements (Nachrichten-Warteschlange, gemeinsam nutzbarer Speicherbereich, Semaphore)
Datenstrukturen
Statusinformationen abfragen oder ändern
Dabei steht xxx jeweils für msg
, sem
oder shm
.
Jedes Kommunikationselement (Nachrichten-Warteschlange, Gemeinsamer Speicherbereich, Semaphor) wird durch eine positive ganze Zahl identifiziert. Die Nummer wird beim Einrichten des Kommunikationselements xxxget()
vom System vergeben. Der Benutzer kann zusätzlich einen Zahlenschlüssel als Namen eines von ihm erzeugten Kommunikationselements festlegen.
Zu jedem Mechanismus existiert eine Tabelle, deren Einträge alle Kommunikationselemente des jeweiligen Mechanismus enthalten.
Dabei enthält jeder Eintrag einen vom Benutzer gewählten Zahlenschlüssel als Namen, durch den der Eintrag identifiziert wird.
Einrichten eines Kommunikationselements
Für jeden Mechanismus gibt es einen Systemaufruf xxxget()
, mit dem ein neues Element erzeugt werden kann oder ein bereits existierendes Element für einen Prozess verfügbar gemacht werden kann. Die Parameter der Systemaufrufe xxxget()
sind ein vom Benutzer gewählter Zahlenschlüssel key als Benutzername und ein Schalter xxxflg.
key | Das Betriebssystem sucht in der zugehörigen Tabelle nach einem Eintrag, der durch den Schlüssel bezeichnet wird. Prozesse können den Systemaufruf xxx |
xxxflg | Der Schalter beeinflusst, ob und wie auf einen Eintrag zugegriffen werden kann, sowie gegebenenfalls die Zugriffsrechte. Wenn der Schalter Falls bereits ein Eintrag mit dem angegebenen Schlüssel existiert, müssen die neun rechten Bits des Schalters eine Teilmenge der Zugriffsrechte des Eintrags sein, andernfalls scheitern die Systemaufrufe xxx |
Die Systemaufrufe xxxget()
liefern eine vom Betriebssystem ausgewählte eindeutige positive ganze Kennzahl (Systemkennzahl xxxid), die in den anderen, dem jeweiligen Mechanismus zugehörigen Systemaufrufen verwendet wird. Die Kennzahlen funktionieren wie die Dateideskriptoren - wie sie z. B. open()
, dup()
und pipe()
liefern -, mit der Ausnahme, dass jeder Prozess, der ihren Wert kennt, sie verwenden kann. D.h. sie müssen nicht vererbt werden, um gültig zu sein. Jeder gemeinsam nutzbare Speicherbereich (shared memory), jede Nachrichtenwarteschlange und jede Semaphorenmenge wird so durch die Kennzahl für gemeinsam nutzbaren Speicherbereich (shmid), die Semaphorenkennzahl (se-mid) bzw. die Warteschlangenkennzahl (msqid) identifiziert.
Datenstrukturen
Jeder Kennzahl ist eine Datenstruktur zugeordnet, die die operationsbezogenen Daten der durchzuführenden oder durchgeführten Operationen enthält. Diese Datenstrukturen (ms-qid_ds
, semid_ds
, shmid_ds
) sind in sys/shm.h
, sys/sem.h
und sys/msg.h
beschrieben. Unter anderem enthalten diese Datenstrukturen die Prozessnummer des letzten Prozesses, der eine Operation durchgeführt hat (Nachricht senden oder empfangen, auf gemeinsamen Speicher zugreifen usw.), und die Zeit des letzten Zugriffs.
Alle Datenstrukturen enthalten Eigentümerinformationen und eine ipc_perm
-Struktur (siehe sys/ipc.h
), auf Grund der Prozessen, die IPC-Funktionen verwenden, Schreib-/Leserechte (bei Semaphoren Änder-/Leserechte) erteilt oder verweigert werden. Die ipc_perm
-Struktur enthält die effektive Benutzer- und Gruppennummer des Prozesses, der den Eintrag erstellt hat (xxx_perm.cuid und xxx_perm.cgid), sowie eine Benutzer- und eine Gruppennummer (xxx_perm.uid und xxx_perm.gid), die auch durch den Systemaufruf xxxctl()
gesetzt werden können. Dazu kommt ein Bitfeld von Zugriffsrechten in der Komponente mode
der ipc_perm
-Struktur. Die Bits sind wie folgt belegt:
Bit | Bedeutung |
0400 | lesen (Eigentümer) |
0200 | schreiben (Eigentümer) |
0040 | lesen (Gruppe) |
0020 | schreiben (Gruppe) |
0004 | lesen (Andere) |
0002 | schreiben (Andere) |
Die Struktur vom Typ ipc_perm
hat den Namen shm_perm
, sem_perm
oder msg_perm
, je nach verwendetem Mechanismus. Lese- und Schreib-/ Änderungsberechtigungen werden einem Prozess erteilt, wenn eine oder mehrere der folgenden Bedingungen zutreffen.
Die effektive Benutzernummer eines Prozesses mit Sonderrechten.
Die effektive Benutzernummer des Prozesses ist identisch mit xxx_perm.cuid oder xxx_perm.uid in der der IPC-Kennzahl zugeordneten Datenstruktur, und das entsprechende Bit für Eigentümer in xxx_perm.mode ist gesetzt.
Die effektive Benutzernummer des Prozesses ist nicht identisch mit xxx_perm.cuid oder xxx_perm.uid, aber die effektive Gruppennummer des Prozesses ist identisch mit xxx_perm.cgid oder xxx_perm.gid in der der IPC-Kennzahl zugeordneten Datenstruktur, und das entsprechende Bit für Gruppe in xxx_perm.mode ist gesetzt.
Die effektive Benutzernummer des Prozesses ist nicht identisch mit xxx_perm.cuid oder xxx_perm.uid, und die effektive Gruppennummer des Prozesses ist nicht identisch mit xxx_perm.cgid oder xxx_perm.gid in der der IPC-Kennzahl zugeordneten Datenstruktur, aber das entsprechende Bit für Andere in xxx_perm.mode ist gesetzt.
In allen anderen Fällen wird keine Berechtigung erteilt.
Statusinformationen abfragen oder ändern
xxxctl()
Für jeden Mechanismus gibt es einen Systemaufruf xxxctl()
, mit dem der Status eines Eintrags abgefragt werden kann, Statusinformation gesetzt oder ein Eintrag aus dem System entfernt werden kann.
Fragt ein Prozess den Status eines Eintrags ab, so prüft das Betriebssystem, ob der Prozess die Leseberechtigung hat, und kopiert danach Daten aus dem Tabelleneintrag in die vom Benutzer angegebene Struktur.
Will ein Prozess die Parameter des Eintrags neu setzen, dann prüft das Betriebssystem, ob die effektive Benutzernummer des Prozesses mit der Benutzernummer des Eintrags oder mit der Benutzernummer des Erstellers des Eintrags übereinstimmt bzw. ob die effektive Benutzernummer die eines Prozesses mit Sonderrechten ist. Um Parameter neu zu setzen, ist Schreibberechtigung allein nicht ausreichend. Das Betriebssystem kopiert die vom Benutzer angegebenen Daten in den Tabelleneintrag, setzt dabei die Benutzernummer, die Gruppennummer, die Zugriffsrechte und andere von der Art des Mechanismus abhängige Felder. Nicht verändert werden die Felder mit der Benutzer- und Gruppennummer des Erstellers des Eintrags; dadurch verbleiben dem Ersteller des Eintrags immer Kontrollrechte.
Will ein Prozess einen Eintrag entfernen, stellt das Betriebssystem sicher, dass die effektive Benutzernummer des Prozesses mit einer der Benutzernummern in der
ipc_perm
-Struktur übereinstimmt. Nachdem ein Eintrag entfernt wurde, ist es nicht mehr möglich, mit der alten Kennzahl auf den Eintrag zuzugreifen.
Hinweis
Die Verwendung der IPC-Mechanismen verlangt hohe Sorgfalt, da nicht nutzbare oder nicht benötigte IPC-Elemente vom Betriebssystem nicht in allen Fällen erkannt werden. Im Betriebssystem gibt es keine Aufzeichnungen darüber, welche Prozesse auf ein IPC-Element zugreifen - in der Tat kann jeder Prozess auf ein IPC-Element zugreifen, dem die richtige Kennzahl bekannt ist und der zugriffsberechtigt ist, auch wenn er nie einen Systemaufruf xxxget()
abgesetzt hat. Deshalb kann das Betriebssystem die IPC-Strukturen nicht implizit bereinigen (z.B. bei Prozessende).
Die IPC-Mechanismen sollten nur bei extremen Performance-Anforderungen verwendet werden.