Provided by: manpages-de-dev_4.27.0-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 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.

Linux man-pages 6.9.1                             15. Juni 2024                                         SHMOP(2)