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