51

Robert Loveの次の記事を読んでいます

http://www.linuxjournal.com/article/6916

それは言う

「...ワーク キューがプロセス コンテキストで実行されるという事実について説明しましょう。これは、すべて割り込みコンテキストで実行される他の下位半分のメカニズムとは対照的です。割り込みコンテキストで実行されるコードは、割り込みのため、スリープまたはブロックできません。コンテキストには、再スケジュールするバッキング プロセスがありません。したがって、割り込みハンドラはプロセスに関連付けられていないため、スケジューラがスリープ状態になることはなく、さらに重要なことに、スケジューラが起動することもありません..."

理解できません。私の知る限り、カーネルのスケジューラは O(1) であり、ビットマップを介して実装されます。では、スケジューラが割り込みコンテキストをスリープ状態にし、次のスケジュール可能なプロセスを取得して制御を渡すのを阻止するものは何でしょうか?

4

11 に答える 11

44

では、スケジューラが割り込みコンテキストをスリープ状態にし、次のスケジュール可能なプロセスを取得して制御を渡すのを阻止するものは何ですか?

問題は、割り込みコンテキストがプロセスではないため、スリープ状態にできないことです。

割り込みが発生すると、プロセッサはレジスタをスタックに保存し、割り込みサービス ルーチンの先頭にジャンプします。これは、割り込みハンドラーが実行されている場合、割り込みが発生したときに実行されていたプロセスのコンテキストで実行されていることを意味します。割り込みはそのプロセスのスタックで実行されており、割り込みハンドラーが完了すると、そのプロセスは実行を再開します。

割り込みハンドラー内でスリープまたはブロックしようとすると、割り込みハンドラーが停止するだけでなく、中断されたプロセスも停止します。割り込みハンドラーは、割り込まれたプロセスが何をしていたのかを知る方法がないため、またはそのプロセスが一時停止されても安全であるかどうかを知る方法がないため、これは危険な場合があります。

問題が発生する可能性がある単純なシナリオは、割り込みハンドラーとそれが割り込むプロセスの間のデッドロックです。

  1. Process1 がカーネル モードに入ります。
  2. Process1はLockAを取得します。
  3. 割り込みが発生します。
  4. ISR は、Process1のスタックを使用して実行を開始します。
  5. ISR はLockAの取得を試みます。
  6. ISR は sleep を呼び出して、LockAが解放されるのを待ちます。

この時点で、デッドロックが発生します。 Process1は、ISR がそのスタックで完了するまで実行を再開できません。しかし ISR は、 Process1 が LockA を解放するのを待ってブロックます。

于 2009-06-27T21:10:49.537 に答える
35

デザインのアイデアだと思います。

確かに、中断して眠ることができるシステムを設計することはできますが、システムを理解しにくく複雑にすることを除いて(多くの状況を考慮に入れる必要があります)、それは何の助けにもなりません。したがって、設計の観点から、スリープできないとして割り込みハンドラを宣言することは非常に明確で、実装が簡単です。


Robert Love(カーネルハッカー)から:http: //permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791

割り込みにはバッキングプロセスコンテキストがないため、割り込みハンドラでスリープすることはできません。したがって、スケジュールを変更する必要はありません。言い換えると、割り込みハンドラーはタスクに関連付けられていないため、「スリープ状態にする」ことはなく、(さらに重要なことに)「ウェイクアップするものもありません」。それらはアトミックに実行する必要があります。

これは他のオペレーティングシステムと同じです。ほとんどのオペレーティングシステムでは、割り込みはスレッド化されていません。ただし、下半分は多くの場合です。

ページフォールトハンドラーがスリープできる理由は、プロセスコンテキストで実行されているコードによってのみ呼び出されるためです。カーネル自体のメモリはページングできないため、ユーザースペースのメモリアクセスのみがページフォールトを引き起こす可能性があります。したがって、カーネル内でページフォールトを引き起こす可能性があるのは、特定の場所(copy_ {to、from} _user()の呼び出しなど)のみです。これらの場所はすべて、スリープ可能なコード(つまり、プロセスコンテキスト、ロックなしなど)で作成する必要があります。

于 2009-06-29T05:37:23.437 に答える
6

その時点でスレッド切り替えインフラストラクチャが使用できないためです。割り込みを処理するときは、優先度の高いものだけを実行できます。割り込み、タスク、およびプロセッサの優先度については、Intel Software Developer's Manual を参照してください。別のスレッドの実行を許可した場合 (質問で簡単に実行できることを暗示しています)、何も実行させることはできません。ページ フォールトが発生した場合は、サービスを使用する必要があります。カーネルでは、割り込みが処理されている間は使用できません (理由については以下を参照してください)。

通常、割り込みルーチンでの唯一の目標は、デバイスに割り込みを停止させ、より低い割り込みレベル (UNIX ではこれは通常非割り込みレベルですが、Windows ではディスパッチ、apc、またはパッシブ レベルです) で何かをキューに入れることです。カーネル/OS のより多くの機能にアクセスできる重い仕事をしてください。ハンドラーの実装を参照してください。

