#include <sys/mman.h> #include <sys/stat.h> /* Pour les constantes de mode */ #include <fcntl.h> /* Pour les constantes O_* */ int shm_open(const char *nom, int masque, mode_t mode); int shm_unlink(const char *nom);
Le fonctionnement de shm_open() est analogue à celui de open(2). nom indique l'objet en mémoire partagée à créer ou ouvrir. Pour un fonctionnement portable, un objet en mémoire partagée doit être identifié par un nom au format /un_nom ; c'est-à-dire une chaîne terminée par un octet de valeur zéro d'au plus NAME_MAX (c'est-à-dire 255) caractères, et commençant par une barre oblique (« / ») suivie d'un caractère ou plus, ces derniers n'étant pas des barres obliques.
masque est un masque de bits associant à l'aide d'un OU logique une et une seule des deux constantes O_RDONLY ou O_RDWR et un ou plusieurs des attributs décrits ci-après :
Les définitions des valeurs de ces attributs peuvent être obtenues en incluant <fcntl.h>.
Si elle réussit, la fonction shm_open() renvoie un nouveau descripteur de fichierréférençant l'objet en mémoire partagée. Ce descripteur sera le plus petit numéro disponible dans la table des descripteurs du processus. L'attribut FD_CLOEXEC (consultez fcntl(2)) sera activé pour le descripteur de fichier.
Le descripteur de fichier est utilisé normalement pour les appels ultérieurs à ftruncate(2) (pour un objet nouvellement créé) et mmap(2). Après un appel à mmap(2) le descripteur peut être fermé sans affecter la projection mémoire.
Le fonctionnement de shm_unlink() est analogue à celui de unlink(2) : il supprime le nom d'un objet en mémoire partagée, et, une fois que tous les processus ont supprimé leur projection en mémoire, libère et détruit le contenu de la portion de mémoire associée. Après un appel réussi à shm_unlink(), les tentatives d'appeler shm_open() avec le même nom échoueront (sauf si O_CREAT est spécifié, auquel cas un nouvel objet distinct sera créé).
| Interface | Attribut | Valeur |
| shm_open(), shm_unlink() | Sécurité des threads | MT-Safe locale |
L'implémentation sous Linux des objets de mémoire partagée POSIX utilise un système de fichiers tmpfs(5) dédié, monté en principe sous /dev/shm.
POSIX.1-2001 indique que le groupe propriétaire d'un objet en mémoire partagée nouvellement créé utilise soit l'ID de groupe du processus appelant, soit un « ID de groupe par défaut défini par le système ». POSIX.1-2008 indique que le groupe propriétaire peut être défini soit avec l'ID de groupe du processus appelant, soit, si l'objet est visible dans le système de fichiers, avec l'ID de groupe du répertoire parent.
$ ./pshm_ucase_bounce /myshm & [1] 270171 $ ./pshm_ucase_send /myshm bonjour BONJOUR
Vous trouverez plus de détails à propos de ces programmes ci-dessous.
#ifndef PSHM_UCASE_H
#define PSHM_UCASE_H
#include <semaphore.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
#define BUF_SIZE 1024 /* Maximum size for exchanged string */
/* Define a structure that will be imposed on the shared
memory object */
struct shmbuf {
sem_t sem1; /* POSIX unnamed semaphore */
sem_t sem2; /* POSIX unnamed semaphore */
size_t cnt; /* Number of bytes used in 'buf' */
char buf[BUF_SIZE]; /* Data being transferred */
};
#endif // include guard
Une fois le premier sémaphore posté par le programme « send », le programme « bounce » met en capitales les données placées en mémoire par le programme « send », puis poste le second sémaphore pour indiquer au programme « send » qu'il peut maintenant accéder à la mémoire partagée.
/* pshm_ucase_bounce.c
Licensed under GNU General Public License v2 or later.
*/
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include "pshm_ucase.h"
int
main(int argc, char *argv[])
{
int fd;
char *shmpath;
struct shmbuf *shmp;
if (argc != 2) {
fprintf(stderr, "Usage: %s /shm-path\n", argv[0]);
exit(EXIT_FAILURE);
}
shmpath = argv[1];
/* Create shared memory object and set its size to the size
of our structure. */
fd = shm_open(shmpath, O_CREAT | O_EXCL | O_RDWR, 0600);
if (fd == -1)
errExit("shm_open");
if (ftruncate(fd, sizeof(struct shmbuf)) == -1)
errExit("ftruncate");
/* Map the object into the caller's address space. */
shmp = mmap(NULL, sizeof(*shmp), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (shmp == MAP_FAILED)
errExit("mmap");
/* Initialize semaphores as process-shared, with value 0. */
if (sem_init(&shmp->sem1, 1, 0) == -1)
errExit("sem_init-sem1");
if (sem_init(&shmp->sem2, 1, 0) == -1)
errExit("sem_init-sem2");
/* Wait for 'sem1' to be posted by peer before touching
shared memory. */
if (sem_wait(&shmp->sem1) == -1)
errExit("sem_wait");
/* Convert data in shared memory into upper case. */
for (size_t j = 0; j < shmp->cnt; j++)
shmp->buf[j] = toupper((unsigned char) shmp->buf[j]);
/* Post 'sem2' to tell the peer that it can now
access the modified data in shared memory. */
if (sem_post(&shmp->sem2) == -1)
errExit("sem_post");
/* Unlink the shared memory object. Even if the peer process
is still using the object, this is okay. The object will
be removed only after all open references are closed. */
shm_unlink(shmpath);
exit(EXIT_SUCCESS);
}
Le programme ouvre l'objet en mémoire partagée et le projette dans son espace d'adressage. Ensuite, il copie les données spécifiées à l'aide du second argument vers la mémoire partagée et poste le premier sémaphore pour informer le programme « bounce » qu'il peut maintenant accéder aux données. Lorsque le programme « bounce » a posté le second sémaphore, le programme « send » affiche le contenu de la mémoire partagée sur la sortie standard.
/* pshm_ucase_send.c
Licensed under GNU General Public License v2 or later.
*/
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include "pshm_ucase.h"
int
main(int argc, char *argv[])
{
int fd;
char *shmpath, *string;
size_t len;
struct shmbuf *shmp;
if (argc != 3) {
fprintf(stderr, "Usage: %s /shm-path string\n", argv[0]);
exit(EXIT_FAILURE);
}
shmpath = argv[1];
string = argv[2];
len = strlen(string);
if (len > BUF_SIZE) {
fprintf(stderr, "String is too long\n");
exit(EXIT_FAILURE);
}
/* Open the existing shared memory object and map it
into the caller's address space. */
fd = shm_open(shmpath, O_RDWR, 0);
if (fd == -1)
errExit("shm_open");
shmp = mmap(NULL, sizeof(*shmp), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (shmp == MAP_FAILED)
errExit("mmap");
/* Copy data into the shared memory object. */
shmp->cnt = len;
memcpy(&shmp->buf, string, len);
/* Tell peer that it can now access shared memory. */
if (sem_post(&shmp->sem1) == -1)
errExit("sem_post");
/* Wait until peer says that it has finished accessing
the shared memory. */
if (sem_wait(&shmp->sem2) == -1)
errExit("sem_wait");
/* Write modified data in shared memory to standard output. */
write(STDOUT_FILENO, &shmp->buf, len);
write(STDOUT_FILENO, "\n", 1);
exit(EXIT_SUCCESS);
}
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 à