web-dev-qa-db-ja.com

Linux組み込みドライバーのロード順序とは何ですか?

組み込みドライバーの読み込み順序をどのようにカスタマイズできますか(一部の組み込みドライバーモジュールを最初に読み込み、依存モジュールを後で読み込みます)?

26
Dien Nguyen

組み込みドライバーはloadedではないため、組み込みドライバーです。それらの初期化関数が呼び出され、カーネルがそれ自体をセットアップするときにドライバーがアクティブ化されます。これらの初期化関数はinit/main.c::do_initcalls()で呼び出されます。すべてのinit呼び出しは、_initcall_levels_および_include/linux/init.h_で定義されているレベルに分類されます。

これらのレベルは、リンカースクリプト(_Arch/*/kernel/vmlinux.lds.*_)で定義された実際のシンボルです。カーネルのコンパイル時に、リンカーはmodule_init()またはその他の*_initcall()とマークされたすべての関数を収集し、レベルに分類し、すべての関数を同じレベルにまとめて同じ場所に配置し、配列のように作成します関数ポインタの。

Do_initcall_level()が実行時に行うことは、配列内のポインターが指す各関数を呼び出すことです。 do_initcall_levelには、レベル以外の呼び出しポリシーはありませんが、配列内の順序はリンク時に決定されます。

これで、ドライバーの開始順序がリンク時に固定されていることがわかりますが、何ができますか?

  1. init関数を上位レベルに置く、または
  2. デバイスドライバーをMakefileの上位に配置します

上記を読んだなら、最初のものは明らかです。つまり、適切であれば、代わりにearly_initcall()を使用してください。

2つ目はもう少し説明が必要です。 Makefileの順序が重要である理由は、現在のカーネルビルドシステムの動作方法とリンカーの動作方法です。簡単に言えば、ビルドシステムは_obj-y_内のすべてのオブジェクトファイルを取得し、それらをリンクします。これは環境に大きく依存しますが、リンカが最初のオブジェクトファイルを_obj-y_の下位アドレスに配置する可能性が高いため、先に呼び出されます。

ドライバーを同じディレクトリ内の他のドライバーより前に呼び出す場合は、これが最も簡単な方法です。

38
Yasushi Shoji

depmodは、各モジュールによってエクスポートされ、必要なシンボルを調べ、modprobeが後で適切な順序でモジュールをロードするために使用できるトポロジーソートを行います。依存したいモジュールからのシンボルを要求するだけで、正しいことを実行できます。

initrd 内であっても、正しいモジュールの順序と依存関係は modprobe によって処理されます。

最近、この問題が発生しました。充電器ドライバーがADCドライバーに依存しているため、ADCドライバーをロードする前に、充電器ドライバーがロードされ、DTSファイルで定義されているADCハンドルをチェックして、ADCドライバーによって初期化する必要があります。 .drivers/Makefileでモジュールの順序を変更することで解決しました

0
Nagi