it-swarm.com.de

Der Unterschied zwischen initrd und initramfs?

Soweit ich weiß, fungiert initrd als Blockgerät und erfordert daher einen Dateisystemtreiber (wie ext2). Der Kernel muss über mindestens ein integriertes Modul zur Erkennung des Dateisystems von initrd verfügen. In diesem Artikel Einführung in initramfs, ein neues Modell für erste RAM -Datenträger , wird Folgendes geschrieben:

Allerdings verschwenden RAM-Disks aufgrund von Zwischenspeicherung sogar noch mehr Speicherplatz. Linux ist zum Zwischenspeichern aller gelesenen oder geschriebenen Dateien und Verzeichniseinträge Um Geräte zu blockieren, kopiert Linux Daten von und zur Ramdisk in den "Seiten-Cache" (für Dateidaten) und den "Dentry-Cache" (für Verzeichniseinträge). Der Nachteil der Ramdisk, der vorgibt, ein .__ zu sein. Blockgerät wird es wie ein Blockgerät behandelt.

Was ist page cache und dentry cache? Bedeutet das im Abschnitt, dass die Daten dupliziert wurden, weil ramdisk als Blockgerät behandelt wird und somit alle Daten zwischengespeichert werden?

In der Bedingung ramfs:

Vor ein paar Jahren hatte Linus Torvalds eine gute Idee: Was wäre, wenn der Cache von Linux könnte wie ein Dateisystem gemountet werden? Behalten Sie einfach die Dateien im Cache und niemals loswerden, bis sie gelöscht werden oder das System neu startet? Linus hat einen kleinen Wrapper um den Cache geschrieben, der "ramfs" und andere Kernel-Entwickler erstellten eine verbesserte Version namens "tmpfs" (mit der Daten in den Auslagerungsspeicher geschrieben werden können und die Größe eines angegebenen Mount-Punktes begrenzt wird, damit der Speicher voll ist, bevor der gesamte verfügbare Speicherplatz verbraucht wird). Initramfs ist eine Instanz von tmpfs.

Diese RAM-basierten Dateisysteme werden automatisch vergrößert oder verkleinert, um auf die .__ zu passen. Größe der Daten, die sie enthalten. Durch das Hinzufügen von Dateien zu einem Ramfs (oder das Erweitern vorhandener Vorhandener Dateien) wird automatisch mehr Speicherplatz zugewiesen. Durch das Abschneiden von Dateien wird dieser Speicher freigegeben. Es gibt keine Doppelung zwischen Blockgerät und Cache, weil es kein Blockgerät gibt. Die Kopie in Der Cache ist die einzige Kopie der Daten. Das Beste ist, dass dies nicht neu ist. Code, aber eine neue Anwendung für den vorhandenen Linux-Cache-Code, der bedeutet, dass es fast keine Größe hinzufügt, sehr einfach ist und auf .__ basiert. extrem gut getestete Infrastruktur.

In der Summe ist ramfs nur eine Datei, die geöffnet und in den Speicher geladen wird, nicht wahr? 

Sowohl initrd als auch ramfs werden zur Kompilierzeit gezippt. Der Unterschied besteht jedoch darin, dass initrd ein nicht entpacktes Block-Device ist, das vom Kernel beim Booten eingebunden wird, während ramfs über cpio in den Arbeitsspeicher entpackt wird. Hab ich recht? Oder ist ramfs ein sehr minimales Dateisystem?

Schließlich wird bis heute das initrd-Bild im neuesten Kernel angezeigt. Ist diese initrd tatsächlich die heute verwendete ramfs und der Name dient nur historischen Zwecken? 

48
Amumu

Dentry (und Inode) Cache

Das Dateisystem-Subsystem in Linux besteht aus drei Schichten. Das VFS (virtuelles Dateisystem), das die Schnittstelle für Systemaufrufe implementiert und das Überkreuzen von Einhängepunkten sowie Standardberechtigungen und Grenzwertprüfungen behandelt. Darunter befinden sich die Treiber für einzelne Dateisysteme und diese wiederum haben eine Schnittstelle zu Treibern für Blockgeräte (Festplatten, Speicherkarten usw.; Netzwerkschnittstellen bilden eine Ausnahme).

Die Schnittstelle zwischen VFS und dem Dateisystem besteht aus mehreren Klassen (es ist einfaches C, also Strukturen, die Zeiger auf Funktionen und dergleichen enthalten, jedoch konzeptuell eine objektorientierte Schnittstelle). Die drei Hauptklassen sind inode, die jedes Objekt (Datei oder Verzeichnis) in einem Dateisystem beschreibt, dentry, das den Eintrag in einem Verzeichnis beschreibt, und file, das die von einem Prozess geöffnete Datei beschreibt. Wenn der Dateisystemtreiber gemountet ist, erstellt er inode und dentry für das Stammverzeichnis und die anderen werden auf Anforderung erstellt, wenn der Prozess auf eine Datei zugreifen möchte und eventuell abgelaufen ist. Das ist ein Dentry- und Inode-Cache.

