web-dev-qa-db-ja.com

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

私は起動プロセスを理解しようと努めてきましたが、頭の中で起こっていることが1つだけあります。

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

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

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

14
rpthms

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

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

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

enter image description here

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

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

問題は、カーネル(およびramdisk)の重量が1 MiBを超えるため、それらをRAMにロードするには、カーネルを最初の1 MiBにロードしてから、保護モード(32ビット)にジャンプする必要があります)、ロードされたカーネルをハイメモリに移動し(リアルモードの最初の1 MiBを解放)、再びリアル(16ビット)モードに戻り、ディスクから最初の1 MiBにRAMディスクを取得します(個別のinitrdおよび古いカーネルの場合)。プロテクト(32ビット)モードに戻し、それを所属する場所に置き、おそらくリアルモードに戻します(またはそうではありません: https://stackoverflow.com/questions/4821911/does-grub-switch-to- protected-mode )を実行し、カーネルコードを実行します警告:この部分の説明の完全性と正確性については、完全にはわかりません。

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

21
Boris Burkov

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

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

1

参考までに、ブートローダーがinitrdをしないロードする場合、別のブートローダーをテストする価値があります。私はちょうど this のような状況に遭遇しました。LILOは適切に指定された中サイズのinitrdを黙って無視しました(<4Mb; SATA SSD上の単一のext4 rootfs; GPT)および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)
0