#include <sys/shm.h> void *shmat(int shmid, const void *_Nullable shmaddr, int shmflg); int shmdt(const void *shmaddr);
En plus de SHM_RND, les attributs suivants peuvent être indiqués dans le paramètre de masque shmflg :
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 :
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 :
S'il réussit, shmdt() renvoie 0. En cas d'échec, -1 est renvoyé et errno est positionné pour indiquer l'erreur.
shmdt() peut échouer avec une des erreurs suivantes :
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 *.
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() :
L'implémentation ne met pas de limite intrinsèque par processus pour le nombre maximal de segments de mémoire partagée (SHMSEG).
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 » :
/* 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
};
/* 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");
/* 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");
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 à