102 votes

La différence entre initrd et initramfs

Dans la mesure de mes connaissances, initrd agit comme un périphérique bloc, nécessitant donc un pilote de système de fichiers (tel que ext2). Le noyau doit avoir au moins un module intégré pour détecter le système de fichiers de initrd. Dans cet article, Présentation de l'initramfs, un nouveau modèle pour les disques RAM initiaux, il est écrit que :

Mais les ramdisks gaspillent en fait encore plus de mémoire en raison du cache. Linux est conçu pour mettre en cache tous les fichiers et entrées de répertoires lus à partir ou écrits sur des périphériques blocs, donc Linux copie les données du ramdisk vers et depuis le "cache de pages" (pour les données de fichiers), et le "cache d'entrées d'entrée" (pour les entrées de répertoire). L'inconvénient du ramdisk se faisant passer pour un périphérique bloc est qu'il est traité comme un périphérique bloc.

Qu'est-ce que le cache de pages et le cache d'entrées d'entrée? Dans le paragraphe, est-ce que cela signifie que les données sont dupliquées car le ramdisk est traité comme un périphérique bloc, donc toutes les données sont mises en cache?

En revanche, le ramfs :

Il y a quelques années, Linus Torvalds a eu une idée intéressante : Et si le cache de Linux pouvait être monté comme un système de fichiers? Il suffit de garder les fichiers en mémoire cache et de ne jamais s'en débarrasser jusqu'à ce qu'ils soient supprimés ou que le système redémarre? Linus a écrit un petit wrapper autour du cache appelé "ramfs", et d'autres développeurs de noyau ont créé une version améliorée appelée "tmpfs" (qui peut écrire les données dans l'espace d'échange, et limiter la taille d'un point de montage donné pour qu'il se remplisse avant de consommer toute la mémoire disponible). Initramfs est une instance de tmpfs.

Ces systèmes de fichiers basés sur la RAM grandissent ou rétrécissent automatiquement pour s'adapter à la taille des données qu'ils contiennent. Ajouter des fichiers à un ramfs (ou étendre des fichiers existants) alloue automatiquement plus de mémoire, et supprimer ou tronquer des fichiers libère cette mémoire. Il n'y a pas de duplication entre le périphérique bloc et le cache, car il n'y a pas de périphérique bloc. La copie dans le cache est la seule copie des données. Et le mieux, ce n'est pas un nouveau code mais une nouvelle application pour le code de mise en cache Linux existant, ce qui signifie qu'il ajoute presque aucune taille, est très simple et repose sur une infrastructure extrêmement bien testée.

En résumé, le ramfs est simplement un fichier ouvert et chargé en mémoire, n'est-ce pas?

Les deux initrd et ramfs sont compressés au moment de la compilation, mais la différence est que initrd est un périphérique bloc décompressé pour être monté par le noyau au démarrage, tandis que ramfs est décompressé via cpio en mémoire. Ai-je raison? Ou est-ce que ramfs est un système de fichiers très minimal?

Enfin, jusqu'à ce jour, l'image initrd est encore présentée dans le dernier noyau. Cependant, est-ce que cet initrd est en fait le ramfs utilisé actuellement et le nom est-il simplement à des fins historiques?

100voto

rodrigo Points 34500

Je pense que tu as raison sur tout.

La différence est facile à voir si tu suis les étapes nécessaires au démarrage :

initrd

  • Un périphérique bloc ramdev est créé. Il s'agit d'un périphérique bloc basé sur la RAM, c'est-à-dire un disque dur simulé qui utilise la mémoire au lieu de disques physiques.
  • Le fichier initrd est lu et décompressé dans le périphérique, comme si tu avais fait zcat initrd | dd of=/dev/ram0 ou quelque chose de similaire.
  • L'initrd contient une image d'un système de fichiers, donc maintenant tu peux monter le système de fichiers comme d'habitude : mount /dev/ram0 /root. Naturellement, les systèmes de fichiers ont besoin d'un pilote, donc si tu utilises ext2, le pilote ext2 doit être compilé dans le noyau.
  • Fini !

initramfs

  • Un tmpfs est monté : mount -t tmpfs nodev /root. Le tmpfs n'a pas besoin de pilote, il est toujours dans le noyau. Aucun périphérique nécessaire, aucun pilote supplémentaire.
  • L'initramfs est directement décompressé dans ce nouveau système de fichiers : zcat initramfs | cpio -i, ou quelque chose de similaire.
  • Fini !

