View
107
Download
0
Category
Preview:
Citation preview
2.4 Kommunikationsdienste des Betriebssystems
Interprozeßkommunikation (inter-process communication, IPC)am Beispiel Unix
HW HW
BS BS
Prozesse
KommunizierendeThreads
Interprozeßkommunikation ist sprachunabhängig:
- Nachrichten sind ungetypt, d.h. Bytes oder Byte-Folgen,
- nackte Semantik ohne syntaktischen Zucker,
- u.U. verschiedene Semantiken zur Auswahl.
Pipes, Named Pipes, Message Queues, ... für lokale IPC
Sockets für netzweite IPC
2.4.1 Pipes
Pipe = Simplex-Kanal (Solaris: Duplex!)verbunden mit einem Eingabe- und einem Ausgabe-Port(typischerweise verschiedener Prozesse)
Senden: int write(int port, char *buffer, int length)
Empfangen: int read(int port, char *buffer, int length)
Adressierung: kanalbezogen
Konfigurierung: dynamisch durch Programm:Erzeugung von Prozessen und Pipes,Vererben von Ports bei Prozeßerzeugung
Semantik: zuverlässiger Byte-Strom mit begrenzter Pufferung;read erfolgreich, sobald mindestens 1 Byte vorliegt;write erfolgreich, sobald length Bytes frei;auch nichtblockierende Versionen (mittels fcntl).
2.4.2 Sockets
(socket = Steckdose)
Socket = Duplex-Port (Senden und Empfangen)
für lokale und netzweite IPC
mit unterschiedlich wählbaren Semantiken
Adressierung: portbezogen
Konfigurierung: dynamisch durch Programm:
Erzeugung lokaler Sockets,
Binden an Sockets anderer Prozesse
Semantik: zuverlässiger Byte-Strom
oder Einzelnachrichten ohne Reihenfolge-garantie und Schutz gegen Verlust
Erzeugung eines – ungebundenen – Socket:
int socket(int family, int type, int protocol)
prozeßlokale Protokoll- Dienst ProtokollPort-Nummer Familie (i.d.R. 0 [Null])
Familie
Dienst PF_UNIX PF_INET PF_NS .......
SOCK_STREAM TCP SPP
SOCK_DGRAM UDP IDP
SOCK_RAW IP .......
Benennung eines Socket mit netzweit gültiger Adresse:
int bind(int socket, struct sockaddr *address, int addrlen)
(Protokollfamilie, stationslokale Socket-Nummer , Stationsadresse)
z.B. PF_INET, a-16-bitPortNumber, a-32-bitHostId
SOCK_DGRAM für Internet:
verbindungslose, unzuverlässige Nachrichtenübertragung mit UDP
int sendto(int socket, char *buffer, int length, int flags, struct sockaddr *to, int addrlen)
Absender socket sendet an Adressat to
int recvfrom(int socket, char *buffer, int length, int flags, struct sockaddr *from, int *addrlen)
socket empfängt an ihn gesendete Nachricht sowie deren Absender
SOCK_STREAM für Internet:
verbindungsorientiert - zuverlässiger Byte-Strom mit TCP
Konfigurierung ist an Szenario Auftraggeber/Auftragnehmer orientiert:
Initiative geht von einem Klienten aus
Nach erfolgreich hergestellter Verbindung Nachrichtenaustausch mittels
(Klient) (Server)
write(s1,request,length);read(s3,request,length);...write(s3,reply,length);
read(s1,reply,length);
Herstellung der Verbindung:
(Klient) (Server)
s1 = socket(...); s2 = socket(...);
[ bind(s1,..); ] bind(s2,&local,l);
listen(s2, qlength);
connect(s1,&dest,l); s3 = accept(s2,&source,&l);
write(...); read(...);
... ...
close(s1); close(s3);
Statt write/read auch send/recv(.,.,.,flags) !
Java unterstützt das Arbeiten mit Sockets durch Bibliotheksklassen
Socket,
ServerSocket,
DatagramSocket, MulticastSocket,
.....
siehe java.net.*
2.4.3 Nichtsequentielle Server
Beachte: Server operiert in nichtsequentieller Umgebung
Verbindungsbearbeitung/Auftragsbearbeitung
sequentiell,exklusiv
(Prozeß Monitor!)
nichtsequentiell,überlappend
je Verbindung je Verbindungein Prozeß ein Thread
Ein Server, der mehrere Dienste anbietet:
für jeden Dienst ein eigener Port !
a) sequentiell: disjunktives Warten auf Verbindungswünsche
b) nichtsequentiell: je Port ein (statischer) Thread
c) nichtsequentiell: disjunktives Warten + (dynamische) Threads
d) nichtsequentiell: disjunktives Warten + Prozesse
2.4.4 Disjunktives Warten
auf Verbindungsanforderungen über mehrere Sockets
- allgemein: auf Empfangs/Sende-Möglichkeit über Kanäle !
Alternativen:
wiederholtes nichtblockierendes Senden/Empfangen („polling“)
asynchrones Senden/Empfangen mit Signalisierung durch
Software-Unterbrechung (Unix: signal SIGIO) - mühsam !
disjunktives Warten mit Systemaufruf (Unix:) select
2.4.5 Datenkonvertierung
bei Hardware-Heterogenität
Byte-Reihenfolge, z.B. für 16-Bit-Ganzzahlen:
„little-endian“ (Intel,..)
„big-endian“ (Motorola,..)
Zeichen: ASCII, EBCDIC, ...
Gleitkommazahlen: IEEE-Standard, ...
a+1 a
a a+1
2 Alternativen:
1. Ad-hoc-Umwandlung, z.B. „receiver makes it right“
2. Verwendung einer kanonischen Darstellung auf dem Netz
(external data representation)
Auch Felder, Verbunde, Objekte, ... behandeln !
Bezug zu: - Typsystem der Programmiersprache
- vom Übersetzer gewählte interne Darstellung
- evtl. Sprachheterogenität !
(Wir kommen in einem späteren Kapitel darauf zurück.)
[ Zuständig gemäß OSI-Referenzmodell: Presentation Layer (6) ]
Für Internet Unterstützung durch Bibliotheksroutinen:
in C für Ganzzahlen:
u_long htonl(u_long number); „host to network long“
u_short htons(u_short number);
u_long ntohl(u_long number);
u_short ntohs(u_short number);
Java: automatische Umcodierung bei Benutzung von Socket-Objekten
OutputStream os = mySocket.getOutputStream();
ObjectOutput out = new ObjectOutputStream(os);
out.writeInt(i);
out.writeFloat(f);
out.writeBoolean(b);
...
out.writeObject(o); // o must be Serializable or ...
Entsprechend für Eingabe ...
2.5 Kommunikationsplattformen
- in C, Fortran, ... über Bibliotheken benutzbar
Ziele:
Nachrichtendienst unabhängig von Betriebssystem und Netz
automatische Typkonversion für übertragene Daten
komfortable Prozeßverwaltung
und damit Eignung für Parallelprogrammierung im Netz
Plattform
BS
HW . . . . . . .
. . . . . . .
2.5.1 PVM
„Parallel Virtual Machine“
gepufferte, blockierende, reihenfolgetreue Übertragung von Einzelnachrichten
prozeßbezogene Adressierung, auch Rundsendungen
Unterstützung von Packen/Entpacken von Nachrichten (marshaling)
Dynamische Erzeugung von Prozessen im Netz
interaktive Steuerung der Konfiguration
2.5.2 MPI
„Message Passing Interface“
Entwickelt für Parallelrechner mit verteiltem Speicher(Mehrrechnersystem, multicomputer)
Erweitert für Workstation Clusters und Rechnernetze
Unterstützung für SPMD – Single Program, Multiple Data:
Jeder Prozess(or) arbeitet mit gleichen Programm,
aber auf jeweils eigenem Fragment der Daten,
mit Interaktion über Nachrichten.
Adressierung ist prozeßbezogen:
int MPI_Send(void* message, int count, MPI_Datatype elemType, int destProc, int tag, MPI_Comm communicator)
entspricht send message to destProc(Feld-Typ)
int MPI_Recv(void* message, int count, MPI_Datatype elemType, int srcProc, int tag, MPI_Comm communicator, MPI_Status* status)
entspricht recv message [ from srcProc ]
falls srcProc nicht MPI_ANY_SOURCE
status enthält Prozeßnummer des Senders
Adressierung auch prozeßgruppenbezogen:
int MPI_Bcast(void* message, int count, MPI_Datatype elemType, int root, MPI_Comm communicator)
Falls ausführender Prozeß = root ,
Senden der Rundsendung (broadcast) message
an die Mitglieder der Gruppe communicator
Sonst Empfangen einer Rundsendung
Semantik:
Pufferung ist systemspezifisch/wählbar
Empfangsfolge: zuverlässig reihenfolgetreue Nachrichten
Synchronisation: blockierend, aber auch nichtblockierende Varianten:
int MPI_Isend(..., MPI_Request* request)
int MPI_Irecv(..., MPI_Request* request)
( I für immediate) und Synchronisation mittels
int MPI_Wait(MPI_Request* request, MPI_Status* status)
(statt über Software-Unterbrechungen !)
Konfigurierung
Alle n beteiligten Rechner erhalten und starten eine Kopie eines
MPI-basierten Programms;
die n gestarteten Prozesse verhalten sich ähnlich, aber nicht
identisch (abhängig von ihrer Identität!),
operieren auf jeweils auf einer Teilmenge der Daten
und interagieren dabei über Nachrichten.
Recommended