私はLinuxデバイスドライバーを勉強していますが、私の主な焦点はwifiドライバーです。デバイスをプラグインしたときのコードの流れを知りたい。たぶん、すべての関数にprintk
行を追加するようなことができます。私が持っているデバイスはath9k_htc
ドライバーでサポートされています。学習用にドライバーコードに変更を加えたい。
Linuxのドライバーモジュールのコードフローを理解するための正しいまたは一般的なアプローチは何ですか?
これを行いたいときは、 ftrace
フレームワーク を使用します。まず、特別なファイルシステムをマウントします。
mount -t tracefs nodev /sys/kernel/tracing
(rootとして、このすべてのrootになる必要があります。とにかくすべてをrootとして実行します。Sudo
を使用するよりも、ルートシェルを持つ方が簡単です)。
次に、そのディレクトリに移動します。
cd /sys/kernel/tracing
簡単な要約を提供する基本的なREADME
が含まれています。関数呼び出しを調べるには、 関数グラフトレーサー 、function_graph
をavailable_tracers
で使用します。関心のある関数、たとえば ath9k_htc_tx
を特定して設定します
echo ath9k_htc_tx > set_graph_function
他の関数を追加できます。最初の関数の後に必ず>>
を使用してください。設定された機能は、
cat set_graph_function
set_graph_function
に書き込むと、実行中のカーネルに対して関数がチェックされます。関数が見つからない場合、書き込みは失敗するので、何もトレースしない場合はすぐにわかります。
関数が設定されたら、トレーサーを有効にします。
echo function_graph > current_tracer
次に、trace
ファイルを監視します。トレーサーを再度無効にするには、
echo nop > current_tracer
またはtracing_on
を反転するには、0または1を書き込みます(0はトレースを無効にし、1は再度有効にします)。
主な要点は、ドライバーが上位インターフェイスと下位インターフェイスを接続することです。の場合 ath9k_htc
、下部のインターフェースはUSB、上部のインターフェースはネットワークスタックです。
制御フローは、主に状態マシンであり、同期せずに両方のインターフェースから到着するイベントに対応できます。たとえば、ネットワークインターフェースがマルチキャストグループに参加するようにドライバーに通知すると同時に、デバイスが排出されたUSBサブシステム-マルチプロセッサシステムでは、これらのイベントはさまざまなCPUで報告され、ドライバーは同時に入力されます。
ほとんどのドライバーはプロセスまたはスレッドコンテキストを持たず、純粋にイベント駆動型であり、ドライバーの外部にイベントループがあるため、通常、特定のイベントを処理する小さな関数が多数あり、それらを転送しようとし、失敗した場合はどこかにメモします。そしてすぐに戻ります。
典型的なドライバーの制御フローを視覚化する最も賢明な方法は、共有のロック可能なリソースのマップを描画し、それらにアクセスする機能です。一般的な通信の行は、リストをロックし、データを追加し、ロックを解除することです。一方の側にUSB関連の関数を描画し、もう一方のリソースにネットワーク関連の関数を描画すると、最も明確な画像が得られます。