11

完全なコンテキストを提供するために、ユニプロセッサである ARM Cortex A8 ベースの SoC で SMP Linux (3.0.1-rt11) を実行しているという観察から私の議論を始めました。SMP サポートを無効にすることでパフォーマンスが向上するかどうか知りたいと思っていました。はいの場合、ドライバーと割り込みハンドラーにどのような影響がありますか。

いくつか読んだところ、スピンロックとカーネル プリエンプションという 2 つの関連トピックに出くわしました。私はもう少しグーグルと読書をしましたが、今回は古くて矛盾した答えがほとんどありません. それで、stackoverflowを試してみようと思いました。

私の疑問/質問の起源は、Linuxデバイスドライバーの第3版第5章のこのパラです。

スピンロックは、その性質上、マルチプロセッサ システムでの使用を意図していますが、プリエンプティブ カーネルを実行するユニプロセッサ ワークステーションは、並行性に関する限り、SMP のように動作します。非プリエンプティブ ユニプロセッサ システムがロックでスピンに入った場合、永久にスピンします。他のスレッドが CPU を取得してロックを解放することはできません。このため、プリエンプションが有効になっていないユニプロセッサ システムでのスピンロック操作は、IRQ マスキング ステータスを変更するものを除いて、何もしないように最適化されています。コードが SMP システムで実行されるとはまったく予想していない場合でも、プリエンプションのために、適切なロックを実装する必要があります。

私の疑問/質問は次のとおりです。

a) Linux カーネルはデフォルトでカーネル空間でプリエンプティブですか? はいの場合、このプリエンプションはプロセスのみに制限されていますか、それとも割り込みハンドラもプリエンプトできますか?

b) Linux カーネル (ARM 上) はネストされた割り込みをサポートしていますか? はいの場合、各割り込みハンドラー (上半分) は独自のスタックを持ちますか、それとも同じ 4k/8k カーネル モード スタックを共有しますか?

c) SMP ( CONFIG_SMP) とプリエンプション ( CONFIG_PREEMPT) を無効にした場合、ドライバーと割り込みハンドラーのスピンロックは意味がありますか?

d) 上半分の実行中に発生した割り込みをカーネルがどのように処理するか、つまり、それらは無効化またはマスクされますか?

いくつかのグーグルの後、私はこれを見つけました:

CONFIG_SMP および CONFIG_PREEMPT なしでコンパイルされたカーネルの場合、スピンロックはまったく存在しません。これは優れた設計上の決定です。他の誰も同時に実行できない場合、ロックを設定する理由はありません。

カーネルが CONFIG_SMP なしでコンパイルされているが、CONFIG_PREEMPT が設定されている場合、スピンロックはプリエンプションを無効にするだけで、競合を防ぐのに十分です。ほとんどの場合、プリエンプションは SMP と同等と考えることができ、個別に心配する必要はありません。

しかし、ソースにはカーネルのバージョンや日付はありません。最新の Linux カーネルに対してまだ有効かどうかを確認できますか?

4

1 に答える 1

7

a) Linux がプリエンプティブかどうかは、 でそのように構成するかどうかによって異なり
ますCONFIG_PREEMPT。デフォルトはありません。を実行する場合make configは、選択する必要があります。

b) Linux では割り込みがネストされます。割り込みが処理されている間、他の割り込みが発生する可能性があります。これは、ARM や他の多くのアーキテクチャに当てはまります。それはすべて同じスタックにあります。もちろん、ユーザー空間スタックは割り込みには使用されません!

c) SMP とプリエンプションを無効にすると、コード内のスピンロックが通常のスピンロックの場合はノーオペレーションになり、IRQ スピンロック ( spin_lock_irqsave/ spin_lock_irqrestore) は割り込みの無効化/有効化に変わります。したがって、後者は依然として不可欠です。コードを実行するタスクとコードの実行を中断するタスク間の競合を防ぎます。

d) 「上半分」は、伝統的に割り込みサービス ルーチンを指します。ドライバーの上半分のコードは、割り込みによって実行されます。下半分はタスクによって呼び出されます (データの読み取りまたは書き込みなど)。割り込み処理の詳細はアーキテクチャ固有です。

私は最近、特定の MIPS アーキテクチャで Linux の割り込みに非常に密接に取り組みました。その特定のボードには、2 つの 64 ビット ワードを介してマスク可能な 128 の割り込みラインがありました。カーネルはこれに加えて優先度スキームを実装していたため、特定の割り込みのハンドラーを実行する前に、これらの 2x64 ビット レジスタの更新によって下位の割り込みがマスクされていました。割り込み優先度をハードウェアの位置ではなく任意に設定できるように変更を実装し、動的に値を /procエントリ。さらに、数値の IRQ 優先度の一部がタスクのリアルタイムの優先度と重なるハックを入れました。そのため、特定の範囲の優先度レベルに割り当てられた RT タスク (つまり、ユーザー空間スレッド) は、実行中に特定の範囲の割り込みを暗黙的に抑制することができました。これは、不適切な動作の割り込みが重要なタスクに干渉するのを防ぐのに非常に役立ちました (たとえば、コンパクト フラッシュに使用される IDE ドライバー コードの割り込みサービス ルーチンは、ハードウェア インターフェイスの設計が不適切なためにビジー ループを実行し、フラッシュへの書き込みを引き起こします)。事実上、システム内で最も優先度の高いアクティビティになります。) したがって、顧客が使用するカーネルを制御している場合、IRQ マスキングの動作は決まったものではありません。

spin_lock質問の引用文は、 IRQ スピンロック ( ) ではなく、通常のスピンロック (関数/マクロ)についてのみ当てはまりますspin_lock_irqsave。ユニプロセッサ上のプリエンプティブル カーネルでは、プリエンプションspin_lockを無効にするだけで済みます。これは、他のすべてのタスクをspin_unlock. ただし、spin_lock_irqsave割り込みを無効にする必要があります。

于 2013-05-27T04:57:45.130 に答える