memfd_create
Section: System Calls (2)
Updated: 5 février 2023
Index
Return to Main Contents
NOM
memfd_create - Créer un fichier anonyme
BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)
SYNOPSIS
#define _GNU_SOURCE /* Consultez feature_test_macros(7) */
#include <sys/mman.h>
int memfd_create(const char *name, unsigned int flags);
DESCRIPTION
memfd_create() crée un fichier anonyme et renvoie un descripteur de
fichier qui s'y rapporte. Le fichier se comporte comme un fichier normal, il
peut donc être modifié, tronqué, projeté en mémoire, et ainsi de suite. Mais
contrairement à un fichier normal, il réside dans la RAM et son stockage est
volatile. Une fois que toutes les références au fichier ont disparu, il est
automatiquement libéré. La mémoire anonyme est utilisée pour toutes les
pages de sauvegarde du fichier. Les fichiers créés par memfd_create() ont
donc la même sémantique que les autres allocations de mémoire anonyme telles
que celles qui utilisent mmap(2) avec l'attribut MAP_ANONYMOUS.
La taille initiale du fichier est positionnée à 0. Après l'appel, elle
devrait être définie en utilisant ftruncate(2) (ou le fichier peut être
rempli par des appels à write(2) ou équivalent).
Le nom fourni dans name est utilisé comme nom de fichier et sera affiché
en tant que cible du lien symbolique correspondant dans le répertoire
/proc/self/fd/. Le nom affiché a toujours un préfixe memfd: et il ne
sert que pour le débogage. Les noms ne changent pas le comportement du
descripteur de fichier et en tant que tels plusieurs fichiers peuvent avoir
le même nom sans effets de bord.
Les valeurs suivantes peuvent subir une opération OU logique bit à bit dans
flags pour modifier le comportement de memfd_create() :
- MFD_CLOEXEC
-
Placer l'attribut « close-on-exec » (FD_CLOEXEC) sur le nouveau
descripteur de fichier. Consultez la description de l'attribut O_CLOEXEC
dans open(2) pour savoir pourquoi cela peut être utile.
- MFD_ALLOW_SEALING
-
Permettre des opérations de verrouillage sur ce fichier. Voir le point sur
les opérations F_ADD_SEALS et F_GET_SEALS dans fcntl(2), ainsi que
les NOTES ci-dessous. Le positionnement initial des verrous est vide. Si cet
attribut n'est pas défini, le positionnement initial des verrous sera
F_SEAL_SEAL, ce qui veut dire qu'aucun autre verrou ne peut être
positionné sur le fichier.
- MFD_HUGETLB (depuis Linux 4.14)
-
Le fichier anonyme sera créé sur le système de fichiers hugetlbfs en
utilisant d'immenses pages. Voir le fichier
Documentation/admin-guide/mm/hugetlbpage.rst des sources du noyau Linux
pour plus d'informations sur hugetlbfs. Le fait d'indiquer à la fois
MFD_HUGETLB et MFD_ALLOW_SEALING dans flags est pris en charge
depuis Linux 4.16.
- MFD_HUGE_2MB, MFD_HUGE_1GB, ...
-
Utilisé avec MFD_HUGETLB pour sélectionner d'autres tailles de page
hugetlb (respectivement 2 Mo, 1 Go, ...) sur les systèmes qui gèrent
plusieurs tailles de page hugetlb. Les définitions des tailles de page
immenses connues figurent dans le fichier d'entête
<linux/memfd.h>.
-
Pour des détails sur l'encodage des tailles des pages immenses ne figurant
pas dans le fichier d'entête, voir le point sur les constantes du même nom
dans mmap(2).
Les bits inusitées dans flags doivent valoir 0.
En code de retour, memfd_create() renvoie un nouveau descripteur de
fichier qui peut être utilisé pour se référer au fichier. Ce descripteur de
fichier est ouvert en lecture et en écriture (O_RDWR) et O_LARGEFILE
est positionné pour le descripteur de fichier.
Par rapport à fork(2) et execve(2), la sémantique habituelle
s'applique au descripteur de fichier créé par memfd_create(). Une copie
du descripteur de fichier est récupérée par l'enfant produit par fork(2)
et elle se rapporte au même fichier. Le descripteur de fichier est préservé
pendant un execve(2), sauf si l'attribut close-on-exec a été positionné.
VALEUR RENVOYÉE
En cas de succès, memfd_create() renvoie un nouveau descripteur de
fichier. En cas d'erreur, -1 est renvoyé et errno est positionné pour
indiquer l'erreur.
ERREURS
- EFAULT
-
L'adresse dans name pointe vers une mémoire non valable.
- EINVAL
-
flags comprend des bits inconnus.
- EINVAL
-
name était trop long (la limite de 249 octets, n'incluant pas l'octet
NULL final).
- EINVAL
-
MFD_HUGETLB et MFD_ALLOW_SEALING ont tous deux été indiqués dans
flags.
- EMFILE
-
La limite du nombre de descripteurs de fichiers par processus a été
atteinte.
- ENFILE
-
La limite du nombre total de fichiers ouverts pour le système entier a été
atteinte.
- ENOMEM
-
Mémoire insuffisante pour créer un nouveau fichier anonyme.
VERSIONS
L'appel système memfd_create() est apparu dans Linux 3.17 ; la prise en
charge de la glibc a été ajouté dans la glibc 2.27.
- EPERM
-
L'attribut MFD_HUGETLB a été spécifié, mais l'appelant n'est pas un
utilisateur privilégié (il n'a pas la capacité CAP_IPC_LOCK) et il n'est
pas membre du groupe sysctl_hugetlb_shm_group ; consultez la description
de /proc/sys/vm/sysctl_hugetlb_shm_group dans proc(5).
STANDARDS
L'appel système memfd_create() est spécifique à Linux.
NOTES
L'appel système memfd_create() offre une alternative simple au montage
manuel d'un système de fichiers tmpfs(5) et à la création et l'ouverture
d'un fichier dans ce système de fichiers. Le premier objectif de
memfd_create() est de créer des fichiers et leur descripteur associé,
utilisés avec les API de verrou de fichiers fournis par fcntl(2).
L'appel système memfd_create() s'utilise également sans verrou de fichier
(c'est pourquoi le verrouillage de fichier a été désactivé sauf demande
explicite avec l'attribut MFD_ALLOW_SEALING). En particulier, il peut
être utilisé comme alternative pour créer des fichiers dans tmp ou pour
utiliser O_TMPFILE de open(2), si vous ne voulez pas rattacher le
fichier résultant au système de fichiers.
Verrou de fichiers
En l'absence de verrou de fichier, les processus qui communiquent à travers
la mémoire partagée doivent soit se faire confiance entre eux, soit prendre
des mesures pour gérer la possibilité qu'un pair non fiable manipule la
région de mémoire partagée de manière problématique. Par exemple, un pair
non fiable pourrait modifier le contenu de la mémoire partagée n'importe
quand ou rétrécir la zone de mémoire partagée. La première éventualité rend
le processus local vulnérable aux conflits (race conditions)
time-of-check-to-time-of-use (généralement gérés en copiant les données de
la zone de mémoire partagée avant de les vérifier et de les utiliser). La
deuxième éventualité rend le processus local vulnérable aux signaux
SIGBUS quand on essaie d'accéder à un emplacement inexistant dans la zone
de mémoire partagée (gérer cette éventualité implique d'utiliser un
gestionnaire pour le signal SIGBUS).
La gestion de pairs non fiables impose une plus grande complexité du code
qui utilise la mémoire partagée. Les verrous mémoire éliminent cette
complexité, en permettant à un processus d'agir en toute sécurité en sachant
que son pair ne peut pas modifier la mémoire partagée de manière non
souhaitée.
Voici un exemple d'utilisation du mécanisme de verrouillage :
- (1)
-
Le premier processus crée un fichier tmpfs(5) en utilisant
memfd_create(). L'appel donne un descripteur de fichier utilisé dans les
étapes ultérieures.
- (2)
-
Le premier processus dimensionne le fichier créé à l'étape précédente en
utilisant ftruncate(2), il le projette en utilisant mmap(2) et il
remplit la mémoire partagée avec les données désirées.
- (3)
-
Le premier processus utilise l'opération F_ADD_SEALS de fcntl(2) pour
poser un ou plusieurs verrous sur le fichier afin de restreindre des
modifications ultérieures (si on pose un verrou F_SEAL_WRITE, il sera
nécessaire de désassocier la projection modifiable partagée créée à l'étape
précédente. Sinon, on peut obtenir un comportement identique à
F_SEAL_WRITE en utilisant F_SEAL_FUTURE_WRITE, qui empêchera des
écritures ultérieures à l'aide de mmap(2) et de write(2), tout en
conservant les projections modifiables partagées existantes).
- (4)
-
Un deuxième processus obtient un descripteur de fichier pour le fichier
tmpfs(5) et le projette. Parmi les origines possibles de cela, vous
trouverez :
-
- •
-
Le processus qui a appelé memfd_create() a pu transférer le descripteur
de fichier consécutif au deuxième processus à l'aide d'un socket de domaine
UNIX (voir unix(7) et cmsg(3)). Le deuxième processus projette alors
le fichier en utilisant mmap(2).
- •
-
Le deuxième processus est créé à l'aide de fork(2) et, ainsi, il récupère
automatiquement le descripteur de fichier et sa projection (remarquez que
dans ce cas et dans le prochain, il existe une relation de confiance
naturelle entre les deux processus puisqu'ils tournent sous le même
identifiant utilisateur. Donc, un verrou de fichier n'est, en principe, pas
nécessaire).
- •
-
Le deuxième processus ouvre le fichier
/proc/<pid>/fd/<fd>, où <pid> est
l'identifiant de processus du premier processus (celui qui a appelé
memfd_create()) et <fd> est le numéro du descripteur de
fichier renvoyé par l'appel à memfd_create dans ce processus. Le deuxième
processus projette ensuite le fichier en utilisant mmap(2).
- (5)
-
Le deuxième processus utilise l'opération F_GET_SEALS de fcntl(2) pour
récupérer le masque de bits de verrous appliqué au fichier. Ce masque peut
être examiné pour déterminer le type de restrictions posées aux
modifications du fichier. Si vous le souhaitez, le deuxième processus peut
appliquer des verrous supplémentaires pour imposer d'autres restrictions
(tant que le verrou F_SEAL_SEAL n'a pas encore été appliqué).
EXEMPLES
Voici deux exemples de programme montrant l'utilisation de memfd_create()
et de l'API de verrou de fichier.
Le premier programme, t_memfd_create.c, crée un fichier tmpfs(5) en
utilisant memfd_create(), donne une taille au fichier, le projette en
mémoire et, en option, pose des verrous sur le fichier. Le programme accepte
jusqu'à trois paramètres en ligne de commande, dont les deux premiers sont
requis. Le premier paramètre est le nom à donner au fichier, le deuxième est
la taille à lui donner, le troisième, optionnel, est une chaîne de
caractères qui indique les verrous à poser sur le fichier.
Le deuxième programme, t_get_seals.c, peut être utilisé pour ouvrir un
fichier existant créé à l'aide de memfd_create() et examiner les verrous
qui y sont posés.
La session d'interpréteur suivant montre l'utilisation de ces
programmes. Nous créons d'abord un fichier tmpfs(5) et nous posons des
verrous dessus :
$ ./t_memfd_create my_memfd_file 4096 sw &
[1] 11775
PID: 11775; fd: 3; /proc/11775/fd/3
À ce moment, le programme t_memfd_create continue à s'exécuter en tâche
de fond. À partir d'un autre programme, nous pouvons obtenir un descripteur
de fichier pour le fichier créé par memfd_create() en ouvrant
/proc/pid/fd qui correspond au descripteur de fichier ouvert par
memfd_create(). En utilisant ce chemin, nous examinons le contenu du lien
symbolique /proc/pid/fd et nous utilisons notre programme
t_get_seals pour voir les verrous posés sur le fichier :
$ readlink /proc/11775/fd/3
/memfd:my_memfd_file (deleted)
$ ./t_get_seals /proc/11775/fd/3
Verrous existants : WRITE SHRINK
Source du programme : t_memfd_create.c
#define _GNU_SOURCE
#include <err.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
int fd;
char *name, *seals_arg;
ssize_t len;
unsigned int seals;
if (argc < 3) {
fprintf(stderr, "%s name size [seals]\n", argv[0]);
fprintf(stderr, "\t'seals' can contain any of the "
"following characters:\n");
fprintf(stderr, "\t\tg - F_SEAL_GROW\n");
fprintf(stderr, "\t\ts - F_SEAL_SHRINK\n");
fprintf(stderr, "\t\tw - F_SEAL_WRITE\n");
fprintf(stderr, "\t\tW - F_SEAL_FUTURE_WRITE\n");
fprintf(stderr, "\t\tS - F_SEAL_SEAL\n");
exit(EXIT_FAILURE);
}
name = argv[1];
len = atoi(argv[2]);
seals_arg = argv[3];
/* Créer un fichier anonyme dans tmpfs ; permet de poser
des verrous sur le fichier. */
fd = memfd_create(name, MFD_ALLOW_SEALING);
if (fd == -1)
err(EXIT_FAILURE, "memfd_create");
/* Taille du fichier indiquée sur la ligne de commande. */
if (ftruncate(fd, len) == -1)
err(EXIT_FAILURE, "truncate");
printf("PID: %jd; fd: %d; /proc/%jd/fd/%d\n",
(intmax_t) getpid(), fd, (intmax_t) getpid(), fd);
/* Code pour projeter le fichier et remplir la projection
avec des données omises. */
/* Si un paramètre 'seals' de la ligne de commande est fourni,
poser des verrous sur le fichier. */
if (seals_arg != NULL) {
seals = 0;
if (strchr(seals_arg, 'g') != NULL)
seals |= F_SEAL_GROW;
if (strchr(seals_arg, 's') != NULL)
seals |= F_SEAL_SHRINK;
if (strchr(seals_arg, 'w') != NULL)
seals |= F_SEAL_WRITE;
if (strchr(seals_arg, 'W') != NULL)
seals |= F_SEAL_FUTURE_WRITE;
if (strchr(seals_arg, 'S') != NULL)
seals |= F_SEAL_SEAL;
if (fcntl(fd, F_ADD_SEALS, seals) == -1)
err(EXIT_FAILURE, "fcntl");
}
/* Continuer l’exécution pour que le fichier créé par
memfd_create() continue à exister. */
pause();
exit(EXIT_SUCCESS);
}
Source du programme : t_get_seals.c
#define _GNU_SOURCE
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int fd;
unsigned int seals;
if (argc != 2) {
fprintf(stderr, "%s /proc/PID/fd/FD\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDWR);
if (fd == -1)
err(EXIT_FAILURE, "open");
seals = fcntl(fd, F_GET_SEALS);
if (seals == -1)
err(EXIT_FAILURE, "fcntl");
printf("Existing seals:");
if (seals & F_SEAL_SEAL)
printf(" SEAL");
if (seals & F_SEAL_GROW)
printf(" GROW");
if (seals & F_SEAL_WRITE)
printf(" WRITE");
if (seals & F_SEAL_FUTURE_WRITE)
printf(" FUTURE_WRITE");
if (seals & F_SEAL_SHRINK)
printf(" SHRINK");
printf("\n");
/* Code pour associer le fichier et l'accès au contenu de la
projection résultante omise. */
exit(EXIT_SUCCESS);
}
VOIR AUSSI
fcntl(2), ftruncate(2), memfd_secret(2), mmap(2), shmget(2),
shm_open(3)
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 <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>
et
Jean-Philippe MENGUAL <jpmengual@debian.org>
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 à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- VERSIONS
-
- STANDARDS
-
- NOTES
-
- Verrou de fichiers
-
- EXEMPLES
-
- Source du programme : t_memfd_create.c
-
- Source du programme : t_get_seals.c
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 07:42:26 GMT, May 18, 2024