Im Shared Memory darf kein Zeiger hinterlegt werden!!

Werbung
C Tutorium
– Shared Memory –
Knut Stolze
Shared Memory

Ein Speicherbereich, auf den mehrere
Prozesse Zugriff haben
– Also kein privater Speicher
– Schnellste Form der Inter-Prozess-
Kommunikation (IPC)

Shared Memory Segment wird in
Adressbereich jedes einzelnen
(verbundenen) Prozesses abgebildet
2
Shared Memory
Hauptspeicher
Addressraum
Prozess 1
Prozess 1
Shared Memory
Segment
Addressraum
Prozess 2
Prozess 2
3
Gotchas

Zeiger (Pointer) sind Werte, die Adressen zu
anderen Daten beinhalten
 Shared Memory Segmente können an den
unterschiedlichen Adressen in die
Adressräume der einzelnen Prozesse
abgebildet werden
 Im Shared Memory darf kein Zeiger
hinterlegt werden!!
4
Erzeugen eines SHM
Segments

Ein Prozess legt Segment an
int shmget(key, size, flags)
– key: Schlüssel für das Segment; üblicherweise mittels
“ftok” generiert
– size: Größe des Segments in Bytes

Vergleichbar mit Größe bei “malloc”
– flags:



IPC_CREAT – Segment erzeugen
IPC_EXCL – zu erzeugendes Segment darf noch nicht
existieren; sonst Fehler
Zugriffsrechte (wie bei Dateien)
– Ergebnis: ID des Segments (oder –1 bei Fehler)

Nicht gleich dem “key”!
5
shmget

Es wird keine Verbindung zum SHM
hergestellt, d.h. das Segment wird nicht in
den aktuellen Prozessraum abgebildet
 Windows:
– SHM Segment existiert nur so lange, wie der
Prozess lebt, der das Segment erzeugt hat
6
ftok

Generiere Schlüssel für “shmget”, “msgget” oder
“semget”
key_t ftok(file, proj_id)
– file: Existierende Datei (inode kann herangezogen
werden)
– proj_id: Identifikator für aktuelles Projekt/Programm

Schlüssel ist immer identisch für ein (file,
proj_id)-Tupel
– Prozessübergreifend
– Andere Datei/andere “proj_id” gibt i.A. anderen
Schlüssel
7
Verbinden zu einem
existierenden SHM Segment

Jeder Prozess, der auf SHM Segment zugreifen
will, muss sich mit dem Segment verbinden
void *shmat(id, addr, flags)
– id: ID des Shared Memory Segments (von shmget)
– addr: Zieladresse des abgebildeten Segments

Sollte immer NULL sein!
– flags:


SHM_RDONLY – nur lesender Zugriff möglich
SHM_RND – abrunden einer gegebenen Adresse in “addr”
zum nächsten Seitenanfang
8
shmat

Segment wird in den eigenen Adressraum
abgebildet
– Ähnlich zu “malloc”
Nach “shmat” kann mit dem Segment wie mit
jedem anderen Speicherblock gearbeitet werden
 Bei Fehler wird Zeiger mit Wert –1
zurückgegeben

ptr = shmat(…);
if ((char *)ptr == (char *)(-1)) { … /* Fehler */ … }
9
Verbindung zum SHM
Segment trennen

Aktueller Prozess beendet Verbindung zum Shared
Memory Segment
int shmdt(addr)
– addr: Zeiger zum Beginn des Segments

Ergebnis von “shmat”
– Vergleichbar zu “free”

Zugriff auf Speicher des SHM Segments darf nach
“shmdt” nicht mehr erfolgen!
 Segment wird nicht zerstört
10
Segment zerstören

Segment wird zum Zerstören markiert
int shmctl(id, cmd, buffer)
– id: ID des Shared Memory Segments

Ergebnis von “shmget”
– cmd: Operation auf dem Segment
 IPC_RMID – Segment zerstören
 IPC_STAT – Informationen über das Segment in
“buffer” kopieren
 IPC_SET – Setze Zugriffsrechte für Segment
11
shmctl


Betriebssystem zestört Segment, wenn letzte
Verbindung aller Prozesse getrennt wird
Aktueller Prozess kann immer noch Verbindung
haben
–
1.
2.
3.
4.
5.
Beispiel: Start von X-Server
id = shmget(…, IPC_CREAT | IPC_EXCL)
segment = shmat(id, …)
shmctl(id, IPC_RMID, NULL);
…
shmdt(segment, …)
12
Verwendung von SHM

Segment ist ein zusammenhängender
Speicherbereich
– Muss von Anwendung(en) selbständig organisiert und
strukturiert werden
struct Entry {
int x, y;
};
ptr = shmat(…);
int *count = (int *)ptr;
struct Entry *entries = (struct entry *)(count + 1);
count
entry entry entry
…
entry
13
Verwendung von SHM (2)

Konkurrierender Zugriff auf Segment muss
synchronisiert werden
Semaphoren

Nur bei Nutzung mehrerer Prozesse
– Multi-Threading braucht keinen Shared
Memory
14
Kommandozeile (Unix)

Liste alle IPC-Resources (Message Queues,
Semaphore, Shared Memors Segmente)
$ ipcs

Lösche eine IPC-Resource
$ ipcrm

Beispiel um alle Resources des aktuellen Nutzers
zu löschen:
$ ipcs | grep `user` | awk ‘{ print “ipcrm –”$1,$2 } | sh -e
15
Herunterladen