Provided by: manpages-fr-dev_4.27.0-1_all bug

NOM

       shmat, shmdt - Opérations sur la mémoire partagée System V

BIBLIOTHÈQUE

       Bibliothèque C standard (libc, -lc)

SYNOPSIS

       #include <sys/shm.h>

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

DESCRIPTION

   shmat()
       La  fonction  shmat()  attache  le segment de mémoire partagée System V identifié par shmid au segment de
       données du processus appelant. L'adresse  d'attachement  est  indiquée  par  shmaddr  avec  les  critères
       suivants :

       -  Si shmaddr vaut NULL, le système choisit une adresse (non utilisée) alignée sur la page convenant pour
          attacher le segment.

       -  Si  shmaddr  n'est  pas  NULL  et si SHM_RND est indiqué dans shmflg, l'attachement a lieu à l'adresse
          égale à shmaddr arrondie au multiple inférieur de SHMLBA.

       -  Sinon, shmaddr doit être alignée sur une frontière de page, où l'attachement a lieu.

       En plus de SHM_RND, les attributs suivants peuvent être indiqués dans le paramètre de masque shmflg :

       SHM_EXEC (spécifique à Linux, depuis Linux 2.6.9)
              Autoriser l'exécution du contenu du segment. L'appelant doit disposer du droit d'exécution sur  le
              segment.

       SHM_RDONLY
              Attacher  le  segment  en  lecture  seule.  Le processus doit disposer de la permission de lecture
              dessus. Si cet attribut n'est pas indiqué, le segment est attaché en lecture et  écriture,  et  le
              processus doit disposer des deux permissions d'accès. Il n'y a pas de notion d'écriture seule pour
              les segments de mémoire partagée.

       SHM_REMAP (spécifique à Linux)
              Cet  attribut  indique  que la projection du segment doit remplacer une projection précédente dans
              l'intervalle commençant en shmaddr et s'étendant sur la taille du segment. Normalement une  erreur
              EINVAL  devrait  se produire si une projection existe déjà dans l'intervalle indiqué. Dans ce cas,
              shmaddr ne doit pas être NULL.

       La  valeur  brk(2)  du  processus  appelant  n'est  pas  altérée  par  l'attachement.  Le   segment   est
       automatiquement  détaché  quand  le  processus se termine. Le même segment peut être attaché à la fois en
       lecture seule et en lecture/écriture. Il peut également être attaché en plusieurs  endroits  de  l'espace
       d'adressage du processus.

       Quand  shmat()  réussit,  les  membres  de  la structure shmid_ds associée au segment de mémoire partagée
       (consultez shmctl(2)) sont mis à jour ainsi :

       -  shm_atime correspond à l'heure actuelle.

       -  shm_lpid contient le PID de l'appelant.

       -  shm_nattch est incrémenté de 1.

   shmdt()
       La fonction shmdt() détache le segment de mémoire partagée situé à l'adresse  indiquée  par  shmaddr.  Le
       segment  doit  être effectivement attaché, et l'adresse shmaddr doit être celle renvoyée précédemment par
       l'appel shmat().

       Quand shmdt() réussit, les membres de la structure shmid_ds associée au segment de mémoire partagée  sont
       mis à jour ainsi par le système :

       -  shm_dtime correspond à l'heure actuelle.

       -  shm_lpid contient le PID de l'appelant.

       -  shm_nattch  est décrémenté de 1. S'il devient nul et si le segment est marqué pour destruction, il est
          effectivement détruit.

VALEUR RENVOYÉE

       S'il réussit, shmat() renvoie l'adresse d'attachement du segment de  mémoire  partagée.  En  cas  d'échec
       (void *) -1 est renvoyé, et errno est positionné pour indiquer l'erreur.

       S'il  réussit,  shmdt()  renvoie  0. En cas d'échec, -1 est renvoyé et errno est positionné pour indiquer
       l'erreur.