Ja, es bedeutet, dass für jede geöffnete Datei und jedes Verzeichnis bis zum Stammverzeichnis inode und dentry Strukturen im Kernelspeicher vorhanden sein müssen, die sie darstellen.

Seiten-Cache

In Linux wird jede Speicherseite, die Benutzerlanddaten enthält, durch eine einheitliche page-Struktur dargestellt. Dies kann dazu führen, dass die Seite entweder als anonym gekennzeichnet wird (wenn vorhanden, um Speicherplatz auszutauschen) oder mit inode in einem Dateisystem verknüpft wird (wird möglicherweise in das Dateisystem zurückgeschrieben und erneut gelesen), und es kann Teil einer beliebigen Anzahl von Speicher sein Karten, dh sichtbar im Adressraum eines Prozesses. Die Summe aller aktuell in den Speicher geladenen Seiten ist der Seitencache.

Die Seiten werden zur Implementierung der mmap-Schnittstelle verwendet. Während reguläre Lese- und Schreibsystemaufrufe vom Dateisystem auf andere Weise implementiert werden können, verwenden die meisten Schnittstellen eine generische Funktion, die auch Seiten verwendet. Es gibt generische Funktionen, die, wenn das Lesen von Dateien angefordert wird, Seiten zuordnen und das Dateisystem aufrufen, diese nacheinander auszufüllen. Bei einem auf einem Blockgerät basierenden Dateisystem werden lediglich die entsprechenden Adressen berechnet und diese Befüllung an den Blockgerätetreiber delegiert.

ramdev (Ramdisk)

Ramdev ist ein normales Blockgerät. Dies ermöglicht das Layering eines beliebigen Dateisystems darüber, ist jedoch durch die Blockgeräteschnittstelle eingeschränkt. Und das hat nur Methoden, um eine vom Anrufer zugewiesene Seite auszufüllen und zurückzuschreiben. Das ist genau das, was für echte Blockgeräte wie Festplatten, Speicherkarten, USB-Massenspeicher und dergleichen benötigt wird, aber für Ramdisk bedeutet dies, dass die Daten zweimal im Speicher vorhanden sind, einmal im Speicher des Ramdev und einmal im vom Speicher zugewiesenen Speicher Anrufer.

Dies ist die alte Art der Implementierung von initrd. Aus Zeiten, als initrd selten und exotisch vorkam.

tmpfs

Tmpfs ist anders. Es ist ein Dummy-Dateisystem. Die Methoden, die VFS zur Verfügung stellt, sind das absolut Nötigste, um funktionieren zu können (als solches ist es eine exzellente Dokumentation der Inode-, Dentry- und File-Methoden). Dateien sind nur vorhanden, wenn der Inode-Cache entsprechende Inode und Dentry enthält, die beim Erstellen der Datei erstellt werden und niemals verfallen, wenn die Datei nicht gelöscht wird. Die Seiten sind Dateien zugeordnet, wenn Daten geschrieben werden, und verhalten sich ansonsten wie anonym (Daten können zum Auslagern gespeichert werden, page-Strukturen bleiben in Gebrauch, solange die Datei vorhanden ist).

Dies bedeutet, dass sich keine zusätzlichen Kopien der Daten im Speicher befinden und das Ganze ist viel einfacher und daher auch etwas schneller. Es verwendet einfach die Datenstrukturen, die als Cache für jedes andere Dateisystem dienen, als Primärspeicher.

Dies ist die neue Art der Implementierung von initrd (initramfs, aber das Bild wird immer noch als initrd bezeichnet).

Dies ist auch der Weg zur Implementierung von "posix shared memory" (was einfach bedeutet, dass tmpfs an /dev/shm angehängt ist und Anwendungen dort frei sind, um Dateien zu erstellen und sie zu mappen; einfach und effizient). In letzter Zeit haben sogar /tmp und /run (oder /var/run) häufig tmpfs Speziell auf Notebooks montiert, um zu verhindern, dass Festplatten hochgefahren werden oder Verschleiß bei SSDs.

42
Jan Hudec

Ich denke, dass du in allem Recht hast.

Der Unterschied ist leicht zu erkennen, wenn Sie den beim Booten erforderlichen Schritten folgen:

