Provided by: manpages-de-dev_4.23.1-1_all bug

BEZEICHNUNG

       shmat, shmdt - System-V-Operationen mit gemeinsam benutztem Speicher

BIBLIOTHEK

       Standard-C-Bibliothek (libc, -lc)

ÜBERSICHT

       #include <sys/shm.h>

       void *shmat(int shmid, const void *_Nullable shmaddr, int shmflg);
       int shmdt(const void *shmaddr);

BESCHREIBUNG

   shmat()
       shmat()  blendet  das  durch  shmid bezeichnete gemeinsame System-V-Speichersegment in den
       Adressraum des aufrufenden Prozesses ein. Die Adresse der Einblendung wird  durch  shmaddr
       nach einem der folgenden Kriterien bestimmt:

       •  Falls shmaddr NULL ist, wählt das System eine geeignete (freie), an einer Speicherseite
          ausgerichtete Adresse, um das Segment einzublenden.

       •  Wenn shmaddr nicht NULL ist und SHM_RND in shmflg angegeben  wurde,  wird  die  Adresse
          durch Abrundung von shmaddr bis auf ein Vielfaches von SHMLBA bestimmt.

       •  Andernfalls  muss  shmaddr  eine  an einer Speicherseite ausgerichtete Adresse sein, an
          welcher das Einblenden beginnt.

       Zusätzlich zu SHM_RND  dürfen  die  folgenden  Schalter  im  Bitmask-Argument  von  shmflg
       angegeben werden:

       SHM_EXEC (Linux-spezifisch; seit Linux 2.6.9)
              ermöglicht,  dass  der Inhalt des Segments ausgeführt wird. Der Aufrufende muss auf
              dem Segment Ausführungsrechte besitzen.

       SHM_RDONLY
              blendet das Segment mit Lesezugriff ein. Der  Prozess  muss  die  Berechtigung  für
              Lesezugriffe  auf  das Segment besitzen. Falls dieser Schalter nicht angegeben ist,
              wird das Segment mit Lese- und Schreibzugriff eingeblendet und der Prozess muss die
              Berechtigung   für   Lese-  und  Schreibzugriffe  auf  das  Segment  besitzen.  Ein
              gemeinsames Speichersegment mit reinem Schreibzugriff ist nicht vorgesehen.

       SHM_REMAP (Linux-spezifisch)
              Dieser Schalter gibt an, dass das Abbilden des Segments jedes existierende Abbilden
              im  Bereich  von  shmaddr  bis zur Größe des Segments ersetzen soll. (Falls bereits
              eine Abbildung in diesem Adressbereich existiert, würde dies normalerweise  zu  dem
              Fehler EINVAL führen.) In diesem Fall darf shmaddr nicht NULL sein.

       Der  brk(2)-Wert  des aufrufenden Prozesses wird durch das Einblenden nicht verändert. Das
       Segment wird bei Beenden des Prozesses automatisch abgetrennt. Das  gleiche  Segment  kann
       mit  Lese-  sowie  mit Lese- und Schreibzugriff einmal oder mehrfach in den Adressraum des
       Prozesses eingeblendet werden.

       Nach einem erfolgreichen shmat()-Aufruf aktualisiert das System die Bestandteile  der  dem
       Speichersegment zugeordneten shmid_ds-Struktur (siehe shmctl(2)) wie folgt:

       •  shm_atime wird auf die aktuelle Zeit gesetzt.

       •  shm_lpid wird auf die Prozesskennung des aufrufenden Prozesses gesetzt.

       •  shm_nattch wird um Eins erhöht.

   shmdt()
       shmdt()  löst  das  gemeinsame  Speichersegment, das an der Adresse shmaddr liegt, aus dem
       Adressraum des aufrufenden Prozesses. Das zu entfernende gemeinsame  Speichersegment  muss
       momentan   mit   shmaddr   eingeblendet   sein,  das  dem  Rückgabewert  des  einbendenden
       shat()-Aufrufs entspricht.

       Nach einem erfolgreichen shmdt()-Aufruf aktualisiert das System die Bestandteile  der  dem
       Speichersegment zugeordneten Struktur shmid_ds wie folgt:

       •  shm_dtime wird auf die aktuelle Zeit gesetzt.

       •  shm_lpid wird auf die Prozesskennung des aufrufenden Prozesses gesetzt.

       •  shm_nattch wird um Eins verringert. Wenn es dabei zu 0 wird und das Segment zum Löschen
          markiert ist, wird es gelöscht.

