dwww Home | Manual pages | Find package

SHMOP(2)                      System Calls Manual                     SHMOP(2)

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 sui-
       vants :

       •  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  mul-
          tiple inférieur de SHMLBA.

       •  Sinon, shmaddr doit être alignée sur une frontière de page, où l'at-
          tachement 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 par-
              tagé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'attache-
       ment. Le segment est automatiquement détaché quand le processus se ter-
       mine. Le même segment peut être attaché à la fois en lecture  seule  et
       en  lecture/écriture.  Il  peut également être attaché en plusieurs en-
       droits 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 at-
       taché, 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éces-
              saires  pour  ce  type  d'attachement  et  n'a  pas  la capacité
              CAP_IPC_OWNER dans l'espace de noms utilisateur qui gère son es-
              pace 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  va-
              leur  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-2001, POSIX.1-2008, 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  at-
       taché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 dif-
       fé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  per-
       mettent pas.

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

       SHMLBA Multiple  d’adresse pour limite basse de segment. Lors d’une in-
              dication 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 proces-
              seur, 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 utili-
       sant 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'in-
       terpré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  identi-
       fiants 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 pro-
       gramme 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 la GNU General Public License v2 ou supérieure.
           */
           #include <sys/types.h>
           #include <sys/ipc.h>
           #include <sys/shm.h>
           #include <sys/sem.h>
           #include <stdio.h>
           #include <stdlib.h>
           #include <string.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

   Source du programme : svshm_string_read.c
       Le  programme  « reader » crée un segment de mémoire partagée et un en-
       semble 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 la GNU General Public License v2 ou supé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éma-
       phore à 0 pour informer « reader » qu'il peut examiner le contenu de la
       mémoire partagée.

           /* svshm_string_write.c

              Sous la GNU General Public License v2 ou supé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         len;
               struct sembuf  sop;

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

               len = strlen(argv[3]) + 1;  /* +1 pour inclure le '\0' final */
               if (len > 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], len);

               /* 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_over-
       view(7), sysvipc(7)

TRADUCTION
       La traduction française de cette page de manuel a été créée par  Chris-
       tophe  Blaess  <https://www.blaess.fr/christophe/>, Stéphan Rafin <ste-
       phan.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.cou-
       lon@wanadoo.fr>,  Julien  Cristau <jcristau@debian.org>, Thomas Huriaux
       <thomas.huriaux@gmail.com>, Nicolas François  <nicolas.francois@centra-
       liens.net>,  Florentin  Duneau <fduneau@gmail.com>, Simon Paillard <si-
       mon.paillard@resel.enst-bretagne.fr>,   Denis   Barbier    <barbier@de-
       bian.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
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ 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.03   5 février 2023                        SHMOP(2)

Generated by dwww version 1.15 on Sat Jun 29 01:43:09 CEST 2024.