これは、Linux に固有のものではなく、O/S がどのように動作する必要があるかの特性です。割り込みルーチンはいつでも実行できるため、割り込みの状態は一貫していません。スレッド スケジューリング コードを中断した場合、その状態は矛盾しているため、「スリープ」してスレッドを切り替えることができるかどうかを確認できません。スレッド切り替えコードが中断されないように保護したとしても、スレッド切り替えは O/S の非常に高レベルの機能であり、スレッド切り替えが依存するすべてのものを保護した場合、割り込みはその名前が暗示する命令よりもむしろ提案になります。

于 2009-06-27T20:43:01.433 に答える
3

So what stops the scehduler from putting interrupt context to sleep and taking next schedulable process and passing it the control?

Scheduling happens on timer interrupts. The basic rule is that only one interrupt can be open at a time, so if you go to sleep in the "got data from device X" interrupt, the timer interrupt cannot run to schedule it out.

Interrupts also happen many times and overlap. If you put the "got data" interrupt to sleep, and then get more data, what happens? It's confusing (and fragile) enough that the catch-all rule is: no sleeping in interrupts. You will do it wrong.

于 2009-06-27T22:52:24.980 に答える
2

ISRをスリープ状態にすることができたとしても、それはしたくないでしょう。後続の割り込みを見逃すリスクを減らすために、ISRをできるだけ高速にする必要があります。

于 2009-07-30T17:56:10.197 に答える
2

割り込みハンドラのブロックを禁止することは、設計上の選択です。一部のデータがデバイス上にある場合、割り込みハンドラーは現在のプロセスをインターセプトし、データの転送を準備して、割り込みを有効にします。ハンドラが現在の割り込みを有効にする前に、デバイスがハングする必要があります。I/O をビジー状態に保ち、システムの応答性を維持したい場合は、割り込みハンドラーをブロックしない方がよいでしょう。

「不安定な状態」が本質的な理由だとは思いません。プロセスは、ユーザー モードまたはカーネル モードに関係なく、割り込みによって中断される可能性があることに注意する必要があります。一部のカーネル モード データ構造が割り込みハンドラーと現在のプロセスの両方によってアクセスされ、競合状態が存在する場合、現在のプロセスはローカル割り込みを無効にする必要があり、さらにマルチプロセッサ アーキテクチャの場合は、クリティカル セクション中にスピンロックを使用する必要があります。 .

また、割り込みハンドラがブロックされていた場合、ウェイクアップできないとは思いません。「ブロック」と言うとき、基本的には、ブロックされたプロセスが何らかのイベント/リソースを待っていることを意味するため、そのイベント/リソースの待機キューにリンクされます。リソースが解放されるたびに、解放プロセスは待機中のプロセスを起動する責任があります。

ただし、本当に面倒なことは、ブロックされたプロセスがブロックされている間は何もできないことです。それは不公平であるこの罰に何の問題もありませんでした。そして、誰もブロック時間を確実に予測することはできなかったので、無実のプロセスは不明確な理由で無限の時間待たなければなりません.

于 2011-01-16T23:26:31.483 に答える
1

Linux カーネルには、割り込みスタックを割り当てる 2 つの方法があります。1 つは割り込まれたプロセスのカーネル スタック上にあり、もう 1 つは CPU ごとの専用の割り込みスタックにあります。割り込みコンテキストが CPU ごとの専用割り込みスタックに保存されている場合、実際には、割り込みコンテキストはどのプロセスにも完全に関連付けられていません。「現在の」マクロは、現在実行中のプロセスへの無効なポインターを生成します。これは、一部のアーキテクチャの「現在の」マクロがスタック ポインターで計算されるためです。割り込みコンテキストのスタック ポインターは、一部のプロセスのカーネル スタックではなく、専用の割り込みスタックを指す場合があります。

于 2010-08-03T19:25:17.090 に答える
0

上位レベルの割り込みルーチンが一定期間後に次に実行する必要があるポイントに到達した場合、別の割り込みルーチンを実行するように要求する要求をタイマーキューに入れる必要があります(優先度は低くなります)。レベル)しばらくしてから。

その割り込みルーチンが実行されると、優先度レベルが元の割り込みルーチンのレベルに戻り、実行が続行されます。これは睡眠と同じ効果があります。

于 2009-07-30T17:57:59.150 に答える
0

これは、Linux OS での設計/実装の選択にすぎません。この設計の利点はシンプルですが、リアルタイム OS の要件には適さない場合があります。

他の OS には、他の設計/実装があります。

たとえば、Solaris では、割り込みにさまざまな優先度を設定できるため、ほとんどのデバイス割り込みを割り込みスレッドで呼び出すことができます。割り込みスレッドのそれぞれがスレッドのコンテキストで個別のスタックを持っているため、割り込みスレッドはスリープを許可します。割り込みスレッドの設計は、割り込みよりも高い優先度を持つ必要があるリアルタイム スレッドに適しています。

于 2013-01-31T03:47:28.097 に答える
0

高レベルの割り込みハンドラは、システム タイマー割り込みを含む、優先順位の低いすべての割り込みの操作をマスクします。したがって、割り込みハンドラーは、スリープ状態になる可能性のあるアクティビティに関与しないようにする必要があります。ハンドラーがスリープ状態になると、タイマーがマスクされ、スリープ状態のスレッドをスケジュールできないため、システムがハングする可能性があります。これは理にかなっていますか?

于 2009-07-30T17:50:36.980 に答える