RÜCKGABEWERT

       Bei Erfolg gibt  shmat()  die  Adresse  des  eingeblendeten  gemeinsamen  Speichersegments
       zurück;  bei einem Fehler wird (void *) -1 zurückgegeben und errno gesetzt, um den Fehlers
       anzuzeigen.

       Bei Erfolg gibt shmdt() 0 zurück;  bei  einem  Fehler  wird  -1  zurückgegeben  und  errno
       gesetzt, um den Fehlers anzuzeigen.

FEHLER

       shmat() kann mit einem der folgenden Fehler fehlschlagen:

       EACCES Dem  aufrufenden  Prozess  fehlen  die nötigen Zugriffsrechte für den angeforderten
              Einblendetyp und die CAP_IPC_OWNER-Capability in dem Benutzernamensraum, der seinen
              IPC-Namensraum beherrscht.

       EIDRM  shmid zeigt auf einen entfernten Bezeichner.

       EINVAL Ungültiger   shmid-Wert,  nicht  ausgerichteter  (d.h.  nicht  an  die  Seitengröße
              angepasst und SHM_RND wurde nicht angegeben) oder ungültiger shmaddr-Wert  oder  es
              wurde SHM_REMAP angegeben und shmaddr war NULL.

       ENOMEM Es  konnte  kein  Speicher  für  den  Deskriptor oder die Seitentabellen reserviert
              werden.

       shmdt() kann mit einem der folgenden Fehler fehlschlagen:

       EINVAL Es ist kein gemeinsames Speichersegment in shmaddr eingeblendet  oder  shmaddr  ist
              nicht an der Seitengrenze ausgerichtet.

STANDARDS

       POSIX.1-2008.

GESCHICHTE

       POSIX.1-2001, SVr4.

       In SVID 3 (oder vielleicht früher) wurde der Typ des Arguments shmaddr von char * in const
       void * und der von shmat() zurückgegebene Typ von char * in void * geändert.

ANMERKUNGEN

       Nach einem fork(2) erbt der Kindprozess das eingeblendete gemeinsame Speichersegment.

       Nach einem exec(2) sind  alle  eingeblendeten  gemeinsamen  Speichersegmente  vom  Prozess
       abgelöst.

       Bei  einem  exit(2)  sind  alle  eingeblendeten  gemeinsamen  Speichersegmente vom Prozess
       abgelöst.

       Die bevorzugte, portierbare Möglichkeit,  ein  gemeinsames  Speichersegment  einzublenden,
       besteht  darin,  shmat() mit shmaddr gleich NULL zu benutzen. Sie sollten wissen, dass das
       eingeblendete gemeinsame Speichersegment auf diese Art  an  unterschiedliche  Adressen  in
       unterschiedlichen  Prozessen  eingeblendet  werden kann. Deshalb müssen alle innerhalb des
       gemeinsamen Speichers verwalteten Zeiger  relativ  (typischerweise  zur  Startadresse  des
       Segments) statt absolut sein.

       Unter  Linux  ist  es möglich, sogar ein gemeinsames Speichersegment einzublenden, wenn es
       bereits zum Löschen markiert ist. POSIX.1 spezifiziert dieses Verhalten jedoch  nicht  und
       andere Implementierungen unterstützen es nicht.

       Der folgende Systemparameter beeinflusst shmat():

       SHMLBA Untere  Segmentgrenze  des  Adressvielfachen. Wenn in einem Aufruf von shmat() eine
              Adresse explizit angegeben wurde. sollte der  Aufrufende  sicherstellen,  dass  die
              Adresse  ein  Vielfaches  dieses  Wertes  ist.  Dies  ist auf einigen Architekturen
              notwendig, um eine gute Leistung des CPU-Zwischenspeichers zu gewährleisten oder um
              sicherzustellen, dass unterschiedliche Einblendungen desselben Segments konsistente
              Ansichten innerhalb  des  CPU-Zwischenspeichers  haben.  SHMLBA  ist  normalerweise
              irgendein    Vielfaches    von   der   Seitengröße   des   Systems.   (Auf   vielen
              Linux-Architekturen ist SHMLBA dasselbe wie die Seitengröße des Systems.)

       Die  Implementierung  hat  keine  inhärenten  pro-Prozess-Einschränkungen  bezüglich   der
       maximalen Anzahl von gemeinsamen Speichersegmenten (SHMSEG).