initrd

  • Ein ramdev-Blockgerät wird erstellt. Es handelt sich um ein RAM-basiertes Blockgerät, dh eine simulierte Festplatte, die Speicher statt physischer Festplatten verwendet.
  • Die initrd-Datei wird gelesen und in das Gerät entpackt, als ob Sie zcat initrd | dd of=/dev/ram0 oder etwas Ähnliches getan hätten. 
  • Die initrd enthält ein Image eines Dateisystems, sodass Sie das Dateisystem jetzt wie gewohnt einhängen können: mount /dev/ram0 /root. Dateisysteme benötigen natürlich einen Treiber. Wenn Sie ext2 verwenden, muss der ext2-Treiber im Kernel kompiliert werden.
  • Erledigt!

initramfs

  • Eine tmpfs ist gemountet: mount -t tmpfs nodev /root. Das tmpfs benötigt keinen Treiber, es ist immer ein Kernel. Kein Gerät erforderlich, keine zusätzlichen Treiber.
  • Die initramfs wird direkt in dieses neue Dateisystem dekomprimiert: zcat initramfs | cpio -i oder ähnliches.
  • Erledigt!

Und ja, es wird an vielen Stellen noch initrd genannt, obwohl es eine initramfs ist, insbesondere in Bootloadern, da es für sie nur ein BLOB ist. Den Unterschied macht das Betriebssystem beim Booten.

52
rodrigo

Um einen weiteren bemerkenswerten Unterschied zwischen initrd und initramfs hinzuzufügen, der in der ausgezeichneten Antwort oben nicht erwähnt wurde.

  • Mit initrd wird der Kernel standardmäßig an den Userspace pid 0 um /sbin/init übergeben.
  • Neuere initramfs ändern jedoch Dinge und führen pid 0 bei /init aus.

da es eine Falle werden könnte (siehe https://unix.stackexchange.com/a/147688/24394 )

0

Minimal ausführbare QEMU-Beispiele und Neulinge-Erklärung

In dieser Antwort werde ich:

  • ein minimal ausführbares Buildroot + QEMU-Beispiel, in dem Sie die Dinge testen können
  • erklären Sie den grundlegendsten Unterschied zwischen beiden für die Anfänger, die dies wahrscheinlich googeln

Hoffentlich dienen diese als Grundlage für die Überprüfung und das Verständnis der detaillierteren Details der Unterschiede.

Das minimale Setup ist hier vollautomatisiert , und dies ist das entsprechende Erste Schritte .

Das Setup druckt die QEMU-Befehle aus, während sie ausgeführt werden. Wie in diesem Repo erläutert, können wir problemlos die drei folgenden Arbeitstypen von Booten erstellen:

  1. das Root-Dateisystem befindet sich auf einer ext2-Festplatte:

    qemu-system-x86_64 -kernel normal/bzImage -drive file=rootfs.ext2
    
  2. das Root-Dateisystem befindet sich in initrd:

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

    -drive ist nicht angegeben.

    rootfs.cpio enthält die gleichen Dateien wie rootfs.ext2, außer dass sie sich im Format CPIO befinden. Dieses Format ähnelt .tar: Es serialisiert Verzeichnisse ohne sie zu komprimieren.

  3. das Root-Dateisystem befindet sich in initramfs:

    qemu-system-x86_64 -kernel with_initramfs/bzImage
    

    Weder -drive noch -initrd sind angegeben.

    with_initramfs/bzImage ist ein Kernel, der mit identischen Optionen wie normal/bzImage kompiliert ist, mit Ausnahme von einer: CONFIG_INITRAMFS_SOURCE=rootfs.cpio, die auf genau dieselbe CPIO verweist wie im -initrd-Beispiel.

Durch den Vergleich der Setups können wir die grundlegendsten Eigenschaften von jedem abschließen:

  1. im Festplatten-Setup lädt QEMU bzImage in den Arbeitsspeicher.

    Diese Arbeit wird normalerweise von Bootloadern/Firmware in echter Hardware z. B. GRUB ausgeführt.

    Der Linux-Kernel bootet dann mit seinen Treibern das Root-Dateisystem von der Festplatte.

  2. im initrd-Setup führt QEMU neben dem Laden des Kernels in den Arbeitsspeicher noch einige weitere Bootloader-Funktionen aus:

    Diesmal verwendet der Kernel den rootfs.cpio direkt aus dem Speicher, da keine Festplatte vorhanden ist.

    Schreibvorgänge sind nach Neustarts nicht dauerhaft, da sich alles im Speicher befindet

  3. im initramfs-Setup bauen wir den Kernel etwas anders: Wir geben auch den rootfs.cpio an das Kernel-Build-System.

    Das Kernel-Build-System weiß dann, wie es das Kernel-Image und das CPIO zu einem einzigen Image zusammenfügt.

    Daher müssen wir das bzImage nur an QEMU übergeben. QEMU lädt es wie in den anderen Setups in image, aber es ist nichts anderes erforderlich: Der CPIO wird ebenfalls in den Speicher geladen, da er mit dem Kernel-Image verklebt ist!