Ein UNIX-Proßes ist eine sequentielle zeitliche Folge von Aktionen, die durch eine sequentielle Folge von Instruktionen verursacht wird.
Erweiterte Kommunikation:
Ein Semaphor ist eine Flagge, die zwei oder mehrere Prozesse daran hindert, auf die gleichen Betriebsmittel zur gleichen Zeit zuzugreifen.
Eine Message ist eine kleine Datenmenge, die an eine Massage-Queue geschickt werden kann. Jeder Prozeß mit den passenden Rechten kann Messages aus einer Massage-Queue erhalten.
Shared-Memory (gemeinsame Speicherbereiche) bietet die schnellste Art der Prozeßkommunikation. Hierbei wird ein und derselbe Speicherbereich über den Adreßraum von zwei oder mehr Prozessen gelegt.
execl()-Funktion
Aufruf:
execl( Datei, Arg1, Arg2, ... , Argn, 0);
execl weist UNIX an, daß durch Datei bezeichnete Programm in den Hauptspeicherbereich des aktuellen Prozesses zu laden und auszuführen, wobei dem Programm die Argumente Arg1 bis Argn übergeben werden. Die Null kennzeichnet das Ende der Eingabekette.
Der Code- und Datenbereich des durch execl() aktivierten Programmes wird im aktuellen Programm überlagert.
Die Prozeßumgebung bleibt bestehen, d.h. offene Dateien, Benutzeridentifikation, das aktuelle Verzeichnis sowie die Interprozeßverbindungen sind im aufgerufenen Programm verfügbar.
In UNIX gibt es nur eine einzige Art, einen neuen Benutzerprozeß zu erzeugen.
Aufruf:
ProzessNr = fork();
Die Anweisung fork() erstellt eine exakte Kopie vom aktuellen Prozeß.
Der neue Prozeß (Kindprozeß) besitzt den Datenbereich, den Codebereich und die Prozeßumgebung des Elternprozesses. Beide Prozesse laufen parallel und asynchron weiter.
Die Unterscheidung wird durch die Unterstellung des Kindprozesse zum Elternprozeß vorgenommen. Im Elternprozeß gibt fork() die Prozeßnummer des Kindprozesses zurück.
Im Kindprozeß wird 0 zurückgegeben.
Ruft ein Prozeß die Systemfunktion wait() auf, so wird dieser Prozeß angehalten bis einer seiner Kindprozesse terminiert ist.
Aufruf:
ProzessNr = wait (Status);
Status gibt den Grund für die Terminierung an.
Prozesse terminieren sich durch exit()
Aufruf:
exit(Status);
Bei terminieren des Prozesses wird der Hauptspeicherbereich (Code und Datenbereich) freigegeben, offene Dateien geschlossen und der Prozeß von der systeminternen Prizeßverwaltung abgemeldet.
Die Datenübergabe von einem Prozeß zu einem anderen wird durch s.g. Pipe in UNIX realisiert.
Eine Pipe ist ein Einweg-Kommunikationskanal. Mit write() werden Daten in diesen Kanal hineingeschrieben, mit read() herausgelesen.
Wird die Pipe voll, so wird der schreibende Prozeß von UNIX aus suspendiert.
Ist die Pipe leer so wird der lesende Prozeß angehalten.
Aufruf:
Staus = pipe ( PipeDD)
Pipe gibt ein Dateideskriptorpaar zurück.
PipeDD[1] für die Schreibseite
PipeDD[0] für die Leseseite
Mit der close() -Anweisung wird eine Seite des Kanal geschlossen.
Aufruf:
close(KommKanal[0]); /* Leseseite schließen */
Signale dienen dazu, einem Programm asynchrone Ereignisse mitzuteilen.
Bei asynchronen Ereignissen in der Programmausführung kommunizieren die Prozesse mittels Signale.
Möglichkeiten:
Signalursachen:
Empfängt ein Prozeß ein Signal, so wird dieser in den meisten Fällen abgebrochen.
Mittels der Anweisung signal() können Signal im Programm behandelt werden.
(signal.h)
signal( Signalnummer , SIG_IGN ); /* Signal ignorieren */
signal( Signalnummer , SIG_DFL ); /* Signal mit Standardaktion behandeln */
signal( Signalnummer , Funktion ); /* Signal mit einer Benutzerfunktion behandeln */
Um unterschiedliche Netzwerke und Protokolle zu unterstützen, spielt sich die Kommunikation jeweils nur in einem bestimmten Kommunikationsbereich ab. Innerhalb eines Bereichs findet alle Kommunikation über Sockets (Sockel,Stecker) statt. Sockes stellen die Verbindungspunkte beim Datenaustausch mit anderen Sockets innerhalb eines Bereichs dar. Prozesse benützen die Sockets zum Senden und Empfangen von Nachrichten.
Aufruf:
Datendeskriptor=socket(Domain,Typus,Protokoll)
Typus legt die Behandlung wie Flußkontrolle Zuverlässogkeit ect.
wichtige Typen:
Datagram: Alle Daten sind mit genügend Information ausgestattet, um selbständig und unabhängig von den anderen Paketen ins Ziel zu gelangen.
Virtual Circuit: Dieser Typ garantiert einen flußkontrollierten und fehlerfreien Datenstrom zwischen den Verbindungspunkten.
Der dritte Parameter der socket()-Anweisung legt das Protokoll fest, das die Kommunikation innerhalb einer Domain regelt. Für jede Domain existiert pro Typ ein Standartprotokoll.
Ist der Parameter Null wird das (TCP) Protokoll benutzt.
Mittels eines solchen Mechanismus läßt sich eine Server-Client- Kopplung zwischen Prozessen realisieren.
Ein Server ist dabei ein Dienstleistungsprogramm, das bestimmte Aufgaben übernimmt.
Cliets sind Prozeße die diese Dientsleistung in Anspruch nehmen.
Zur Programmierung:
Der Server erstellt ein Socket und wartet in einer endlosen Schleife auf die Serviceanfragen der anderen Prozesse. Die Clients müssen nur diesen Socket kennen, um mit ihm in Verbindung zu treten.
Die Struktur kann wie folgt beschrieben werden.
#include <sys/types.h>
#include <sys/socket.h>
main() /* Server*/
{
int s_des, neuer_s_des;
int name_laeng;
struct sockaddr ext_name;
/* Name und Länge in 'ext_name' kopieren */
/* Erstellten des Socket im lokalen Bereich AF_UNIX mit dem Servicetyp SOCK_STREAM */
s_des = socket(AF_UNIX,SOCK_STREAM,0) ;
/* Bekanntmachen des Sockes gegen außen */
bind(s_des,&ext_name,sezeof)ext_name));
/*Anzahl der Verbindungen festlegen */
listen(s_des,ANZ_VERB);
/*Warte auf Service-Anfragen */
while((neuer_s_des=accept(s_des,&ext_name,&name_laenge))!=-1)
{ /* Verarbeitung der Anfragen des akzeptierten Clienten */
}
}
Die eigentliche Datenübertragung wird mit read() bzw. write() oder mit sent() bzw. recv() realisiert.
Beim verbindungslosen Sockets (Typ Datagram) erfolgt die Kommunikation mit den Aufrufen sentto() und recvfrom(), die jeweils ein eingenständiges Datenpacket übermitteln.
Um Prozesse auf verschiedene, durch ein Netz gekoppelte Rechner zu verteilen, werden zusätzliche Informationen über Adressen, zu verwendende Protokolle, Ports ect benötigt.
Dieses ist in den Bibliotheksfunktionen genauer spezifiziert.
Ein Client-Prozess erstellt ebenfalls zuerst einen Socket im Bereich AF_UNIX. Sobald sie zur Verarbeitung der Daten bereit sind, wird die Verbindung mit dem Serverprozeß durch connect() durchführt.
Die Struktur hat eine folgende Form:
#include <sys/types.h>
#include <sys/socket.h>
main() /* Client*/
{
int s_des;
int name_laeng;
struct sockaddr ext_name;
s_des =socket(AF_UNIX,SOCK_STREAM,0);
/*Name und Länge in ext_name kopieren und dann die Verbindung aufbauen */
connect(s_des,&ext_name,name_laenge);
/* Wenn Verbing so Beginn der Verarbeitung */
...
}
Mittels der vorgestellten Möglichkeiten der Programmkopplung unter UNIX können folgende Schnittstellen, die durch eine Grafik veranschaulicht werden, zum WWW - Browser erstellt werden
Kopplung als Sever-Client
Kopplung mit verwandten Prozessen
Um einen Leistungsvergleich zwischen diesen Kopplungsarten anstellen zu können wäre es sinnvoll beide Kopplungsarten zu implementieren.