私の知る限り、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
はファイルを開いてメモリにロードするだけです。
initrd
とramfs
は両方ともコンパイル時に圧縮されますが、違いは、initrd
は、起動時にカーネルによってマウントされるようにアンパックされたブロックデバイスであり、ramfs
はcpioを介してメモリに展開されます。私は正しいですか?または、ramfs
は非常に最小限のファイルシステムですか?
最後に、今日まで、initrd
イメージはまだ最新のカーネルに表示されています。しかし、initrd
は実際に今日使用されているramfs
であり、名前は歴史的な目的のためだけのものですか?
Linuxのファイルシステムサブシステムには3つの層があります。システムを実装するVFS(仮想ファイルシステム)はインターフェースを呼び出し、クロスマウントポイントとデフォルトの許可および制限チェックを処理します。その下には、個々のファイルシステムのドライバーと、ブロックデバイス(ディスク、メモリーカードなど。ネットワークインターフェイスは例外です)のドライバーへのインターフェイスがあります。
VFSとファイルシステム間のインターフェースはいくつかのクラスです(プレーンCなので、関数などへのポインターを含む構造ですが、概念的にはオブジェクト指向のインターフェースです)。主な3つのクラスは、ファイルシステム内のオブジェクト(ファイルまたはディレクトリ)を記述するinode
、ディレクトリ内のエントリを記述するdentry
、およびファイルオープンを記述するfile
です。プロセスによって。マウントされると、ファイルシステムドライバーはそのルート用にinode
とdentry
を作成し、他のものはプロセスがファイルにアクセスして最終的に期限切れになるときにオンデマンドで作成されます。これはdentryとiノードのキャッシュです。
はい、すべての開いているファイルとルートまでのディレクトリごとに、それを表すカーネルメモリにinode
およびdentry
構造が割り当てられている必要があります。
Linuxでは、ユーザーランドデータを含む各メモリページは、統一されたpage
構造で表されます。これは、ページを匿名としてマークするか(使用可能な場合はスワップスペースにスワップされる可能性があります)、またはファイルシステム上のinode
に関連付けられ(ファイルシステムに書き戻され、再読み込みされる可能性があります)任意の数のメモリマップ、つまり、あるプロセスのアドレス空間に表示されます。現在メモリにロードされているすべてのページの合計がページキャッシュです。
ページはmmapインターフェイスの実装に使用され、通常の読み取りおよび書き込みシステムコールは他の方法でファイルシステムによって実装できますが、インターフェイスの大部分はページも使用する汎用機能を使用します。ファイルの読み取りが要求されると、ページを割り当て、ファイルシステムを呼び出してそれらを埋めるための汎用関数があります。ブロックデバイスベースのファイルシステムの場合、適切なアドレスを計算し、この充填をブロックデバイスドライバーに委任します。
Ramdevは通常のブロックデバイスです。これにより、その上に任意のファイルシステムを階層化できますが、ブロックデバイスインターフェイスによって制限されます。そして、それは呼び出し元によって割り当てられたページを埋めて書き戻すためのメソッドを持っています。これは、ディスク、メモリカード、USB大容量ストレージなどの実際のブロックデバイスに必要なものです。しかし、ramdiskの場合、データはメモリに2回存在します。ramdevのメモリに1回と、発信者。
これは、initrd
を実装する古い方法です。 initrdがまれでエキゾチックな出来事だった時代から。
Tmpfsは異なります。これはダミーのファイルシステムです。 VFSに提供するメソッドは、VFSを機能させるための最小限の最低限のものです(そのため、inode、dentry、およびfileメソッドが何をすべきかについての優れたドキュメントです)。ファイルは、対応するinodeとdentryがinodeキャッシュに存在する場合にのみ存在し、ファイルの作成時に作成され、ファイルが削除されない限り期限切れになりません。ページは、データが書き込まれるときにファイルに関連付けられ、それ以外の場合は匿名のものとして動作します(データはスワップに保存される場合があり、page
構造はファイルが存在する限り使用されます)。
これは、メモリ内にデータの余分なコピーがないことを意味し、全体がずっと単純であり、そのためわずかに高速です。プライマリストレージであるため、他のファイルシステムのキャッシュとして機能するデータ構造を使用します。
これは、initrd
(initramfs
を実装する新しい方法ですが、画像はまだinitrd
と呼ばれます)。
また、「posix共有メモリ」を実装する方法でもあります(これは単にtmpfsが/dev/shm
およびアプリケーションは、そこにファイルを作成してそれらをmmapできます。シンプルで効率的)、最近では/tmp
および/run
(または/var/run
)多くの場合、特にノートブックにtmpfsをマウントして、SSDの場合にディスクがスピンアップしたり、摩耗を回避したりしないようにします。
あなたはすべて正しいと思います。
違いは、ブート時に必要な手順に従うかどうかを簡単に確認できます。
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の起動時に行われます。
上記の優れた回答で言及されていないinitrd
とinitramfs
の別の注目すべき違いを追加します。
initrd
を使用すると、カーネルはデフォルトでpid 1
のユーザースペース/sbin/init
に引き渡しますpid 1
で/init
を実行します落とし穴になる可能性があるため( https://unix.stackexchange.com/a/147688/24394 を参照)
最小限の実行可能なQEMUの例と初心者向けの説明
この答えでは、私は:
うまくいけば、これらが内部の詳細な違いの詳細を検証し理解するための基礎として役立つことを願っています。
最小限のセットアップは ここで完全に自動化 であり、これは 対応する入門 です。
セットアップは、実行時にQEMUコマンドを出力します。そのレポで説明されているように、次の3つの作業タイプのブートを簡単に作成できます。
ルートファイルシステムはext2の「ハードディスク」にあります:
qemu-system-x86_64 -kernel normal/bzImage -drive file=rootfs.ext2
ルートファイルシステムはinitrdにあります:
qemu-system-x86_64 -kernel normal/bzImage -initrd rootfs.cpio
-drive
が指定されていません。
rootfs.cpio
にはrootfs.ext2
と同じファイルが含まれますが、 [〜#〜] cpio [〜#〜] 形式であり、.tar
に似ています。 :圧縮せずにディレクトリをシリアル化します。
ルートファイルシステムはinitramfsにあります:
qemu-system-x86_64 -kernel with_initramfs/bzImage
-drive
も-initrd
も指定されていません。
with_initramfs/bzImage
は、1つを除いてnormal/bzImage
と同じオプションでコンパイルされたカーネルです。CONFIG_INITRAMFS_SOURCE=rootfs.cpio
は、-initrd
の例とまったく同じCPIOを指します。
セットアップを比較することにより、それぞれの最も基本的なプロパティを結論付けることができます。
ハードディスクのセットアップでは、QEMUはbzImageをメモリにロードします。
この作業は通常、ブートローダーによって実行されます/ファームウェアは実際のハードウェアで実行します GRUB など。
Linuxカーネルが起動し、ドライバーを使用してディスクからルートファイルシステムを読み取ります。
initrdセットアップでは、QEMUはカーネルをメモリにロードする以外に、さらにブートローダーを実行します。
rootfs.cpio
をメモリにロードします今回は、ハードディスクが存在しないため、カーネルはメモリからrootfs.cpio
を直接使用します。
すべてがメモリ内にあるため、書き込みは再起動後も持続しません
initramfsのセットアップでは、カーネルのビルド方法が少し異なります。カーネルビルドシステムにrootfs.cpio
を指定します。
カーネルビルドシステムは、カーネルイメージとCPIOを1つのイメージにまとめる方法を認識します。
したがって、bzImageをQEMUに渡すだけです。 QEMUは、他のセットアップの場合と同様に、イメージにロードしますが、他に何も必要ありません。CPIOはカーネルイメージに接着されているため、メモリにもロードされます。