
Linux ソースには、次の場所に 2 つの異なる head.S ファイルがあります。
それぞれの目的は何ですか、また実行順序は何ですか?
答え1
よりよい回答を歓迎しますが、私の理解では、これはアセンブリで手書きされたカーネル起動コード (アーキテクチャ固有) です (この時点では、ベアメタル CPU とメモリへの生のアクセスしかありません。ファイル マネージャがまだないため、ファイル システムに保存されている複雑なライブラリにアクセスすることはできません。これは、ビッグバンを誰が作ったのかを尋ねるようなものです)。これをブート ローダー (ディスクから RAM にブート セクターをロードする) と混同しないでください。私自身、以前の回答でこれらを混同していました。
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
' bootloader ' ' kernel '
' ' ' '
+------+ ' +-----------------------------------+ +------------------------------+ ' ' +-----------------------------+ +---------------------------------------+ '
| BIOS | --> ' | arch/x86/boot/header.S::call main | --> | arch/x86/boot/main.c::main() | ' --> ' | init/main.c::start_kernel() | --> | arch/x86/kernel/setup.c::setup_arch() | '
+------+ ' +-----------------------------------+ +------------------------------+ ' ' +-----------------------------+ +---------------------------------------+ '
' ' ' '
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
(編集: これは Minix です。最初に間違って入力しました)
+------+ +--------------------+ +------------------+ +------------------------+
| BIOS | --> | Bootloader (mbr.S) | --> | startup (head.S) | --> | kernel/main.c::kmain() |
+------+ +--------------------+ +------------------+ +------------------------+
head.Sの最後に次の行が表示されます
call _C_LABEL(kmain)
これはカーネルへのエントリポイントです:
kernel/main.c
コンパイル時にカーネル イメージの先頭に追加されるものだと思いますhead.S
。このコード ブロックは先頭にあり、RAM ディスクのルート ファイル システムであるため、BIOS はこのコード ブロックを実行することを認識しています。
圧縮部分と非圧縮部分が存在する理由については、カーネル イメージのアーキテクチャ固有のアセンブリ部分で、圧縮を行えるほど熟練したプログラマーがいないからだと思います。Ckmain
で記述されたルーチン (ただしアセンブリにコンパイルされている) にジャンプすると、カーネルのフットプリントを大幅に小さくする解凍ルーチンにアクセスできます。
http://duartes.org/gustavo/blog/post/カーネルブートプロセス/
アセンブリを使用したエントリポイント
私たちはすべてを C で記述することを好みますが、アセンブリを少しだけ使用することは避けられません。カーネルの開始点となる小さなファイルを x86 アセンブリ言語で記述します。アセンブリ ファイルで実行するのは、C で記述した外部関数を呼び出して、プログラム フローを停止することだけです。
このアセンブリ コードがカーネルの開始点として機能することをどのように確認するのでしょうか?
オブジェクト ファイルをリンクして最終的なカーネル実行ファイルを生成するリンカー スクリプトを使用します (詳細は後述)。このリンカー スクリプトでは、バイナリをアドレス 0x100000 にロードすることを明示的に指定します。前に述べたように、このアドレスはカーネルが存在すると予想される場所です。したがって、ブートローダはカーネルのエントリ ポイントを起動します。
http://arjunsreedharan.org/post/82710718100/kernel-101-lets-write-a-kernel