私はLinuxカーネルが起動時に必要なrootfsの場所をどのように知っているかを理解しようとしています。
私はこの記事を読んだ。
https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
興味のある内容は次のとおりです。
すべての2.6 Linuxカーネルには、カーネルの起動時にrootfsで抽出されるgzipで圧縮された「cpio」形式のアーカイブが含まれています。組み込みのcpioアーカイブが抽出された後、rootfsにinitプログラムが含まれていないと、カーネルは失敗します。古いコードルートパーティションを見つけてマウントするには
私たちのカーネルは4.Xですが、これはまだ適用されていると思いますか?すべてのカーネルに「cpio」rootfsが組み込まれているようです。
実際に私たちが読んだように:
2.6カーネルビルドプロセスは、常にgzipで圧縮されたcpio形式のinitramfsアーカイブを作成し、生成されたカーネルバイナリにリンクします。デフォルトでは、このアーカイブは空です...設定オプションCONFIG_INITRAMFS_SOURCE...を使用してinitramfsアーカイブのソースを指定できます。
これにより、いくつかの質問がさらに提起されます。
CONFIG_INITRAMFS_SOURCE
したがって、私のrootfsをRAMに入れるには、私のrootfs(おそらくcpio形式)を指すように設定する必要があります。
しかし、これは私のカーネルとrootfsがもう分離できないという意味ですか?再構築せずにRootFSを少し調整するにはどうすればよいですか? rootfsをカーネルとは別に保存するにはどうすればよいですか?私のrootfsの場所をカーネルにどのように伝えますか?
- また、私のrootfsをRAMの代わりに物理ストレージ(例えばeMMC、フラッシュドライブなど)に置くにはどうすればよいですか?
前述の内容は次のとおりです。
組み込みのcpioアーカイブをrootfsに抽出した後、rootfsにinitプログラムがない場合、カーネルは以前のコードを使用してルートパーティションを見つけてマウントします。
しかし…どうですか? rootfsがどこにあるのか、どうすればわかりますか? eMMCにいる場合は、どういうわけかカーネルに教えてください。
私が使用するブートローダはU-bootです。 U-boot環境変数を調べて、どういうわけかrootfsの場所をカーネルにブート引数として渡していることを確認しましたが、そうではありません...
編集する:
コメントで指摘したように、rootfsの位置はboot argを介してカーネルに渡されます。私の場合、u-bootはroot=/dev/mmcblk0p4 rw
ブート引数としてカーネルに渡されます。これは私の質問の1つに対する答えです。解凍された rootfs にブート引数として位置を渡すことができます。
rootfs.tar.gz
カーネルとは別のものを考えると、カーネルにそれをRAMに解凍し、rootfsとして使用するように指示する方法はまだ明確ではありません。たぶんこれは不可能かもしれませんが、単に使用する必要がありますかCONFIG_INITRAMFS_SOURCE
?とにかく4.Xのドキュメントを読んでみましょう。
答え1
まず、カーネル文書の「2.6」参照に恐れないでください。現在、カーネルはまだ「2.6」シリーズのメンバーですが、「マーケティング目的」のために2回にわたって番号を付け直しました(したがって、2.6.40は3.0になり、3.20は4.0になりました)。 4.19カーネルには通常2.6.79というラベルが付いています。
ここで「rootfs」の意味について若干の混乱があるようです。 「rootfs」は、カーネルで内部的に使用される特別なRAMベースのファイルシステムです。これは通常、にマウントされている「tmpfs」ファイルシステムとまったく同じです/run
。 (まあ、「tmpfs」機能がカーネルにコンパイルされていない限り、この場合は「ramfs」と呼ばれる単純な「tmpfs」が使用されます。)これらのファイルシステムはページキャッシュにのみ存在し、デバイスramfsをサポートしません。 tmpfsはスワップ(利用可能な場合)としてサポートされています。/dev/shm
/tmp
したがって、カーネルは「rootfs」を「見つける」ことを心配する必要はありませんが、起動時にページ全体のキャッシュが空であるため、何らかの方法でそれを埋める必要があります。これが「initramfsファイル」が動作する場所です。これはカーネルによって空の「rootfs」に解凍されたcpio
(tar
文書に記載されている理由のためではなく)(圧縮された)アーカイブだけです。このアーカイブは、CONFIG_INITRAMFS_SOURCE
ビルド中の設定を介してカーネルイメージに直接含めることも、ブートローダで提供することもできます(initrd
GRUBのオプションが実行するアクション)。アーカイブは通常、dracut
(混乱しても)などのユーザースペースツールを使用して作成されますmkinitrd
。
cpioイメージが利用できない場合、または実行可能ファイルが含まれていない場合、/init
カーネルはコマンドライン引数を見て、root=
それを実際のルートファイルシステムの場所として解釈し、マウントして/
直接実行する別の方法に置き換えますinit
。しかし、このアプローチは、必要なすべてのリポジトリとファイルシステムドライバをカーネルに直接コンパイルする必要があるため、今日ではほとんど使用されていません。ほとんどのシステムでは、このroot=
パラメータはカーネルでは使用されず、/init
initramfsで処理されます。これは/init
(通常はsystemd
シェルスクリプト)必須モジュールのロード、実際のルートファイルシステムのマウント、および移行を担当します。
長い間、「initrd」という別のメカニズムが現代の「initramfs」を置き換えるために使用されていました。 「initrd」(「init ramdisk」)は、実際のファイルシステム(ext2など)で初期化され、そのイメージが最新のアーカイブのように提供されるRAMベースのブロックデバイスですcpio
。これが、多くの場所でこれらの初期起動項目を指すためにまだ「initrd」という名前を使用する理由です。
答え2
したがって、私のrootfsをRAMに保存するには、CONFIG_INITRAMFS_SOURCEが私のrootfs(おそらくcpio形式)を指すように設定する必要があります。
それは一ついくつかの方法があります。はい、しかしこれはありません。ただ方法。
CONFIG_INITRAMFS_SOURCE
カーネルとinitramfsを別々のファイルにロードするように設定できるブートローダがある場合、カーネルをビルドするときは必要ありません。CONFIG_BLK_DEV_INITRD
カーネル構成で設定すれば十分です。 (initramfs以前は、initramfsという以前のバージョンの技術があり、initrd
以前の名前はまだいくつかの場所に表示されます。)ブートローダはinitramfsファイルをロードし、メモリの場所とサイズに関するいくつかの情報でデータ構造を埋めます。ロードされたカーネルイメージの位置。カーネルには、この情報を使用してシステムRAMでinitramfsを見つけて解凍する組み込みルーチンがあります。
initramfsを別々のファイルとして使用すると、initramfsファイルをより簡単に変更でき、ブートローダーがユーザーの入力を受け入れることができる場合は、起動時にロードされる通常のファイルの代わりにロードする別のinitramfsファイルを指定できます。 (これはカスタムinitramfsを生成しようとし、間違いをする場合は非常に便利です。そこに行きました。)
既存の BIOS ベースの x86 システムでは、以下にこれらの詳細を見つけることができます。(カーネルソースコード)/Documentation/x86/boot.txt。 UEFIベースのシステムはこれを少し異なる方法で実行しますが(同じ文書にも記載されています)、他のアーキテクチャ(ARMなど)には、ブートローダからカーネルに情報を渡す方法に関する一意の詳細セットがあります。
また、私のrootfsをRAMの代わりに物理ストレージ(例えばeMMC、フラッシュドライブなど)に置くにはどうすればよいですか?
一般的な非埋め込みシステムでは、initramfsには通常、基本サブシステムを有効にするのに十分な機能しか含まれていません。通常のPCでは、これらのドライバは通常、LVM、ディスク暗号化、および/またはソフトウェアRAIDなどのサブシステムを有効にするために必要なカーネルモジュールおよびツールであり、キーボード、モニタ、およびルートファイルシステムストレージコントローラ用のドライバです。これらの機能を使用してください。
デフォルトのサブシステムがアクティブでルートファイルシステムにアクセスできるようになると、通常、initramfsはpivot_root(8)
initramfsから実際のルートファイルシステムに切り替えます。しかし、組み込みシステムや次のような特別なユーティリティはデータベース管理ネットワーク、必要なものすべてをinitramfsに入れることができますが、決してそうしないでくださいpivot_root
。
通常、initramfsのスクリプトおよび/またはツールは、カーネルコマンドラインのオプションから実際のルートファイルシステムを見つけるために必要な情報を取得します。しかし、あなたはそうではありません持つこれを行うには:カスタムinitramfsを使用すると、起動シーケンス中に特定のキーまたはマウスボタンを押すと、別のルートファイルシステムに切り替えることができます。
複雑なストレージ構成(たとえば、冗長マルチパスSANストレージを使用するシステムのソフトウェアRAIDの上に暗号化されたLVM)の場合、ルートファイルシステムを有効にするために必要なすべての情報がカーネルコマンドラインに収まらない可能性があるため、より多くの情報を含めるできます。部分は initramfs に配置されます。
最新のディストリビューションは通常、次のものを使用します。initramfsジェネレータインストールされたカーネルごとにカスタムinitramfsをビルドします。独自のinitramfsジェネレータを使用するさまざまなディストリビューション:RedHatは1つを使用し、mkinitrd
Debianはそれを使用しましたupdate-initramfs
。しかしsystemd
導入された後には多くのディストリビューションが標準化されているようです。dracut
initramfsジェネレータとして。
最新の initramfs ファイルは複数のアーカイブをリンクでき、.cpio
各アーカイブの各部分は圧縮または圧縮されない場合があります。最新のx86_64システムの一般的なinitramfsファイルは、最初のコンポーネントとして「初期マイクロコードアップデート」ファイルを持つことができます(通常、マイクロコードファイルは暗号化されて圧縮性が低下するため、圧縮されていないcpioアーカイブの単一ファイルです。には、通常のinitramfsコンテンツ(圧縮.cpio
ファイル)
システムをより深く理解するには、initramfsファイルを一時ディレクトリに抽出してその内容を確認することをお勧めします。 Debianには、unmkinitramfs(8)
initramfsファイルを簡単に抽出するために使用できるツールがあります。 RedHat 7では、Skip Microcodeを使用して/usr/lib/dracut/skipcpio <initramfs file>
ファイルを更新し、結果の出力をパイプし、initramfsコンテンツを現在の作業ディレクトリに引き続きgzcat
抽出できます。cpio -i -d
Ubuntulzcat
はgzcat
。