Et oui, il est toujours appelé initrd dans de nombreux endroits même s'il s'agit d'un initramfs, particulièrement dans les chargeurs de démarrage, car pour eux c'est juste un BLOB. La différence est faite par le système d'exploitation au démarrage.

63voto

Jan Hudec Points 27417

Cache de dentry (et inode)

Le sous-système de système de fichiers dans Linux a trois couches. Le VFS (système de fichiers virtuel), qui implémente l'interface des appels système et gère le franchissement des points de montage et les vérifications par défaut des autorisations et des limites. En dessous se trouvent les pilotes pour les systèmes de fichiers individuels qui à leur tour interagissent avec des pilotes pour les périphériques de bloc (disques, cartes mémoire, etc.; les interfaces réseau sont une exception).

L'interface entre le VFS et le système de fichiers comprend plusieurs classes (c'est du code C simple, donc les structures contiennent des pointeurs de fonctions, mais c'est une interface orientée objet conceptuellement). Les trois principales classes sont inode, qui décrit tout objet (fichier ou répertoire) dans un système de fichiers, dentry, qui décrit une entrée dans un répertoire et file, qui décrit un fichier ouvert par un processus. Lorsqu'un système de fichiers est monté, le pilote crée inode et dentry pour sa racine et les autres sont créés à la demande lorsqu'un processus souhaite accéder à un fichier et expire finalement. C'est une cache de dentry et inode.

Oui, cela signifie que pour chaque fichier ouvert et pour chaque répertoire jusqu'à la racine, il doit y avoir des structures inode et dentry allouées dans la mémoire du noyau les représentant.

Cache de page

Dans Linux, chaque page mémoire contenant des données de l'espace utilisateur est représentée par une structure de page unifiée. Cela peut marquer la page comme anonyme (pouvant être transférée dans l'espace d'échange si disponible) ou l'associer à un inode sur un système de fichiers (pouvant être écrit de nouveau sur le système de fichiers) et elle peut faire partie de n'importe quel nombre de cartes mémoire, c'est-à-dire visibles dans l'espace d'adressage d'un processus. La somme de toutes les pages actuellement chargées en mémoire est la cache de pages.

Les pages sont utilisées pour mettre en œuvre l'interface mmap et tandis que les appels système de lecture et d'écriture classiques peuvent être mis en œuvre par le système de fichiers par d'autres moyens, la majorité des interfaces utilisent une fonction générique qui utilise également des pages. Il existe des fonctions génériques qui, lorsqu'une lecture de fichier est demandée, allouent des pages et appellent le système de fichiers pour les remplir, une par une. Pour les systèmes de fichiers basés sur des périphériques de bloc, il calcule simplement les adresses appropriées et délègue ce remplissage au pilote du périphérique de bloc.

ramdev (disque RAM)

Ramdev est un périphérique de bloc classique. Cela permet de superposer n'importe quel système de fichiers dessus, mais il est limité par l'interface du périphérique de bloc. Et cela a juste des méthodes pour remplir une page allouée par l'appelant et l'écrire à nouveau. C'est exactement ce dont un vrai périphérique de bloc comme les disques, les cartes mémoire, le stockage de masse USB, etc., a besoin, mais pour un disque RAM, cela signifie que les données existent en mémoire deux fois, une fois dans la mémoire du ramdev et une fois dans la mémoire allouée par l'appelant.

C'est l'ancienne manière de mettre en œuvre initrd. À l'époque où initrd était une occurrence rare et exotique.

tmpfs

Tmpfs est différent. C'est un système de fichiers bidon. Les méthodes qu'il fournit au VFS sont le strict minimum nécessaire pour le faire fonctionner (en tant que tel, c'est une excellente documentation de ce que les méthodes inode, dentry et file doivent faire). Les fichiers n'existent que s'il y a un inode et une dentry correspondante dans la cache d'inodes, créés lorsque le fichier est créé et jamais expirés sauf si le fichier est supprimé. Les pages sont associées aux fichiers lorsque les données sont écrites et agissent par ailleurs comme des pages anonymes (les données peuvent être stockées dans l'échange, les structures de page restent en cours d'utilisation tant que le fichier existe).

Cela signifie qu'il n'y a pas de copies supplémentaires des données en mémoire et que tout le processus est beaucoup plus simple et donc légèrement plus rapide aussi. Il utilise simplement les structures de données qui servent de cache pour n'importe quel autre système de fichiers, comme son espace de stockage principal.

C'est la nouvelle manière de mettre en œuvre initrd (initramfs, mais l'image est toujours appelée simplement initrd).