ERREURS

       shmat() peut échouer avec une des erreurs suivantes :

       EACCES Le processus appelant n'a pas les permissions d'accès nécessaires pour ce  type  d'attachement  et
              n'a  pas  la  capacité CAP_IPC_OWNER dans l'espace de noms utilisateur qui gère son espace de noms
              IPC.

       EIDRM  shmid pointe sur un segment détruit.

       EINVAL La valeur shmid n'est pas valable, mal alignée (c'est-à-dire pas alignée sur une page  et  SHM_RND
              n'a  pas  été  précisé)  ou  la  valeur  shmaddr  n'est pas valable, ou ne peut pas être attaché à
              shmaddr, ou SHM_REMAP a été réclamé et shmaddr est NULL.

       ENOMEM Pas assez de mémoire pour le descripteur ou pour les tables de pages.

       shmdt() peut échouer avec une des erreurs suivantes :

       EINVAL Aucun segment de mémoire partagée n'est attaché à l'adresse shmaddr, ou  bien  shmaddr  n'est  pas
              aligné une limite de page.

STANDARDS

       POSIX.1-2008.

HISTORIQUE

       POSIX.1-2001, SVr4.

       Dans  SVID  3  (ou  peut être auparavant), le type de l'argument shmaddr a été modifié de char * en const
       void *, et le type de retour de shmat() de char * en void *.

