- Explique la structure mémoire des processus sous Linux au niveau du fonctionnement réel, avec une présentation étape par étape de la relation entre espace d’adressage virtuel et mémoire physique
- Décrit concrètement comment un processus possède et accède à la mémoire, en se concentrant sur des mécanismes clés comme les tables de pages, VMA, mmap, page fault, CoW
- Présente comment observer l’état mémoire de chaque processus via le système de fichiers
/proc, ainsi que le rôle d’outils de diagnostic avancés commepagemapetkpageflags - Traite de l’optimisation des performances et des techniques de dirty tracking en espace utilisateur grâce à des fonctionnalités récentes du noyau comme Transparent Huge Pages (THP), userfaultfd et PAGEMAP_SCAN
- Explique aussi des principes de conception du noyau liés à la sécurité et aux performances, comme PTI contre Meltdown, flush du TLB et politique W^X, afin d’offrir une compréhension d’ensemble de la gestion mémoire sous Linux
Structure de base de la mémoire d’un processus
- Lorsqu’un programme s’exécute, tout se passe comme s’il disposait d’une immense mémoire continue, mais en réalité le noyau Linux l’organise dynamiquement page par page
- Le CPU consulte les tables de pages pour traduire les adresses virtuelles en cadres physiques
- S’il n’existe pas de mapping, un défaut de page (page fault) se produit, et le noyau alloue une nouvelle page ou renvoie une erreur
- Si la RAM physique manque, le noyau déplace sur disque les pages inutilisées ou supprime des pages de fichiers pour libérer de l’espace
/procest un système de fichiers virtuel construit par le noyau en mémoire, qui expose sous forme de fichiers l’état des processus et du noyau
Espace d’adressage et VMA
- Chaque processus possède un objet d’espace d’adressage, dont l’intérieur est composé de plusieurs VMA (Virtual Memory Area)
- Une VMA est une plage d’adresses continue avec les mêmes droits (R/W/X) et le même backend (mémoire anonyme ou fichier)
- La table de pages est la structure référencée par le matériel, qui stocke les informations de mapping (PTE) entre pages virtuelles et pages physiques
- Les modifications de l’espace d’adressage s’effectuent via trois appels système
mmap: crée une nouvelle zonemprotect: modifie les droitsmunmap: supprime le mapping
- La page est l’unité de base de 4 KiB, et certains systèmes prennent aussi en charge de grandes pages de 2 MiB et 1 GiB
Voir la disposition mémoire avec /proc/self/maps
- La commande
cat /proc/self/mapspermet d’inspecter la carte mémoire du processus- On y voit le code, les données et la bss de l’exécutable, le heap, les mappings anonymes, les bibliothèques partagées, la pile, etc.
- Les zones
[vdso]et[vvar]contiennent du code et des données mappés par le noyau pour des appels système rapides
Principe de fonctionnement de mmap
mmapn’alloue pas immédiatement de la mémoire réelle, il enregistre une promesse dans l’espace d’adressage- Les pages sont allouées au premier accès
- Pour un mapping de fichier,
offsetdoit être aligné sur la taille de page, et un accès au-delà de la fin du fichier provoqueSIGBUS MAP_SHAREDrépercute directement les modifications dans le fichier, tandis queMAP_PRIVATEcrée des pages indépendantes par Copy-on-Write (CoW)MAP_FIXED_NOREPLACEaméliore la sûreté en échouant si l’adresse demandée est déjà mappée
Premier accès et défaut de page
- Lors du premier accès à un nouveau mapping, si le CPU ne trouve pas l’entrée correspondante dans la table de pages, un page fault se produit
- Le noyau vérifie la validité de l’adresse, les droits d’accès et l’existence de la zone
- Pour un mapping anonyme, il alloue une nouvelle page remplie de zéros ; pour un mapping de fichier, il lit depuis le page cache
- Un minor fault se produit lorsque les données sont déjà en RAM, un major fault lorsqu’une E/S disque est nécessaire
- La pile est protégée par une guard page ; un accès trop en dessous provoque
SIGSEGV
fork() et le Copy-on-Write de MAP_PRIVATE
- Lors d’un
fork, le parent et l’enfant partagent les mêmes pages physiques, marquées en lecture seule pour les deux- Une nouvelle page n’est copiée qu’au moment de l’écriture afin de conserver leur indépendance
- Les mappings de fichiers
MAP_PRIVATEfonctionnent selon le même principe - Options associées
vfork: partage l’espace d’adressage du parentclone(CLONE_VM): crée un threadMADV_DONTFORK,MADV_WIPEONFORK: excluent le mapping du processus enfant ou le réinitialisent à zéro
Changement de droits et invalidation du TLB
- Lorsqu’on modifie les droits d’une page avec
mprotect, le noyau scinde éventuellement la VMA et modifie la table de pages, puis effectue une invalidation du TLB - Selon la politique W^X, une page ne peut pas être à la fois inscriptible et exécutable
- Le TLB (Translation Lookaside Buffer) est un cache des traductions d’adresses récentes ; son invalidation introduit un léger délai
Observation détaillée via /proc
/proc/<pid>/maps,smapsetsmaps_rolluppermettent de voir, par zone, les droits, la RSS et l’usage des HugePages/proc/<pid>/pagemapfournit l’état page par page (présence, swap, PFN, etc.), mais les PFN ne sont pas accessibles aux utilisateurs ordinaires/proc/kpagecountet/proc/kpageflagsaffichent, pour chaque PFN, le nombre de mappings et les propriétés de page (anonyme, fichier, dirty, etc.)mincoreetSEEK_DATA/SEEK_HOLEpermettent d’identifier les zones de données et les trous dans les fichiers creux- En combinant
PAGEMAP_SCANetuserfaultfd, il est possible d’implémenter un dirty tracking en espace utilisateur
Transparent Huge Pages (THP) et mTHP
- THP regroupe automatiquement la mémoire fréquemment accédée en grandes pages (2 MiB, par exemple) afin d’améliorer l’efficacité du TLB
- Le thread
khugepagedfusionne les pages adjacentes
- Le thread
- mTHP prend en charge des grandes pages variables (folio) de tailles diverses, comme 16 KiB ou 64 KiB
- On peut vérifier leur utilisation via
AnonHugePagesetFilePmdMappeddans/proc/self/smaps - La configuration globale du système se gère dans
/sys/kernel/mm/transparent_hugepage/ MADV_HUGEPAGEetMADV_NOHUGEPAGEpermettent un contrôle par zone
Dirty tracking en espace utilisateur
userfaultfdetPAGEMAP_SCANpermettent de ne copier que les pages modifiées- Le noyau effectue en une seule opération atomique le scan et la protection en écriture
- Cette approche est efficace pour les snapshots, la live migration, etc.
Mécanisme de flush du TLB
- Sur x86, l’invalidation du TLB se fait de deux façons
INVLPG: invalide une seule page- rechargement de la racine des tables de pages pour un flush complet
PCIDetINVPCIDréduisent les flush inutiles grâce à une gestion des tags TLB par processustlb_single_page_flush_ceilingest le seuil utilisé par le noyau pour choisir entre flush page par page et flush complet
Réponse à Meltdown : Page Table Isolation (PTI)
- Meltdown est une vulnérabilité où des données du noyau peuvent être exposées via le cache pendant l’exécution spéculative
- Linux utilise PTI (Page Table Isolation) pour séparer les espaces d’adressage utilisateur et noyau
- À l’entrée, un basculement de
CR3active une table de pages dédiée au noyau PCIDest utilisé pour minimiser les flush du TLB
- À l’entrée, un basculement de
- Cette protection est activée par défaut et peut être désactivée avec
nopti
Procédure sûre du noyau pour modifier les mappings
- Lors d’une modification de mapping, l’ordre est le suivant
- traitement des règles de cache
- modification de la table de pages
- invalidation du TLB
- Les mappings internes au noyau (
vmap,vmalloc) synchronisent eux aussi cache et TLB avant et après les E/S - Certaines architectures nécessitent un flush du cache d’instructions après copie de code
Structure de pile et d’appel sur x86
- En mode 64 bits, les registres RIP, RSP et RBP sont utilisés, et la pile croît vers le bas
- Selon l’ABI System V AMD64, les arguments sont passés dans RDI, RSI, RDX, RCX, R8, R9, et la valeur de retour dans RAX
- Le mode utilisateur fonctionne en ring 3, le noyau en ring 0, et les appels système ainsi que les interruptions passent par des gates
Situations d’erreur et diagnostic
mmap→EINVAL: erreur d’alignement de l’offset du fichiermmap→ENOMEM: manque d’espace virtuel ou limitation d’overcommit- accès à un mapping de fichier →
SIGBUS: accès au-delà de l’EOF mprotect(PROT_EXEC)→EACCES: montagenoexecou politique W^X- augmentation de la RSS après
fork(): copie de pages due au CoW - écrasement d’un mapping existant avec
MAP_FIXED→MAP_FIXED_NOREPLACErecommandé
Checklist pratique
- Obtenir immédiatement de la mémoire :
mmap+PROT_READ|PROT_WRITE+MAP_PRIVATE|MAP_ANONYMOUS - Génération de code : conserver W^X, puis
mprotect(PROT_READ|PROT_EXEC) - Mapping de fichier : aligner
offsetsur la taille de page, ne pas accéder au-delà de l’EOF - En cas de nombreux page faults :
MADV_WILLNEEDou pré-accès - Analyse de l’usage mémoire :
/proc/<pid>/smaps_rollup→/proc/<pid>/maps forkde gros processus : prendre en compte le CoW, utiliserexecdans l’enfant- Environnement sensible à la latence : observer THP/mTHP,
mlocket le comportement du TLB
1 commentaires
Commentaires sur Hacker News
J’aime vraiment ce genre de courts billets explicatifs
Même quand je connais déjà le sujet, ça m’aide à le revalider une fois de plus pendant la lecture
Quand je vois une formule comme « mmap, without the fog », j’ai l’impression que c’est un texte coécrit par un LLM, et ça me met mal à l’aise et m’agace pour rien
Avec en plus une expression bizarre comme « without the fog », ça donne vraiment l’impression que chatgpt a participé à la rédaction
En voyant parler d’instruction pipelining, ça me donne envie de revenir à l’époque des architectures simples comme le 6502
À l’époque, ça fonctionnait « tel quel », sans mappings compliqués ni proxies
Avec des interconnexions rapides, on pourrait presque se remettre à rêver de cette simplicité
Mais quand on voit des problèmes comme Meltdown ou Spectre, on voit aussi clairement le prix payé pour cette complexité
Maintenant que la loi de Moore atteint ses limites, on peut se demander si ce compromis de complexité est vraiment optimal
Je ne pense pas que la simplicité soit forcément meilleure
Le site est indiqué comme bloqué parce qu’il appartiendrait à un domaine dangereux ou non sûr
D’après le résultat d’analyse VirusTotal, il n’y a pas de problème
Je me demande ce que veut dire le fait que le rapport d’erreur ne soit que du « bruit » (noise)