web-dev-qa-db-ja.com

initrdとinitramfsの違いは?

私の知る限り、initrdはブロックデバイスとして機能するため、ファイルシステムドライバー(ext2)。カーネルには、initrdのファイルシステムを検出するための組み込みモジュールが少なくとも1つ必要です。この記事では、 initramfsの紹介、初期RAMディスク の新しいモデル、次のように書かれています。

しかし、実際にはRAMディスクはキャッシュのためにさらに多くのメモリを浪費します。 Linuxは、ブロックデバイスとの間で読み書きされるすべてのファイルとディレクトリエントリをキャッシュするように設計されているため、LinuxはRAMディスクとの間でデータを「ページキャッシュ」(ファイルデータ用)および「デントキャッシュ」(ディレクトリエントリ用)にコピーします。ブロックデバイスのふりをしたRAMディスクの欠点は、ブロックデバイスのように扱われることです。

page cacheおよびdentry cache?段落では、ramdiskがブロックデバイスとして扱われ、すべてのデータがキャッシュされるため、データが複製されたことを意味しますか?

Constrastでは、ramfs

数年前、Linus Torvaldsはきちんとしたアイデアを持っていました。Linuxのキャッシュをファイルシステムのようにマウントできるとしたらどうでしょうか。ファイルをキャッシュに保持し、それらが削除されるかシステムが再起動するまでそれらを削除しないでください? Linusは「ramfs」と呼ばれるキャッシュの周りに小さなラッパーを作成し、他のカーネル開発者は「tmpfs」と呼ばれる改良版を作成しました。すべての利用可能なメモリ)。 Initramfsはtmpfsのインスタンスです。

これらのRAMベースのファイルシステムは、含まれるデータのサイズに合わせて自動的に拡大または縮小します。 ramfsにファイルを追加(または既存のファイルを拡張)すると、より多くのメモリが自動的に割り当てられ、ファイルを削除または切り捨てるとそのメモリが解放されます。ブロックデバイスがないため、ブロックデバイスとキャッシュの間に重複はありません。キャッシュ内のコピーがデータの唯一のコピーです。とりわけ、これは新しいコードではなく、既存のLinuxキャッシングコード用の新しいアプリケーションです。つまり、サイズをほとんど追加せず、非常にシンプルで、非常によくテストされたインフラストラクチャに基づいています。

要するに、ramfsはファイルを開いてメモリにロードするだけです。

initrdramfsは両方ともコンパイル時に圧縮されますが、違いは、initrdは、起動時にカーネルによってマウントされるようにアンパックされたブロックデバイスであり、ramfsはcpioを介してメモリに展開されます。私は正しいですか?または、ramfsは非常に最小限のファイルシステムですか?

最後に、今日まで、initrdイメージはまだ最新のカーネルに表示されています。しかし、initrdは実際に今日使用されているramfsであり、名前は歴史的な目的のためだけのものですか?

54
Amumu

Dentry(およびiノード)キャッシュ

Linuxのファイルシステムサブシステムには3つの層があります。システムを実装するVFS(仮想ファイルシステム)はインターフェースを呼び出し、クロスマウントポイントとデフォルトの許可および制限チェックを処理します。その下には、個々のファイルシステムのドライバーと、ブロックデバイス(ディスク、メモリーカードなど。ネットワークインターフェイスは例外です)のドライバーへのインターフェイスがあります。

VFSとファイルシステム間のインターフェースはいくつかのクラスです(プレーンCなので、関数などへのポインターを含む構造ですが、概念的にはオブジェクト指向のインターフェースです)。主な3つのクラスは、ファイルシステム内のオブジェクト(ファイルまたはディレクトリ)を記述するinode、ディレクトリ内のエントリを記述するdentry、およびファイルオープンを記述するfileです。プロセスによって。マウントされると、ファイルシステムドライバーはそのルート用にinodedentryを作成し、他のものはプロセスがファイルにアクセスして最終的に期限切れになるときにオンデマンドで作成されます。これはdentryとiノードのキャッシュです。

はい、すべての開いているファイルとルートまでのディレクトリごとに、それを表すカーネルメモリにinodeおよびdentry構造が割り当てられている必要があります。

ページキャッシュ

Linuxでは、ユーザーランドデータを含む各メモリページは、統一されたpage構造で表されます。これは、ページを匿名としてマークするか(使用可能な場合はスワップスペースにスワップされる可能性があります)、またはファイルシステム上のinodeに関連付けられ(ファイルシステムに書き戻され、再読み込みされる可能性があります)任意の数のメモリマップ、つまり、あるプロセスのアドレス空間に表示されます。現在メモリにロードされているすべてのページの合計がページキャッシュです。

ページはmmapインターフェイスの実装に使用され、通常の読み取りおよび書き込みシステムコールは他の方法でファイルシステムによって実装できますが、インターフェイスの大部分はページも使用する汎用機能を使用します。ファイルの読み取りが要求されると、ページを割り当て、ファイルシステムを呼び出してそれらを埋めるための汎用関数があります。ブロックデバイスベースのファイルシステムの場合、適切なアドレスを計算し、この充填をブロックデバイスドライバーに委任します。

ramdev(ramdisk)

Ramdevは通常のブロックデバイスです。これにより、その上に任意のファイルシステムを階層化できますが、ブロックデバイスインターフェイスによって制限されます。そして、それは呼び出し元によって割り当てられたページを埋めて書き戻すためのメソッドを持っています。これは、ディスク、メモリカード、USB大容量ストレージなどの実際のブロックデバイスに必要なものです。しかし、ramdiskの場合、データはメモリに2回存在します。ramdevのメモリに1回と、発信者。

これは、initrdを実装する古い方法です。 initrdがまれでエキゾチックな出来事だった時代から。

