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