Linuxはどのように「initrd」イメージをロードしますか?


13

起動プロセスを理解しようとしてきましたが、頭に浮かぶことが1つだけあります。

Linuxカーネルがブートされ、ルートファイルシステム(/)がマウントされるとすぐに、プログラムを実行し、追加の機能を提供するためにカーネルモジュールを統合できます。ルートファイルシステムをマウントするには、特定の条件を満たす必要があります。カーネルは、ルートファイルシステムが配置されているデバイス(特にSCSIドライバー)にアクセスするために、対応するドライバーを必要とします。カーネルには、ファイルシステムの読み取りに必要なコード(ext2、reiserfs、romfsなど)も含まれている必要があります。ルートファイルシステムがすでに暗号化されていることも考えられます。この場合、ファイルシステムをマウントするにはパスワードが必要です。

初期RAMディスク(initdiskまたはinitrdとも呼ばれる)は、上記の問題を正確に解決します。Linuxカーネルは、実際のルートファイルシステムがマウントされる前に、RAMディスクに小さなファイルシステムをロードし、そこでプログラムを実行するオプションを提供します。initrdのロードは、ブートローダー(GRUB、LILOなど)によって処理されます。ブートローダーに必要なのは、ブートメディアからデータをロードするBIOSルーチンだけです。ブートローダーがカーネルをロードできる場合、初期ramdiskもロードできます。特別なドライバーは必要ありません。

/ bootが別のパーティションではなく、/パーティションに存在する場合、「initrd」イメージとカーネルイメージにアクセスするために、ブートローダーがSCSIドライバーを必要とするべきではないでしょうか?イメージに直接アクセスできる場合、なぜSCSIドライバーが必要なのですか?

回答:


20

Nighpher、私はあなたの質問に答えようとしますが、ブートプロセスのより包括的な説明については、IBMの記事を試してください

OK、説明のためにブートローダーとしてGRUBまたはGRUB2を使用していると思います。まず、BIOSがディスクにアクセスしてブートローダーをロードするとき、有名な13h割り込みに保存されているディスクアクセス用の組み込みルーチンを使用します。ブートローダー(およびセットアップフェーズのカーネル)は、ディスクにアクセスするときにこれらのルーチンを使用します。BIOSはプロセッサのリアルモード(16ビット)モードで実行されることに注意してください。したがって、リアルモードの各アドレスはsegment_address * 16 +オフセットで構成されるため、2 ^ 20バイト以上のRAM(2 ^ 16ではなく2 ^ 20バイト)をアドレスできません。 、セグメントアドレスとオフセットの両方が16ビットである場合、http://en.wikipedia.org/wiki/X86_memory_segmentationを参照してください。したがって、これらのルーチンは1 MiBを超えるRAMにアクセスできません。これは厳密な制限であり、大きな不便です。

BIOSは、MBR(ディスクの最初の512バイト)からブートローダーコードを直接読み込み、実行します。GRUBを使用している場合、そのコードはGRUBステージ1です。このコードはGRUBステージ1.5をロードします。GRUBステージ1.5は、DOS互換領域と呼ばれるディスクスペースの最初の32 KiBにあるか、ファイルシステムの固定アドレスから読み込まれます。これを行うためにファイルシステムを理解する必要はありません。原因は、ステージ1.5がファイルシステムにあり、「生の」コードであり、RAMに直接ロードして実行できるためです:http : //www.pixelbeat.org/ docs / disk /。ディスクからRAMへのstage1.5のロードでは、BIOSディスクアクセスルーチンが使用されます。

ここに画像の説明を入力してください

Stage1.5にはファイルシステムユーティリティが含まれているため、ファイルシステムからstage2を読み取ることができます(それでもBIOS 13hを使用してディスクからRAMに読み取りますが、iノードなどに関するファイルシステム情報を解読し、生のコードを取得できます)ディスク)。古いBIOSは、ディスクアドレッシングモードの制限により、HD全体にアクセスできない場合があります-シリンダーヘッドセクターシステムを使用し、最初の8 GiBを超えるディスクスペースをアドレス指定できない場合があります:http://en.wikipedia。 ORG /ウィキ/シリンダー・ヘッド・セクター

Stage2 はカーネルをRAMにロードします(これもBIOSディスクユーティリティを使用)。2.6+カーネルの場合は、initramfsもコンパイルされているため、ロードする必要はありません。古いカーネルの場合、ブートローダーはスタンドアロンinitrdイメージもメモリにロードするため、カーネルはそれをマウントし、ディスクから実際のファイルシステムをマウントするためのドライバーを取得できます。