tmpfs

Tmpfsは異なります。これはダミーのファイルシステムです。 VFSに提供するメソッドは、VFSを機能させるための最小限の最低限のものです(そのため、inode、dentry、およびfileメソッドが何をすべきかについての優れたドキュメントです)。ファイルは、対応するinodeとdentryがinodeキャッシュに存在する場合にのみ存在し、ファイルの作成時に作成され、ファイルが削除されない限り期限切れになりません。ページは、データが書き込まれるときにファイルに関連付けられ、それ以外の場合は匿名のものとして動作します(データはスワップに保存される場合があり、page構造はファイルが存在する限り使用されます)。

これは、メモリ内にデータの余分なコピーがないことを意味し、全体がずっと単純であり、そのためわずかに高速です。プライマリストレージであるため、他のファイルシステムのキャッシュとして機能するデータ構造を使用します。

これは、initrdinitramfsを実装する新しい方法ですが、画像はまだinitrdと呼ばれます)。

また、「posix共有メモリ」を実装する方法でもあります(これは単にtmpfsが/dev/shmおよびアプリケーションは、そこにファイルを作成してそれらをmmapできます。シンプルで効率的)、最近では/tmpおよび/run(または/var/run)多くの場合、特にノートブックにtmpfsをマウントして、SSDの場合にディスクがスピンアップしたり、摩耗を回避したりしないようにします。

44
Jan Hudec

あなたはすべて正しいと思います。

違いは、ブート時に必要な手順に従うかどうかを簡単に確認できます。

initrd

  • ramdevブロックデバイスが作成されます。これはRAMベースのブロックデバイスであり、物理ディスクの代わりにメモリを使用するシミュレートされたハードディスクです。
  • initrdファイルが読み取られ、デバイスに解凍されます。まるでzcat initrd | dd of=/dev/ram0または同様のもの。
  • initrdにはファイルシステムのイメージが含まれているため、通常どおりファイルシステムをマウントできます:mount /dev/ram0 /root。当然、ファイルシステムにはドライバーが必要なので、ext2を使用する場合は、ext2ドライバーをカーネル内でコンパイルする必要があります。
  • できた!

initramfs

  • tmpfsがマウントされます:mount -t tmpfs nodev /root。 tmpfsはドライバーを必要とせず、常にカーネル上にあります。デバイスや追加のドライバーは必要ありません。
  • initramfsは、この新しいファイルシステムに直接圧縮解除されます:zcat initramfs | cpio -i、 または類似。
  • できた!

はい、それは多くの場所でinitrdと呼ばれていますが、特にブートローダーではinitramfsですが、BLOBであるためです。違いは、OSの起動時に行われます。

57
rodrigo

上記の優れた回答で言及されていないinitrdinitramfsの別の注目すべき違いを追加します。

  • initrdを使用すると、カーネルはデフォルトでpid 1のユーザースペース/sbin/initに引き渡します
  • ただし、新しいinitramfsは状況を変更し、pid 1/initを実行します

落とし穴になる可能性があるため( https://unix.stackexchange.com/a/147688/24394 を参照)

1

最小限の実行可能なQEMUの例と初心者向けの説明

この答えでは、私は:

  • 最小限の実行可能なBuildroot + QEMUの例を提供して、テストします
  • これをググる可能性が非常に高い初心者向けに、両者の最も基本的な違いを説明

うまくいけば、これらが内部の詳細な違いの詳細を検証し理解するための基礎として役立つことを願っています。

最小限のセットアップは ここで完全に自動化 であり、これは 対応する入門 です。

セットアップは、実行時にQEMUコマンドを出力します。そのレポで説明されているように、次の3つの作業タイプのブートを簡単に作成できます。

  1. ルートファイルシステムはext2の「ハードディスク」にあります:

    qemu-system-x86_64 -kernel normal/bzImage -drive file=rootfs.ext2
    
  2. ルートファイルシステムはinitrdにあります:

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

    -driveが指定されていません。

    rootfs.cpioにはrootfs.ext2と同じファイルが含まれますが、 [〜#〜] cpio [〜#〜] 形式であり、.tarに似ています。 :圧縮せずにディレクトリをシリアル化します。

  3. ルートファイルシステムはinitramfsにあります:

    qemu-system-x86_64 -kernel with_initramfs/bzImage
    

    -drive-initrdも指定されていません。

    with_initramfs/bzImageは、1つを除いてnormal/bzImageと同じオプションでコンパイルされたカーネルです。CONFIG_INITRAMFS_SOURCE=rootfs.cpioは、-initrdの例とまったく同じCPIOを指します。

セットアップを比較することにより、それぞれの最も基本的なプロパティを結論付けることができます。

  1. ハードディスクのセットアップでは、QEMUはbzImageをメモリにロードします。

    この作業は通常、ブートローダーによって実行されます/ファームウェアは実際のハードウェアで実行します GRUB など。

    Linuxカーネルが起動し、ドライバーを使用してディスクからルートファイルシステムを読み取ります。

  2. initrdセットアップでは、QEMUはカーネルをメモリにロードする以外に、さらにブートローダーを実行します。

    今回は、ハードディスクが存在しないため、カーネルはメモリからrootfs.cpioを直接使用します。

    すべてがメモリ内にあるため、書き込みは再起動後も持続しません

  3. initramfsのセットアップでは、カーネルのビルド方法が少し異なります。カーネルビルドシステムにrootfs.cpioを指定します。

    カーネルビルドシステムは、カーネルイメージとCPIOを1つのイメージにまとめる方法を認識します。

    したがって、bzImageをQEMUに渡すだけです。 QEMUは、他のセットアップの場合と同様に、イメージにロードしますが、他に何も必要ありません。CPIOはカーネルイメージに接着されているため、メモリにもロードされます。