4

1つのCPUと非優先的なLinuxカーネル(2.6.x)を備えたシステムでは、spin_lock呼び出しは空の呼び出しと同等であるため、そのように実装されていることを読みました。

私はそれを理解できません:それはミューテックスでの睡眠に相当するべきではありませんか?非優先カーネルでも、たとえば割り込みハンドラーが実行されたり、元のスレッドをスリープ状態にする関数を呼び出したりする場合があります。したがって、空のspin_lock呼び出しが、ミューテックスとして実装された場合のように「安全」であるとは限りません。

わからないものはありますか?

4

4 に答える 4

6

spin_lock()非プリエンプティブカーネルでデータを割り込みハンドラから保護するために使用する場合、(シングルプロセッサマシンで)デッドロックが発生します。

他のカーネルコードがロックを保持しているときに割り込みハンドラーが実行されると、通常のカーネルコードがロックを再開して解放する方法がないため、割り込みハンドラーは永久にスピンします。

スピンロックは、ロックホルダーが常に完了することができる場合にのみ使用できます。

割り込みハンドラーが必要とする可能性のあるロックの解決策は、を使用することspin_lock_irqsave()です。これにより、スピンロックが保持されている間は割り込みが無効になります。1 CPUでは、割り込みハンドラーを実行できないため、デッドロックは発生しません。smpでは、割り込みハンドラーが別のCPUで回転を開始する場合がありますが、ロックを保持しているCPUは割り込みできないため、最終的にロックが解放されます。

于 2010-07-30T15:27:19.167 に答える
6

あなたの質問の2つの部分に答えるには:

非優先カーネルでも、割り込みハンドラは実行される可能性があります...

spin_lock()割り込みハンドラから保護することは想定されていません。ユーザーコンテキストカーネルコードのみです。 spin_lock_irqsave()は割り込みを無効にするバージョンであり、これ非プリエンプティブユニプロセッサでのノーオペレーションではありません。

...または、元のスレッドをスリープ状態にする関数を呼び出す場合があります。

スピンロックを保持したままスリープすることはできません。これは「アトミック中のスケジューリング」のバグです。スリープしたい場合は、代わりにミューテックスを使用する必要があります(これも、プリエンプティブでないユニプロセッサではノーオペレーションではありません)。

于 2010-07-31T05:07:50.873 に答える
5

Jonathan Corbet、Alessandro Rubini、GregKroah-Hartmanによる«LinuxDeviceDrivers»からの引用:

非プリエンプティブユニプロセッサシステムがロックでスピンした場合、それは永久にスピンします。他のスレッドは、ロックを解放するためにCPUを取得できません(それが降伏できなかったため)。このため、プリエンプションが有効になっていないユニプロセッサシステムでのスピンロック操作は、IRQマスキングステータスを変更するもの(Linuxではそうなる)を除いて、何もしないように最適化されています spin_lock_irqsave()。プリエンプションのため、コードがSMPシステムで実行されることを予期しない場合でも、適切なロックを実装する必要があります。

割り込みコンテキスト(ハードウェアまたはソフトウェア)で実行されているコードによって取得できるスピンロックに関心がある場合は、割り込みspin_lock_*を無効にする形式を使用する必要があります。そうしないと、クリティカルセクションに入っている間に割り込みが到着するとすぐにシステムがデッドロックします。

于 2010-07-31T05:44:47.197 に答える
1

定義上、プリエンプティブでないカーネルを使用している場合、プリエンプションされることはありません。独自のマルチタスクを実行する場合、それはカーネルの問題ではありません。それはあなたの問題だ。割り込みハンドラーは引き続き実行できますが、コンテキストスイッチは発生しません。

于 2010-07-30T14:47:55.503 に答える