shm_open, shm_unlink - Créer, ouvrir ou supprimer des objets en
mémoire partagée POSIX
Bibliothèque de temps réel (
librt,
-lrt)
#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);
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éé).
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.
- 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.
Ces fonctions sont fournies depuis la glibc 2.2.
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 |
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.
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.
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.
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 */
};
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);
}
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);
}
close(2),
fchmod(2),
fchown(2),
fcntl(2),
fstat(2),
ftruncate(2),
memfd_create(2),
mmap(2),
open(2),
umask(2),
shm_overview(7)
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]