C'est aussi la manière de mettre en œuvre la "mémoire partagée POSIX" (ce qui signifie simplement que tmpfs est monté sur /dev/shm et que les applications sont libres de créer des fichiers là-bas et de les associer; simple et efficace) et récemment même /tmp et /run (ou /var/run) ont souvent tmpfs monté surtout sur des ordinateurs portables pour éviter que les disques ne tournent ou pour éviter une certaine usure en cas de disques SSD.

11voto

Ciro Santilli Points 3341

Exemples QEMU minimaux et explications pour débutants

Dans cette réponse, je vais :

  • fournir un exemple minimaliste de Buildroot + QEMU pour que vous puissiez tester les choses
  • expliquer la différence la plus fondamentale entre les deux pour les débutants absolus qui recherchent probablement sur Google

J'espère que cela servira de base pour vérifier et comprendre les détails plus spécifiques des différences internes.

La configuration minimale est entièrement automatisée ici, et voici le guide de mise en route correspondant.

La configuration affiche les commandes QEMU telles qu'elles sont exécutées, et comme expliqué dans ce dépôt, nous pouvons facilement produire les trois types de démarrage suivants :

  1. le système de fichiers racine est sur un "disque dur" ext2 :

    qemu-system-x86_64 -kernel normal/bzImage -drive file=rootfs.ext2
  2. le système de fichiers racine est dans initrd :

    qemu-system-x86_64 -kernel normal/bzImage -initrd rootfs.cpio

    -drive n'est pas fourni.

    rootfs.cpio contient les mêmes fichiers que rootfs.ext2, sauf qu'ils sont au format CPIO, qui est similaire à .tar : il sérialise les répertoires sans les compresser.

  3. le système de fichiers racine est dans initramfs :

    qemu-system-x86_64 -kernel with_initramfs/bzImage

    Ni -drive ni -initrd ne sont indiqués.

    with_initramfs/bzImage est un noyau compilé avec des options identiques à normal/bzImage, à l'exception d'une : CONFIG_INITRAMFS_SOURCE=rootfs.cpio pointant vers le même CPIO exact que dans l'exemple -initrd.

En comparant les configurations, nous pouvons en conclure les propriétés les plus fondamentales de chacune :

  1. dans la configuration du disque dur, QEMU charge bzImage en mémoire.

    Ce travail est normalement effectué par des chargeurs d'amorçage / firmwares sur du matériel réel, comme GRUB.

    Le noyau Linux démarre, puis en utilisant ses pilotes lit le système de fichiers racine depuis le disque.

  2. dans la configuration initrd, QEMU effectue un peu plus de travail de chargeur d'amorçage en plus de charger le noyau en mémoire : il :

    Cette fois-ci, le noyau utilise simplement le rootfs.cpio directement en mémoire, puisqu'aucun disque dur n'est présent.

    Les écritures ne sont pas persistantes entre les redémarrages, puisque tout est en mémoire.

  3. dans la configuration initramfs, nous construisons un peu différemment le noyau : nous donnons également le rootfs.cpio au système de construction du noyau.

    Le système de construction du noyau sait alors comment assembler l'image du noyau et le CPIO ensemble dans une seule image.

    Par conséquent, tout ce que nous avons à faire est de passer le bzImage à QEMU. QEMU le charge en mémoire, tout comme il l'a fait pour les autres configurations, mais rien d'autre n'est nécessaire : le CPIO est également chargé en mémoire car il est attaché à l'image du noyau !

5voto

humanityANDpeace Points 471

Pour ajouter une autre différence marquante entre initrd et initramfs non mentionnée dans l'excellente réponse ci-dessus.

  • Avec initrd, le kernel remet par défaut le contrôle à l'espace utilisateur pid 1 à /sbin/init
  • Cependant, avec les initramfs plus récents, les choses changent et exécutent pid 1 à /init

car cela pourrait devenir un piège (voir https://unix.stackexchange.com/a/147688/24394)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X