NOTES

       Après un fork(2), l'enfant hérite des segments de mémoire partagée attachés.

       Après un execve(2), tous les segments de mémoire partagée sont détachés du (pas détruits).

       Lors d'un _exit(2), tous les segments de mémoire partagée sont détachés du processus (pas détruits).

       Utiliser shmat() avec shmaddr égale à NULL est la manière conseillée et portable d'attacher un segment de
       mémoire partagée. Soyez conscients que le segment attaché de cette manière peut  l'être  à  des  adresses
       différentes  dans  les  différents  processus. Ainsi, tout pointeur contenu dans la mémoire partagée doit
       être relatif (habituellement par rapport à l'adresse de départ du segment) et pas absolu.

       Sous Linux, il est possible  d'attacher  un  segment  de  mémoire  partagée  qui  est  déjà  marqué  pour
       effacement.  Cependant, ce comportement n'est pas décrit par POSIX.1 et beaucoup d'autres implémentations
       ne le permettent pas.

       Le paramètre système suivant influe sur shmat() :

       SHMLBA Multiple d’adresse pour limite  basse  de  segment.  Lors  d’une  indication  explicite  d’adresse
              d’attache  dans  un  appel  shmat(), l’appelant devrait s’assurer que l’adresse est un multiple de
              cette valeur. Cela est nécessaire sur certaines architectures, afin de  s’assurer  soit  de  bonne
              performances  du  cache  de processeur, soit que différentes attaches du même segment ont des vues
              cohérentes dans le cache du processeur. SHMLBA est normalement un multiple de la taille de page du
              système (sur de nombreuses architectures Linux, SHMLBA est  identique  à  la  taille  de  page  du
              système).

       L'implémentation  ne  met  pas  de limite intrinsèque par processus pour le nombre maximal de segments de
       mémoire partagée (SHMSEG).

EXEMPLES

       Les deux programmes présentés ci-dessous  échangent  une  chaîne  en  utilisant  un  segment  de  mémoire
       partagée.  Davantage  de  détails  à leur sujet sont donnés ci-dessous. Tout d'abord, nous présentons une
       session d'interpréteur qui montre leur utilisation.

       Dans une fenêtre de terminal, nous exécutons le programme « reader »  qui  crée  un  segment  de  mémoire
       partagée System V et un ensemble de sémaphores System V. Le programme affiche les identifiants des objets
       créés puis attend que le sémaphore modifie la valeur.

           $ ./svshm_string_read
           shmid = 1114194; semid = 15

       Dans  une  autre  fenêtre  de  terminal,  on  exécute  le  programme « writer ». Ce programme prend trois
       paramètres en ligne de commande : les identifiants du segment de mémoire partagée et le jeu de sémaphore,
       créés par le programme « reader » et une chaîne. Il attache le  segment  de  mémoire  partagée  existant,
       copie la chaîne dans la mémoire partagée et modifie la valeur du sémaphore.

           $ ./svshm_string_write 1114194 15 'Bonjour'

       De  retour  dans  le  terminal  où  s'exécute  « reader », on voit que le programme a cessé d'attendre le
       sémaphore et affiche la chaîne copiée dans le segment de mémoire partagée par « writer » :

           Bonjour

   Source du programme : svshm_string.h
       Le fichier d'en-tête suivant est inclus dans les programmes « reader » et « writer » :

           /* svshm_string.h

              Sous licence GNU General Public v2 ou postérieure.
           */
           #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 {                   /* Utilisé dans les appels semctl() */
               int                 val;
               struct semid_ds     *buf;
               unsigned short      *array;
           #if defined(__linux__)
               struct seminfo      *__buf;
           #endif
           };

           #define MEM_SIZE 4096

           #endif  // include guard

   Source du programme : svshm_string_read.c
       Le programme « reader » crée un segment de mémoire partagée et un ensemble  de  sémaphores  contenant  un
       sémaphore.  Il  attache  ensuite  l'objet  en  mémoire partagée à son espace d'adressage et initialise la
       valeur du sémaphore à 1. Enfin, il attend que la valeur du sémaphore devienne 0, après quoi il affiche la
       chaîne qui a été copiée dans le segment de mémoire partagée par « writer ».

           /* svshm_string_read.c

              Sous licence GNU General Public v2 ou postérieure.
           */
           #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;

               /* Créer la mémoire partagée et le jeu de sémaphores contenant
                  un sémaphore. */

               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");

               /*Attacher la mémoire partagée à notre espace d'adressage. */

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

               /* Initialiser le sémaphore 0 du jeu à la valeur 1. */

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

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

               /* Attendre que la valeur du sémaphore devienne 0. */

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

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

               /* Afficher la chaîne à partir de la mémoire partagée. */

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

               /* Supprimer la mémoire partagée et le jeu de sémaphores. */

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

               exit(EXIT_SUCCESS);
           }

   Source du programme : svshm_string_write.c
       Le programme « writer » prend trois paramètres en ligne de commande :  les  identifiants  du  segment  de
       mémoire  partagée  et  du  jeu  de sémaphore créés par « reader » et une chaîne. Il attache le segment de
       mémoire partagée à son espace d'adressage, puis décrémente la valeur  du  sémaphore  à  0  pour  informer
       « reader » qu'il peut examiner le contenu de la mémoire partagée.

           /* svshm_string_write.c

              Sous licence GNU General Public v2 ou postérieure.
           */
           #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         size;
               struct sembuf  sop;

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

               size = strlen(argv[3]) + 1;  /* +1 pour inclure le '\0' final */
               if (size > MEM_SIZE) {
                   fprintf(stderr, "La chaîne est trop longue !\n");
                   exit(EXIT_FAILURE);
               }

               /* Obtenir les identifiants de l'objet depuis la ligne de commande. */

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

               /* Attacher la mémoire partagée dans notre espace d'adressage et copier
                  la chaîne (et notamment l'octet NULL final) dans la mémoire. */

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

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

               /* Décrémenter le sémaphore à 0 */

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

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

               exit(EXIT_SUCCESS);
           }

VOIR AUSSI

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

TRADUCTION

       La   traduction   française   de   cette   page   de   manuel   a   été   créée   par  Christophe  Blaess
       <https://www.blaess.fr/christophe/>,   Stéphan   Rafin   <stephan.rafin@laposte.net>,   Thierry   Vignaud
       <tvignaud@mandriva.com>,  François  Micaux,  Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard
       <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)   <jean-luc.coulon@wanadoo.fr>,   Julien   Cristau
       <jcristau@debian.org>,      Thomas      Huriaux      <thomas.huriaux@gmail.com>,     Nicolas     François
       <nicolas.francois@centraliens.net>,    Florentin    Duneau    <fduneau@gmail.com>,     Simon     Paillard
       <simon.paillard@resel.enst-bretagne.fr>,     Denis    Barbier    <barbier@debian.org>,    David    Prévot
       <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>

       Cette traduction est une documentation libre ; veuillez vous  reporter  à  la  GNU General Public License
       version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si  vous  découvrez  un  bogue  dans la traduction de cette page de manuel, veuillez envoyer un message à
       debian-l10n-french@lists.debian.org.

Pages du manuel de Linux 6.9.1                    15 juin 2024                                          SHMOP(2)