問題は、カーネル(およびRAMディスク)の重量が1 MiBを超えているため、RAMに読み込むには、カーネルを最初の1 MiBに読み込んでから保護モード(32ビット)にジャンプし、読み込んだカーネルをハイメモリに移動する(無料)リアルモードの最初の1 MiB)、次にリアル(16ビット)モードに戻り、ディスクから最初の1 MiB(別のinitrdと古いカーネルの場合)にramdiskを取得し、おそらく保護(32ビット)モードに切り替えます。所属する場所に置き、可能であればリアルモードに戻り(または/programming/4821911/does-grub-switch-to-protected-mode)、カーネルコードを実行します。警告:説明のこの部分の完全性と正確性については完全にはわかりません。

さて、最終的にカーネルを実行すると、すでにブートローダーによってRAMにRAMディスクがロードされているので、カーネルはramdiskのディスクユーティリティを使用して実際のルートファイルシステムをマウントし、ルートをピボットできます。カーネルにramfsドライバーが存在するため、もちろんinitramfsの内容を理解できます。


ブートラダーは、プロテクトモードにジャンプする代わりに、カーネルをチャンクでロードすることはできませんか?そして、その1 MBを解放する必要があります。(ごめん..それを理解できませんでした..)
rpthms

最初の1MiBを解放する必要性は次のとおりです:ブートローダーはリアルモードでのみハードドライブにアクセスできるため、リアルモードのBIOSユーティリティでアクセスできます(16ビット引数で動作し、16ビット操作を使用します)。リアルモードでは、最初の1 MiBを除いてRAMが表示されません。ただし、kernel + initramfsをRAMにロードする必要があり、RAMに約5 MiBのスペースが必要です。これらのBIOSユーティリティでは、5 MiBを最初の1 MiBに絞り込めません。したがって、ブートローダーはそれらをディスクから最初の1 MiBにコピーしてから、保護モードに移行し、最初の1Mb RAMからより高いRAMに移動する必要があります。今より明確ですか?:)
ボリスブルコフ

1
ステージ1 / 1.5 / 2全体は、grubレガシーです。
psusi

1
@CMCDragonkaiはい、stage2ブートローダーはファイルシステム(つまり、/bootパーティション)にあります。カーネルはこの時点ではロードされていません-それはgrubのstage1.5であり、そのミニマルなファイルシステムドライバーを介してファイル/bootシステム(たとえば/boot/grubファイル)のstage2にアクセスしています。カーネルも/bootパーティションから読み取ることができますが、grub2コードの実行とカーネルのロード後、およびカーネルがinitramfsを読み取った後、後で発生します。あなたはといえばしているinit.shのinitramfsの?/bootハードドライブのパーティションに存在し、grubのstage2がそれをRAMに入れ、カーネルがRAMから読み取ります。
ボリスブルコフ

1
Initrd 別のファイルである必要がありました。新しいinitramfsには、可能なカーネルにリンクされているが、それはしないでなければならない -それはまた、ブートローダによって別のファイルとしてロードすることができます。initramfsファイルはcpioアーカイブのシーケンスとして定義されているため、一部のブートローダー(iPXEなど)では複数の initramfsファイルを許可することもあり、これらは次々にメモリにロードされます。また、一部のLinuxディストリビューションは、下位互換性のためにinitrdスタイルのファイル名を使用していますが、実際に使用されている技術は現在initramfsです。
telcoM

1

私は、特定のブートローダーがサポートする機能に要約されると信じています。例えば。結合(ブート+ルート)パーティションの特定のファイルシステムを知る必要はありません。その場合は、ブートローダーで動作する状態で別のブートパーティションを作成するだけで、ルートパーティションをマウントする方法の他の複雑さはカーネルとブートパーティションからブートされるinitrdイメージに残ります。ブートローダーは、独自のドライバーを使用するか、BIOSルーチンを使用することにより、SCSIデバイス(および使用するブートローダーに応じて他のデバイスも)にアクセスする方法を知っています。さらに、いくつかのファイルシステムなどの読み方を知っています。

例えば検討してください。UEFIの起動方法。実際にはUEFIファームウェアはすでにEFIパーティションにアクセスする方法を知っており、それを読み取って、そこからLinuxカーネルをロードします。中間ブートローダーは必要ありません。その場合、Linuxイメージはルートパーティションから分離された状態で存続し、UEFIファームウェアはそれにアクセスするためにすべてのエキゾチックなファイルシステムを知る必要はありません。「ブート」イメージを「ルート」パーティションから分離することは理にかなっていると思います。それ以外の場合は、ルートファイルシステムの暗号化を設定するときにこれが必要です。


0

記録のために、ブートローダーがinitrdをロードしない場合、別のブートローダーをテストする価値があります。LILOが適切に指定された中サイズ(<4Mb; SATA SSD上の単一ext4 rootfs; GPT)のinitrdを静かに無視し、GRUB 2.00が成功したときに、このような状況に陥りました。

ブートプロセスはすぐに終了し、典型的な

RAMDISK: Couldn't find valid RAM disk image starting at 0.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,3)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.