NOM

shm_open, shm_unlink - Créer, ouvrir ou supprimer des objets en mémoire partagée POSIX

BIBLIOTHÈQUE

Bibliothèque de temps réel ( librt, -lrt)

SYNOPSIS

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

DESCRIPTION

La fonction shm_open() crée et ouvre un nouvel objet en mémoire partagée POSIX, ou ouvre un objet existant. Il s'agit d'un descripteur utilisable par des processus indépendants pour projeter la même région mémoire à l'aide de mmap(2). La fonction shm_unlink() réalise l'opération inverse en supprimant l'objet créé précédemment par shm_open().
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 :
O_RDONLY
Ouvrir l'objet en lecture seule. Un tel objet ne pourra être projeté en mémoire avec mmap(2) qu'avec un accès en lecture ( PROT_READ).
O_RDWR
Ouvrir l'objet en lecture et écriture.
O_CREAT
Créer l'objet en mémoire partagée s'il n'existe pas. L'utilisateur et le groupe propriétaires de l'objet proviennent des ID effectifs du processus appelant, et les bits de permission sont définis en fonction des 9 bits de poids faible de mode, excepté que les bits qui sont définis dans le masque de mode de fichier pour la création du processus (consultez umask(2)) sont effacés pour le nouvel objet. Un jeu de constantes de macroutilisables pour définir le mode est décrit dans open(2) (les définitions symboliques de ces constantes peuvent être obtenues en incluant <sys/stat.h>).
A new shared memory object initially has zero length—the size of the object can be set using ftruncate(2). The newly allocated bytes of a shared memory object are automatically initialized to 0.
O_EXCL
Si O_CREAT était aussi précisé et si un objet en mémoire partagée avec le même nom existait déjà, renvoyer une erreur. La vérification de l'existence de l'objet et sa création s'il n'existe pas sont réalisées de manière atomique.
O_TRUNC
Si l'objet en mémoire partagée existe déjà, tronquer sa taille à zéro.
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éé).

VALEUR RENVOYÉE

Si elles réussissent, shm_open() renvoie un descripteur de fichier (un entier non négatif) et shm_unlink() renvoie  0. En cas d'échec, les deux fonctions renvoient  -1 et définissent errno pour indiquer le code d'erreur.

ERREURS

EACCES
La permission d'utiliser shm_unlink() sur l'objet en mémoire partagée a été refusée.
EACCES
L'utilisation de shm_open() pour ouvrir l'objet nom dans le mode spécifié a été refusée, ou O_TRUNC a été spécifié et l'appelant n'a pas les permissions d'écriture sur l'objet.
EEXIST
O_CREAT et O_EXCL ont été spécifiés dans shm_open() et un objet de mémoire partagée du même nom existe déjà.
EINVAL
L'argument nom de shm_open() n'était pas valable.
EMFILE
La limite du nombre de descripteurs de fichiers par processus a été atteinte.
ENAMETOOLONG
La longueur du nom dépasse PATH_MAX.
ENFILE
La limite du nombre total de fichiers ouverts pour le système entier a été atteinte.
ENOENT
Tentative d'ouvrir avec shm_open() un objet nom qui n'existe pas, alors que l'attribut O_CREAT n'a pas été spécifié.
ENOENT
Tentative d'utiliser shm_unlink() sur un objet nom qui n'existe pas.

VERSIONS

Ces fonctions sont fournies depuis la glibc 2.2.

ATTRIBUTS

Pour une explication des termes utilisés dans cette section, consulter attributes(7).
Interface Attribut Valeur
shm_open(), shm_unlink() Sécurité des threads MT-Safe locale
 

STANDARDS

POSIX.1-2001, POSIX.1-2008.
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.

NOTES

POSIX leaves the behavior of the combination of O_RDONLY and O_TRUNC unspecified. On Linux, this will successfully truncate an existing shared memory object—this may not be so on other UNIX systems.
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.

EXEMPLES

Les programmes ci-dessous utilisent la mémoire partagée POSIX et des sémaphores non nommés POSIX pour échanger des données. Le programme « bounce » (qui doit être exécuté en premier) illustre le cas d'une chaîne placée en mémoire partagée par le programme « send ». Lorsque les données ont été modifiées, le programme « send » affiche le contenu de la mémoire partagée modifié. Voici un exemple d'exécution des deux programmes :

$  ./pshm_ucase_bounce /myshm &
[1] 270171
$  ./pshm_ucase_send /myshm bonjour
BONJOUR

Vous trouverez plus de détails à propos de ces programmes ci-dessous.

Source du programme : pshm_ucase.h

Ce fichier d'en-tête est inclus par les deux programmes ci-dessous. Sa principale fonction consiste à définir une structure qui sera imposée à l'objet en mémoire partagé entre les deux programmes.

#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0)
#define BUF_SIZE 1024 /* Taille maximale de la chaîne échangée */
/* Définir une structure qui sera imposée à l'objet en mémoire partagée */
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 */ };

Source programme : pshm_ucase_bounce.c

Le programme « bounce » crée un nouvel objet en mémoire partagée avec le nom spécifié comme argument de la ligne de commande et le dimensionne de manière à correspondre à la taille de la structure shmbuf définie dans le fichier d'en-tête. Il projette ensuite l'objet dans l'espace d'adressage du processus et initialise deux sémaphores POSIX à  0 à l'intérieur de l'objet.
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 "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];
/* Créer l'objet en mémoire partagée et le dimensionner à la taille de notre 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");
/* Initialiser les sémaphores comme partagés entre processus avec la valeur  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");
/* Convertir en capitales les données en mémoire partagée. */
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");
/* Supprimer le lien avec l'objet en mémoire partagée. Cela ne posera pas de problème, même si le processus pair utilise encore l'objet, car ce dernier ne sera supprimé que lorsque tous les liens ouverts qui y font référence auront été fermés. */
shm_unlink(shmpath);
exit(EXIT_SUCCESS); }

Source du programme : pshm_ucase_send.c

Le programme « send » accepte deux arguments de ligne de commande : le nom d'un objet en mémoire partagée préalablement créé par le programme « bounce » et une chaîne à copier dans cet objet.
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 <string.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, "La chaîne est trop longue\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");
/* Copier les données dans l'objet en mémoire partagée. */
shmp->cnt = len; memcpy(&shmp->buf, string, len);
/* Informer le processus pair qu'il peut maintenant accéder à la mémoire partagée. */
if (sem_post(&shmp->sem1) == -1) errExit("sem_post");
/* Attendre que le processus pair indique qu'il a fini d'accéder à la mémoire partagée. */
if (sem_wait(&shmp->sem2) == -1) errExit("sem_wait");
/* Afficher les données qui ont été modifiées en mémoire partagée sur la sortie standard. */
write(STDOUT_FILENO, &shmp->buf, len); write(STDOUT_FILENO, "\n", 1);
exit(EXIT_SUCCESS); }

VOIR AUSSI

close(2), fchmod(2), fchown(2), fcntl(2), fstat(2), ftruncate(2), memfd_create(2), mmap(2), open(2), umask(2), shm_overview(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 <[email protected]>, Thierry Vignaud <[email protected]>, François Micaux, Alain Portal <[email protected]>, Jean-Philippe Guérard <[email protected]>, Jean-Luc Coulon (f5ibh) <[email protected]>, Julien Cristau <[email protected]>, Thomas Huriaux <[email protected]>, Nicolas François <[email protected]>, Florentin Duneau <[email protected]>, Simon Paillard <[email protected]>, Denis Barbier <[email protected]>, David Prévot <[email protected]> et Lucien Gentis <[email protected]>
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 à [email protected]