BEISPIELE

       Die   zwei   nachfolgend  aufgeführten  Programme  tauschen  eine  Zeichenkette  über  ein
       gemeinsames  Speichersegment  aus.  Weitere  Details  über  die   Programme   finden   Sie
       nachfolgend. Zuerst wird eine Shell-Sitzung gezeigt, die ihre Verwendung zeigt.

       In  einem  Terminalfenster führen wir das »Lese«-Programm aus, das ein gemeinsam benutztes
       Speichersegment und eine Semaphoren-Gruppe gemäß System-V erstellt. Das Programm gibt  die
       Kennung  der  erstellten Objekte aus und wartet dann darauf, dass die Semaphore ihren Wert
       ändern.

           $ ./svshm_string_read
           shmid = 1114194; semid = 15

       In  einem  anderen  Terminal-Fenster  führen  wir   das   »Schreibe«-Programm   aus.   Das
       »Schreibe«-Programm   akzeptiert   drei  Befehlszeilenargumente:  die  Kennungen  des  vom
       »Lese«-Programm  erstellten  gemeinsam  benutzten  Speichersegments  und   die   erstellte
       Semaphoren-Gruppe  und  eine  Zeichenkette.  Es  blendet das bestehende gemeinsam benutzte
       Speichersegment ein, kopiert die Zeichenkette in  den  gemeinsam  benutzten  Speicher  und
       verändert den Wert der Semaphore.

           $ ./svshm_string_write 1114194 15 'Hallo, Welt'

       In  dem  Terminal-Fenster,  in  dem  das »Lese«-Programm läuft, können wir sehen, dass das
       Programm aufgehört hat, auf die Semaphore zu warten und die Zeichenkette  ausgegeben  hat,
       die vom Schreibe-Programm in den gemeinsam benutzten Speicher kopiert wurde:

           Hallo Welt

   Quelle des Programms: svshm_string.h
       Die folgende Header-Datei wird von den »Lese«- und »Schreibe«-Programmen eingebunden:

           /* svshm_string.h

              Lizenziert unter der GNU General Public License v2 oder neuer.
           */
           #ifndef SVSHM_STRING_H
           #define SVSHM_STRING_H

           #include <stdio.h>
           #include <stdlib.h>
           #include <sys/sem.h>

           #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                                   } while (0)

           union semun {                   /* Wird in Aufrufen von semctl() verwandt */
               int                 val;
               struct semid_ds    *buf;
               unsigned short     *array;
           #if defined(__linux__)
               struct seminfo     *__buf;
           #endif
           };

           #define MEM_SIZE 4096

   Quelle des Programms: svshm_string_read.c
       Das   »Lese«-Programm   erstellt   ein   gemeinsam   benutztes  Speichersegment  und  eine
       Semaphore-Gruppe, die eine Semaphore enthält.  Es  blendet  dann  das  gemeinsam  benutzte
       Speicherobjekt  in  seinen  Adressraum  ein  und  initialisiert den Semaphoren-Wert auf 1.
       Schließlich wartet das Programm darauf, dass der Semaphoren-Wert 0 wird  und  gibt  danach
       die  Zeichenkette aus, die durch den »Schreiber« in das gemeinsam benutzte Speichersegment
       kopiert wurde.

           /* svshm_string_read.c

              Lizenziert unter der GNU General Public License v2 oder neuer.
           */
           #include <stdio.h>
           #include <stdlib.h>
           #include <sys/ipc.h>
           #include <sys/sem.h>
           #include <sys/shm.h>

           #include "svshm_string.h"

           int
           main(void)
           {
               int            semid, shmid;
               char           *addr;
               union semun    arg, dummy;
               struct sembuf  sop;

               /* Gemeinsam benutzten Speicher und eine Semaphoren-Gruppe, die eine
                  Semaphore enthält, erstellen. */

               shmid = shmget(IPC_PRIVATE, MEM_SIZE, IPC_CREAT | 0600);
               if (shmid == -1)
                   errExit("shmget");

               semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
               if (semid == -1)
                   errExit("semget");

               /* Gemeinsamen Speicher in unseren Adressraum einblenden. */

               addr = shmat(shmid, NULL, SHM_RDONLY);
               if (addr == (void *) -1)
                   errExit("shmat");

               /* Semaphore 0 in der Gruppe mit dem Wert 1 initialisieren. */

               arg.val = 1;
               if (semctl(semid, 0, SETVAL, arg) == -1)
                   errExit("semctl");

               printf("shmid = %d; semid = %d\n", shmid, semid);

               /* Darauf warten, dass der Semaphore-Wert 0 wird. */

               sop.sem_num = 0;
               sop.sem_op = 0;
               sop.sem_flg = 0;

               if (semop(semid, &sop, 1) == -1)
                   errExit("semop");

               /* Die Zeichenkette aus dem gemeinsamen Speicher ausgeben. */

               printf("%s\n", addr);

               /* Den gemeinsam benutzten Speicher und die Semaphoren-Gruppe entfernen. */

               if (shmctl(shmid, IPC_RMID, NULL) == -1)
                   errExit("shmctl");
               if (semctl(semid, 0, IPC_RMID, dummy) == -1)
                   errExit("semctl");

               exit(EXIT_SUCCESS);
           }

   Quelle des Programms: svshm_string_write.c
       Das Schreibe-Programm  akzeptiert  drei  Befehlszeilenargumente:  die  Kennungen  des  vom
       »Lese«-Programm   bereits   erstellten,   gemeinsam  benutzten  Speichersegments  und  die
       Sempahoren-Gruppe und eine Zeichenkette. Es  blendet  das  bestehende  gemeinsam  benutzte
       Speichersegment  in  seinen  Adressraum  ein, verringert den Semaphoren-Wert auf 0, um den
       »Leser« zu informieren, dass  er  jetzt  den  Inhalt  des  gemeinsam  benutzten  Speichers
       untersuchen kann.

           /* svshm_string_write.c

              Lizenziert unter der GNU General Public License v2 oder neuer.
           */
           #include <stdio.h>
           #include <stdlib.h>
           #include <string.h>
           #include <sys/sem.h>
           #include <sys/shm.h>

           #include "svshm_string.h"

           int
           main(int argc, char *argv[])
           {
               int            semid, shmid;
               char           *addr;
               size_t         len;
               struct sembuf  sop;

               if (argc != 4) {
                   fprintf(stderr, "Aufruf: %s shmid semid string\n", argv[0]);
                   exit(EXIT_FAILURE);
               }

               len = strlen(argv[3]) + 1;  /* +1, um abschließende »\0« einzuschließen */
               if (len > MEM_SIZE) {
                   fprintf(stderr, "Zeichenkette ist zu groß!\n");
                   exit(EXIT_FAILURE);
               }

               /* Objektkennungen von der Befehlszeile erhalten. */

               shmid = atoi(argv[1]);
               semid = atoi(argv[2]);

               /* Gemeinsam benutzten Speicher in unseren Adressraum einblenden und Zeichenkette
                  (einschließlich abschließendem Nullbyte) in den Speicher kopieren */

               addr = shmat(shmid, NULL, 0);
               if (addr == (void *) -1)
                   errExit("shmat");

               memcpy(addr, argv[3], len);

               /* Semaphore auf 0 verringern. */

               sop.sem_num = 0;
               sop.sem_op = -1;
               sop.sem_flg = 0;

               if (semop(semid, &sop, 1) == -1)
                   errExit("semop");

               exit(EXIT_SUCCESS);
           }

SIEHE AUCH

       brk(2), mmap(2), shmctl(2), shmget(2), capabilities(7), shm_overview(7), sysvipc(7)

ÜBERSETZUNG

       Die  deutsche Übersetzung dieser Handbuchseite wurde von Ralf Demmer <rdemmer@rdemmer.de>,
       Chris Leick <c.leick@vollbio.de> und Helge Kreutzmann <debian@helgefjell.de> erstellt.

       Diese Übersetzung ist Freie Dokumentation;  lesen  Sie  die  GNU  General  Public  License
       Version  3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ oder neuer bezüglich der Copyright-
       Bedingungen. Es wird KEINE HAFTUNG übernommen.

       Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-
       Mail an die Mailingliste der Übersetzer ⟨debian-l10n-german@lists.debian.org⟩.