SHMOP(2) System Calls Manual SHMOP(2) NOM shmat, shmdt - Operations sur la memoire partagee System V BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #include void *shmat(int shmid, const void *_Nullable shmaddr, int shmflg); int shmdt(const void *shmaddr); DESCRIPTION shmat() La fonction shmat() attache le segment de memoire partagee System V identifie par shmid au segment de donnees du processus appelant. L'adresse d'attachement est indiquee par shmaddr avec les criteres suivants : - Si shmaddr vaut NULL, le systeme choisit une adresse (non utilisee) alignee sur la page convenant pour attacher le segment. - Si shmaddr n'est pas NULL et si SHM_RND est indique dans shmflg, l'attachement a lieu a l'adresse egale a shmaddr arrondie au multiple inferieur de SHMLBA. - Sinon, shmaddr doit etre alignee sur une frontiere de page, ou l'attachement a lieu. En plus de SHM_RND, les attributs suivants peuvent etre indiques dans le parametre de masque shmflg : SHM_EXEC (specifique a Linux, depuis Linux 2.6.9) Autoriser l'execution du contenu du segment. L'appelant doit disposer du droit d'execution 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 indique, le segment est attache en lecture et ecriture, et le processus doit disposer des deux permissions d'acces. Il n'y a pas de notion d'ecriture seule pour les segments de memoire partagee. SHM_REMAP (specifique a Linux) Cet attribut indique que la projection du segment doit remplacer une projection precedente dans l'intervalle commencant en shmaddr et s'etendant sur la taille du segment. Normalement une erreur EINVAL devrait se produire si une projection existe deja dans l'intervalle indique. Dans ce cas, shmaddr ne doit pas etre NULL. La valeur brk(2) du processus appelant n'est pas alteree par l'attachement. Le segment est automatiquement detache quand le processus se termine. Le meme segment peut etre attache a la fois en lecture seule et en lecture/ecriture. Il peut egalement etre attache en plusieurs endroits de l'espace d'adressage du processus. Quand shmat() reussit, les membres de la structure shmid_ds associee au segment de memoire partagee (consultez shmctl(2)) sont mis a jour ainsi : - shm_atime correspond a l'heure actuelle. - shm_lpid contient le PID de l'appelant. - shm_nattch est incremente de 1. shmdt() La fonction shmdt() detache le segment de memoire partagee situe a l'adresse indiquee par shmaddr. Le segment doit etre effectivement attache, et l'adresse shmaddr doit etre celle renvoyee precedemment par l'appel shmat(). Quand shmdt() reussit, les membres de la structure shmid_ds associee au segment de memoire partagee sont mis a jour ainsi par le systeme : - shm_dtime correspond a l'heure actuelle. - shm_lpid contient le PID de l'appelant. - shm_nattch est decremente de 1. S'il devient nul et si le segment est marque pour destruction, il est effectivement detruit. VALEUR RENVOYEE S'il reussit, shmat() renvoie l'adresse d'attachement du segment de memoire partagee. En cas d'echec (void *) -1 est renvoye, et errno est positionne pour indiquer l'erreur. S'il reussit, shmdt() renvoie 0. En cas d'echec, -1 est renvoye et errno est positionne pour indiquer l'erreur. ERREURS shmat() peut echouer avec une des erreurs suivantes : EACCES Le processus appelant n'a pas les permissions d'acces necessaires pour ce type d'attachement et n'a pas la capacite CAP_IPC_OWNER dans l'espace de noms utilisateur qui gere son espace de noms IPC. EIDRM shmid pointe sur un segment detruit. EINVAL Invalid shmid value, unaligned (i.e., not page-aligned and SHM_RND was not specified) or invalid shmaddr value, or can't attach segment at shmaddr, or SHM_REMAP was specified and shmaddr was NULL. ENOMEM Pas assez de memoire pour le descripteur ou pour les tables de pages. shmdt() peut echouer avec une des erreurs suivantes : EINVAL Aucun segment de memoire partagee n'est attache a l'adresse shmaddr, ou bien shmaddr n'est pas aligne une limite de page. NORMES POSIX.1-2008. HISTORIQUE POSIX.1-2001, SVr4. Dans SVID 3 (ou peut etre auparavant), le type de l'argument shmaddr a ete modifie de char * en const void *, et le type de retour de shmat() de char * en void *. POSIX.1-2024 changed the error code from (void *) -1 to SHM_FAILED. NOTES Apres un fork(2), l'enfant herite des segments de memoire partagee attaches. Apres un execve(2), tous les segments de memoire partagee sont detaches du (pas detruits). Lors d'un _exit(2), tous les segments de memoire partagee sont detaches du processus (pas detruits). Utiliser shmat() avec shmaddr egale a NULL est la maniere conseillee et portable d'attacher un segment de memoire partagee. Soyez conscients que le segment attache de cette maniere peut l'etre a des adresses differentes dans les differents processus. Ainsi, tout pointeur contenu dans la memoire partagee doit etre relatif (habituellement par rapport a l'adresse de depart du segment) et pas absolu. Sous Linux, il est possible d'attacher un segment de memoire partagee qui est deja marque pour effacement. Cependant, ce comportement n'est pas decrit par POSIX.1 et beaucoup d'autres implementations ne le permettent pas. Le parametre systeme 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 necessaire sur certaines architectures, afin de s'assurer soit de bonne performances du cache de processeur, soit que differentes attaches du meme segment ont des vues coherentes dans le cache du processeur. SHMLBA est normalement un multiple de la taille de page du systeme (sur de nombreuses architectures Linux, SHMLBA est identique a la taille de page du systeme). L'implementation ne met pas de limite intrinseque par processus pour le nombre maximal de segments de memoire partagee (SHMSEG). EXEMPLES Les deux programmes presentes ci-dessous echangent une chaine en utilisant un segment de memoire partagee. Davantage de details a leur sujet sont donnes ci-dessous. Tout d'abord, nous presentons une session d'interpreteur qui montre leur utilisation. Dans une fenetre de terminal, nous executons le programme << reader >> qui cree un segment de memoire partagee System V et un ensemble de semaphores System V. Le programme affiche les identifiants des objets crees puis attend que le semaphore modifie la valeur. $ ./svshm_string_read; shmid = 1114194 semid = 15 Dans une autre fenetre de terminal, on execute le programme << writer >>. Ce programme prend trois parametres en ligne de commande : les identifiants du segment de memoire partagee et le jeu de semaphore, crees par le programme << reader >> et une chaine. Il attache le segment de memoire partagee existant, copie la chaine dans la memoire partagee et modifie la valeur du semaphore. $ ./svshm_string_write 1114194 15 'Hello, world'; De retour dans le terminal ou s'execute << reader >>, on voit que le programme a cesse d'attendre le semaphore et affiche la chaine copiee dans le segment de memoire partagee par << writer >> : Bonjour Source du programme : svshm_string.h Le fichier d'en-tete suivant est inclus dans les programmes << reader >> et << writer >> : /* svshm_string.h Licensed under GNU General Public License v2 or later. */ #ifndef SVSHM_STRING_H #define SVSHM_STRING_H #include #include #include #include union semun { /* Used in calls to 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 >> cree un segment de memoire partagee et un ensemble de semaphores contenant un semaphore. Il attache ensuite l'objet en memoire partagee a son espace d'adressage et initialise la valeur du semaphore a 1. Enfin, il attend que la valeur du semaphore devienne 0, apres quoi il affiche la chaine qui a ete copiee dans le segment de memoire partagee par << writer >>. /* svshm_string_read.c Licensed under GNU General Public License v2 or later. */ #include #include #include #include #include #include #include "svshm_string.h" int main(void) { int semid, shmid; char *addr; union semun arg, dummy; struct sembuf sop; /* Create shared memory and semaphore set containing one semaphore. */ shmid = shmget(IPC_PRIVATE, MEM_SIZE, IPC_CREAT | 0600); if (shmid == -1) err(EXIT_FAILURE, "shmget"); semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); if (semid == -1) err(EXIT_FAILURE, "semget"); /* Attach shared memory into our address space. */ addr = shmat(shmid, NULL, SHM_RDONLY); if (addr == (void *) -1) err(EXIT_FAILURE, "shmat"); /* Initialize semaphore 0 in set with value 1. */ arg.val = 1; if (semctl(semid, 0, SETVAL, arg) == -1) err(EXIT_FAILURE, "semctl"); printf("shmid = %d\n", shmid); printf("semid = %d\n", semid); /* Wait for semaphore value to become 0. */ sop.sem_num = 0; sop.sem_op = 0; sop.sem_flg = 0; if (semop(semid, &sop, 1) == -1) err(EXIT_FAILURE, "semop"); /* Print the string from shared memory. */ printf("%s\n", addr); /* Remove shared memory and semaphore set. */ if (shmctl(shmid, IPC_RMID, NULL) == -1) err(EXIT_FAILURE, "shmctl"); if (semctl(semid, 0, IPC_RMID, dummy) == -1) err(EXIT_FAILURE, "semctl"); exit(EXIT_SUCCESS); } Source du programme : svshm_string_write.c Le programme << writer >> prend trois parametres en ligne de commande : les identifiants du segment de memoire partagee et du jeu de semaphore crees par << reader >> et une chaine. Il attache le segment de memoire partagee a son espace d'adressage, puis decremente la valeur du semaphore a 0 pour informer << reader >> qu'il peut examiner le contenu de la memoire partagee. /* svshm_string_write.c Licensed under GNU General Public License v2 or later. */ #include #include #include #include #include #include #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, "Usage: %s shmid semid string\n", argv[0]); exit(EXIT_FAILURE); } size = strlen(argv[3]) + 1; /* +1 to include trailing '\0' */ if (size > MEM_SIZE) { fprintf(stderr, "String is too big!\n"); exit(EXIT_FAILURE); } /* Get object IDs from command-line. */ shmid = atoi(argv[1]); semid = atoi(argv[2]); /* Attach shared memory into our address space and copy string (including trailing null byte) into memory. */ addr = shmat(shmid, NULL, 0); if (addr == (void *) -1) err(EXIT_FAILURE, "shmat"); memcpy(addr, argv[3], size); /* Decrement semaphore to 0. */ sop.sem_num = 0; sop.sem_op = -1; sop.sem_flg = 0; if (semop(semid, &sop, 1) == -1) err(EXIT_FAILURE, "semop"); exit(EXIT_SUCCESS); } VOIR AUSSI brk(2), mmap(2), shmctl(2), shmget(2), capabilities(7), shm_overview(7), sysvipc(7) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot et Jean-Philippe MENGUAL Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.18 8 fevrier 2026 SHMOP(2)