banner
EthanYang

Sail's Blog

github

Linuxシステムの起動時には、

之前 Linux の起動プロセスの概要を見ました:

image

もっと具体的な詳細を知りたかったので、いくつかの情報を検索してまとめました。

一、CPU リセット#

電源ボタンを押すと、デバイスに電力が供給され始めますが、最初の電力供給は安定していません。メインボードはこれを検出すると、CPU にリセット信号を継続的に送信し、この時点で CPU はレジスタの残留データをクリアし、レジスタの設定を行います:

image

ここで最も重要なレジスタはCS と EIPです。CS の暗黙のベースは RIP と加算され、つまりffff0000H+fff0H=fffffff0Hffff 0000H + fff0H = ffff fff0 Hとなり、このアドレス(リセットベクトルとも呼ばれる)にはジャンプ命令が格納されています。ジャンプ先のアドレスはBIOS のエントリポイントアドレスです。

なぜリセットベクトルを直接 BIOS のエントリポイントアドレスに設定せずにジャンプするのですか?
X86 チップは最初にリアルモードで実行されますが、リアルモードでは 20 ビットのアドレッシングスペース(1M)しかありません。リセットベクトルは fff0H であり、ffffH までの距離は非常に短いため、BIOS プログラムを格納するのに十分なスペースがありません。そのため、ジャンプする必要があります。
リセットベクトルをアドレススペースの高いアドレスに配置する理由は、より大きなメモリスペースを確保するためです。

リアルモード下のメモリレイアウト

image

マルチコアシステムでの CPU リセット#

マルチコアコンピュータでは、最初にプロトコルを実行するために、システムは 1 つの CPU を選択し、他の CPU は待機状態になります。選択されたメイン CPU はブートストラッピング CPU(BSP)と呼ばれ、BSP だけが続行し、他の CPU は BSP からの命令を待ちます。

二、BIOS の実行#

BIOS は EPROM に固定されたプログラムであり、通常はハードウェアメーカーによって固定されており、システムの起動を担当しています。

POST 電源自己テスト#

BIOS が最初に実行するプログラムは POST です。これはコンピュータが電源を入れた直後にハードウェアの一部をテストするために使用されます。自己テスト中に重大なエラーが見つからない場合、システムはテストコードに基づいてメッセージを表示するかブザーで警告を発することがあります。

なぜブザーを使って警告を発するのですか?
以前はオンボードグラフィックスがなかったため、グラフィックカードは必ず外部デバイスでした。POST が実行されるとき、グラフィックカードはまだ初期化が完了していないため、エラーメッセージを画面に表示することはできず、音で警告するしかありませんでした。

テストは 1 つずつ実行され、BIOS メーカーは各デバイスに対して 1 つのPOST CODEを提供しています。デバイスをテストするときに、この POST CODE が診断ポートにロードされ、テストに合格しない場合はこの CODE が保持され、警告が発生します。

デバイスの初期化#

POST が終了すると、BIOS は各外部デバイスの BIOS を呼び出して自己テストと初期化を行います。たとえば、グラフィックカードの BIOS など、すべてのデバイスはこの時点で初期化されて起動します。
デバイスの初期化以外にも、BIOS はこの時点で割り込みベクタテーブルを初期化します。

ブートローダの起動#

各種デバイスの検出と初期化が完了した後、BIOS はユーザー定義のブート順序を検索します。デフォルトではディスクですが、光学ディスクや USB メモリ(以前はオペレーティングシステムを再インストールするときに使用されました)などに変更することもできます:

image

順序に従って、BIOS は最初に来るデバイスのMBR(メインブートレコード)、つまり 0 トラックの最初のセクタの 512 バイトをRAM の絶対アドレス 0x7C00に読み込み、そのアドレスにジャンプします。

MBR フォーマット
MBR はどのオペレーティングシステムにも属していないため、その 512 バイトの内容は次のようになります:

  • ブートコード(446 バイト):パーティションテーブルの正確性をチェックし、ハードディスク上のブートローダプログラム(例:grub)にシステム制御を転送します。
  • ディスクパーティションテーブル(16 X 4 バイト):DPT は、4 つのパーティションテーブルで構成され、各パーティションテーブルは 16 バイトで、ディスクのパーティション状況を説明します。
  • 終了マーカー(2 バイト)

UEFI
現在の BIOS については、通常 UEFI を指します。従来の BIOS でも UEFI でも、ROM→RAM→BOOT のプロセスを経ていますが、主要な部分には違いがありません。では、なぜ UEFI が必要なのでしょうか?
この回答を参照してください:UEFI 引导与 BIOS 引导在原理上有什么区别?

三、ブートローダ#

ブートローダプログラムは、オペレーティングシステムのカーネルファイルをメモリにロードするためのものであり、このタイプのプログラムの主な機能は次のとおりです:

  1. リアルモードからプロテクトモードへの移行、16 ビットアドレッシングスペースから 32 ビットアドレッシングスペースへの移行、セグメントメカニズムの有効化。
  2. ハードディスクから ELF 形式のカーネル(MBR の後に続くセクタ)を読み込んで固定のメモリ位置に配置します。このプロセスは通常 2 つのステップで行われ、最終的には boot 命令が実行され、システムのブートメニュー(/boot/grub/menu.lstまたは grub.lst)、カーネル vmlinuz、および RAM ディスク initrd がロードされます。
    ここでは GNU のgrubを例に挙げます。grub は、異なるカーネルを持つオペレーティングシステムのパーティションを選択するために使用できます。また、これらのカーネルに起動パラメータを渡すこともできます。grub のロードは通常 2 つのステップで行われます:
  3. 基本ブートプログラム - stage1 をロードします。その主な機能は、第 2 ブートプログラムである stage2 をロードすることです。
  4. 第 2 ブートプログラム - stage2 をロードします。この第 2 ブートローダプログラムは、より高度な機能を提供するために使用され、ユーザーに特定のオペレーティングシステムをロードすることを許可します。grub では、このステップではユーザーに表示メニューを表示するか、ユーザーにコマンドを入力することができます。このステージのブートの最終的な状態は、boot コマンドを実行してオペレーティングシステムカーネルをメモリにロードし、制御をカーネルに渡すことです。
    カーネルのロードが完了すると、メモリは次のようにマップされます:

image

四、Linux カーネルの設定と起動#

Linux カーネルが起動すると、一連のチェックが実行され、チェックが完了すると start_kernel 関数にジャンプし、この関数は各モジュールを順番に初期化します。たとえば、ページテーブル、割り込みベクタなどです。その後、0 番プロセスになります。

0 番プロセスは 1 番の kernel_init プロセスを fork し、kernel_init は init プログラムを実行します。大まかなプロセスは次のようになります:

init プログラム

  1. init プロセスは/etc/inittabファイルを読み取り、Linux のランレベルを設定し、プロセスの実行モードを決定します。
  2. Linux は最初のユーザーレベルファイル/etc/rc.d/rc.sysinitを実行します。このファイルの機能には、PATH 実行変数の設定、ネットワーク設定、スワップパーティションの起動、/proc の設定、システム関数などが含まれます。
  3. /etc/modules.confおよび/etc/modules.dディレクトリのファイルを読み取り、システムカーネルモジュールをロードします。
  4. いくつかのサービスを起動し、その後/etc/rc.d/rc.localファイルを実行します。
  5. 最後に /bin/login プログラムを実行し、ログイン画面に移行し、ユーザーにユーザー名とパスワードを入力させます。

ユーザーの起動が完了すると、0 番プロセスは cpu_idle に入り、idle プロセスになります。これで Linux の起動はほぼ完了です。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。