カーネルにはmain()関数がありますか?[閉まっている]


52

デバイスドライバーとカーネルプログラミングを学んでいます。Jonathan Corbetの本によるとmain()、デバイスドライバーには機能がありません。

だから私は2つの質問:

  • main()デバイスドライバーに関数が必要ないのはなぜですか?
  • カーネル自体にmain()機能はありますか?

誰かがこれを私に説明できますか?


1
また、同じユーザーからの質問:stackoverflow.com/q/18266063/827263
キーストンプソン

@KeithThompson ...はい...私が欲しいものに答えられなかったからといって、それをここで尋ねました。
誰か

@Shadur ...とにかく閉じようとしている...そして、私はそれを移行する特権を持っていません...-
誰か

これは、他の方法で回避閉鎖されている必要があり、この1つはより多くの意見を持っている:-)
チロSantilli新疆改造中心法轮功六四事件

回答:


82

ユーザー空間プログラムでmain()は、バイナリの実行時にlibc初期化コードによって呼び出されるプログラムへのエントリポイントです。libc自体はメモリの割り当て、I / O、プロセス管理などのカーネルsyscallインターフェイスに依存しているため、カーネルコードにはlibcに依存する余裕はありません。

同等の、前記そのmain()カーネルコードでありstart_kernel()され、ブートローダによって呼び出されるカーネルイメージをロードした後は、メモリと設定必須のハードウェア、メモリページングにそれを解凍。start_kernel()システム設定の大部分を実行し、最終的にinitプロセスを生成します。

Linuxカーネルモジュールへのエントリポイントは、module_init()マクロを呼び出すことでカーネルに登録されるinit関数です。登録されたモジュールの初期化関数は、カーネルの起動時に関数を介してカーネルコードによって呼び出されますdo_initcalls()


11
mainC のメソッドの本当の目的を認識していただきありがとうございます(OSがに直接呼び出しを行うというのは、あまりにも一般的に誤解されていますが、mainC ++などではそうではありません)。 dそのためだけにできるなら、あなたにもう一度賛成票を差し上げます。
CVn

1
@Thomas ...この優れた答えをありがとう....-
誰か

17

カーネルにはmain機能がありません。 mainC言語の概念です。カーネルはCおよびアセンブリで記述されています。カーネルのエントリコードは、アセンブリによって記述されます。

ブートシーケンスは次のように構成されています。

  1. BIOSは通常、ブートブロックデバイスからブートローダーをロードします。現在人気のあるブートローダーはgrubです。
  2. Grubは、初期ルートデバイス(initrd)でカーネルイメージをRAMにロードします。次に、あるアドレスのコードが実行されます。
  3. カーネルイメージには、いくつかのカーネルモジュールがあります。たとえば、ファイルシステムモジュール、デバイスドライバーです。カーネルイメージは、ファイルシステムモジュールを使用してルートファイルシステムをマウントします。これで、カーネルはすべてのカーネルモジュールをディスクからロードして実行できます。
  4. カーネルは初期化タスクを実行します。たとえば、PCIバスを走査してすべてのPCIデバイスを見つけ、すべてのデバイスドライバーを初期化します。
  5. 最後に、カーネルはプロセス0とプロセス1(initプロセス)を作成し、CPUのコンテキストをリング0からリング3に切り替え、initプロセスを開始します(プロセスIDは1です)。これでカーネルの起動が完了しました!
  6. initプログラムは、すべてのinitスクリプトを実行します。すべてのサービスが開始されます。シェルが呼び出されます。ユーザーはログインできます。

mainこの関数はCの関数です。実際、メインのメソッドはCプログラムのエントリポイントではありません。Cランタイムは、以前に多くの関数を呼び出しますmain。GCCには、コンストラクターという拡張機能があります。「コンストラクタ」と宣言された関数は、前に呼び出されmainます。

例えば:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \
} 

このマクロはqemuプロジェクトのものです。


メインメソッドはacメソッドです。実際には、メインメソッドはcプログラムのエントリではありません。Cランタイムは、メインメソッドの前に多くのメソッドを呼び出しました。
エドワードシェン

さて、BIOSは通常ブートローダーをロードし、そのブートローダーはカーネルイメージ(および場合によってはinitrd)をロードします。カーネルのコードがないのinitrd、カーネルイメージである
ステファンChazelas

GCCには拡張機能:コンストラクターがあります。メソッド宣言「コンストラクタ」は、メインメソッドの前に呼び出されます。例:/ *これは直接使用しないでください。代わりにblock_initなどを使用してください。* / #define module_init(function、type)\ static void _attribute __((constructor))do_qemu_init ## function(void){\ register_module_init(function、type); \}
エドワードシェン

1
initrd.img カーネルイメージではありません。これは、ブート時にカーネルによってロードされるモジュールのセットです。カーネルイメージの名前は通常「vmlinuz」で始まりますが、ディストリビューションごとに異なります。
goldilocks

3
この答えは「すべてがPC / Linux / i86」でぎっしり詰まっていて、それがそのように起動し、カーネルがそのようになります。
イェンス

9

たとえば、arch / x86 / boot / main.cにはmain()関数があり、システムを実モードから保護モードに切り替える準備ができますが、他のアーキテクチャにはそのようなコードはありません。x86プラットフォームでのLinuxカーネル2.6.xの起動がどのように機能するかについての概要があります。読む価値は本当にあります。

文書HOWTO do Linux kernel developmentによると、Linuxカーネルは

標準Cライブラリに依存しない独立したC環境。したがって、C標準の一部はサポートされません。

C標準のBTWによるとはどういう意味ですか

独立した環境にあるプログラムが「メイン」機能を定義する必要があるかどうかは、実装で定義されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.