デバイスドライバーとカーネルプログラミングを学んでいます。Jonathan Corbetの本によるとmain()
、デバイスドライバーには機能がありません。
だから私は2つの質問:
main()
デバイスドライバーに関数が必要ないのはなぜですか?- カーネル自体に
main()
機能はありますか?
誰かがこれを私に説明できますか?
デバイスドライバーとカーネルプログラミングを学んでいます。Jonathan Corbetの本によるとmain()
、デバイスドライバーには機能がありません。
だから私は2つの質問:
main()
デバイスドライバーに関数が必要ないのはなぜですか?main()
機能はありますか?誰かがこれを私に説明できますか?
回答:
ユーザー空間プログラムでmain()
は、バイナリの実行時にlibc初期化コードによって呼び出されるプログラムへのエントリポイントです。libc自体はメモリの割り当て、I / O、プロセス管理などのカーネルsyscallインターフェイスに依存しているため、カーネルコードにはlibcに依存する余裕はありません。
同等の、前記そのmain()
カーネルコードでありstart_kernel()
され、ブートローダによって呼び出されるカーネルイメージをロードした後は、メモリと設定必須のハードウェア、メモリページングにそれを解凍。start_kernel()
システム設定の大部分を実行し、最終的にinitプロセスを生成します。
Linuxカーネルモジュールへのエントリポイントは、module_init()
マクロを呼び出すことでカーネルに登録されるinit関数です。登録されたモジュールの初期化関数は、カーネルの起動時に関数を介してカーネルコードによって呼び出されますdo_initcalls()
。
main
C のメソッドの本当の目的を認識していただきありがとうございます(OSがに直接呼び出しを行うというのは、あまりにも一般的に誤解されていますが、main
C ++などではそうではありません)。 dそのためだけにできるなら、あなたにもう一度賛成票を差し上げます。
カーネルにはmain
機能がありません。 main
C言語の概念です。カーネルはCおよびアセンブリで記述されています。カーネルのエントリコードは、アセンブリによって記述されます。
ブートシーケンスは次のように構成されています。
initrd
)でカーネルイメージをRAMにロードします。次に、あるアドレスのコードが実行されます。init
プロセス)を作成し、CPUのコンテキストをリング0からリング3に切り替え、initプロセスを開始します(プロセスIDは1です)。これでカーネルの起動が完了しました!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プロジェクトのものです。
initrd.img
カーネルイメージではありません。これは、ブート時にカーネルによってロードされるモジュールのセットです。カーネルイメージの名前は通常「vmlinuz」で始まりますが、ディストリビューションごとに異なります。
たとえば、arch / x86 / boot / main.cにはmain()関数があり、システムを実モードから保護モードに切り替える準備ができますが、他のアーキテクチャにはそのようなコードはありません。x86プラットフォームでのLinuxカーネル2.6.xの起動がどのように機能するかについての概要があります。読む価値は本当にあります。
文書HOWTO do Linux kernel developmentによると、Linuxカーネルは
標準Cライブラリに依存しない独立したC環境。したがって、C標準の一部はサポートされません。
C標準のBTWによるとはどういう意味ですか
独立した環境にあるプログラムが「メイン」機能を定義する必要があるかどうかは、実装で定義されます。