Linuxでは、デバイスドライバーがロード可能なカーネルモジュールとして構築されている場合、デバイスドライバーカーネルモジュールを挿入すると、カーネルはmodule_init()
マクロで示されるようにデバイスドライバーのinit関数を呼び出します。
これは、カーネルに静的にコンパイルされたデバイスドライバーに対してどのように機能しますか?それらのinit関数はどのように呼ばれますか?
Linuxでは、デバイスドライバーがロード可能なカーネルモジュールとして構築されている場合、デバイスドライバーカーネルモジュールを挿入すると、カーネルはmodule_init()
マクロで示されるようにデバイスドライバーのinit関数を呼び出します。
これは、カーネルに静的にコンパイルされたデバイスドライバーに対してどのように機能しますか?それらのinit関数はどのように呼ばれますか?
組み込みドライバーのinitmodule_init()
ルーチンは、引き続きマクロを使用してそのエントリポイントを宣言できます。または、ドライバーがdevice_initcall()
ロード可能なモジュールとしてコンパイルされない場合に、ドライバーを使用できます。または、起動シーケンスの非常に早い段階で初期化を移動するために、ドライバーはを使用できますsubsys_initcall()
。
これらのinitルーチンinclude/linux/init.h
を呼び出すシーケンスでは、次のように記述されます。
/* initcalls are now grouped by functionality into separate
* subsections. Ordering inside the subsections is determined
* by link order.
* For backwards compatibility, initcall() puts the call in
* the device init subsection.
*
* The `id' arg to __define_initcall() is needed so that multiple initcalls
* can point at the same handler without causing duplicate-symbol build errors.
*/
デバイスドライバーのこれらのサブセクションdrivers
は、Linuxカーネルソースツリーのディレクトリ内のサブディレクトリに対応し、リンクの順序はの各サブディレクトリのbuilt-in.oファイルに記録されていると思いますdrivers
。したがって、カーネルの起動中に、各組み込みドライバのinitルーチンは最終的にinによって実行さdo_initcalls()
れinit/main.c
ます。
デバイスドライバのinitルーチンは、HWデバイスが実際に存在することを確認するためにシステムをプローブする役割を果たします。プローブに障害が発生した場合、ドライバーはリソースを割り当てたり、デバイスを登録したりしないでください。
更新:
カーネルコマンドラインでオプション「initcall_debug」を渡すと、各initcallのタイミング情報がコンソールに出力されます。initcallsは、静的にリンクされたカーネルドライバーとサブシステムを初期化し、Linuxのブートプロセスにかなりの時間を費やすために使用されます。出力は次のようになります。
calling tty_class_init+0x0/0x44 @ 1
initcall tty_class_init+0x0/0x44 returned 0 after 9765 usecs
calling spi_init+0x0/0x90 @ 1
initcall spi_init+0x0/0x90 returned 0 after 9765 usecs
kernelinit.hのコメントで指定されているとおり
「module_init()は、do_initcalls()(組み込みの場合)またはモジュール挿入時(モジュールの場合)のいずれかで呼び出されます。」
init.hを調べると、次のように表示されます。
module_init(x)__initcall(x);を定義します。
そして、あなたが注意深く観察するならば、
__initcall(fn)を定義しますdevice_initcall(fn)
と
device_initcall(fn)を定義します__define_initcall( "6"、fn、6)
したがって、基本的にモジュールinitは、起動時にのみinitcall(注:静的にコンパイルされたモジュールの場合のみ)につながります。