1

ですから、私は現在スレッドについて学んでいて、いくつかのことがどのように処理されるのか疑問に思っています。たとえば、あるスレッドが入力をリッスンし、別のスレッドが単一のプロセッサで計算を実行するプログラムがあるとします。計算スレッドが実行されているときに、ユーザーが入力スレッド専用のボタンを押す必要がある場合はどうなりますか?その特定のスレッドに切り替えられるまで、入力は入力スレッドによって無視されませんか?

4

5 に答える 5

3

これは、入力メカニズムがどのように実装されているかに大きく依存します。I / Oを実装する簡単ですが非常に不利な方法の1つは、継続的なポーリングです...そのシナリオでは、入力スレッドがループになり、ハードウェアレジスタを何度も読み取り、レジスタの値が変化したときに発生する可能性があります。 0から1まで、入力スレッドはボタンが押されたことを認識します。

void inputThread()
{
   while(1)
   {
      if (some_register_indicates_the_button_is_pressed()) react();
   }
}

この方法の問題は、それがひどく非効率的であるということです。入力スレッドは、レジスタを何度もチェックするだけで、数十億のCPUサイクルを使用しています。このコードを実行するマルチスレッドシステムでは、スレッドスケジューラはCPUをビジー待機中の入力スレッドと計算スレッドの間で量子ごとに(たとえば10ミリ秒ごとに)切り替えるため、入力スレッドはCPUサイクルの半分と計算スレッドを使用します残りの半分を使用します。このシステムでは、ユーザーがボタンを押した瞬間に入力スレッドが実行されていれば、入力はほぼ瞬時に検出されますが、計算スレッドが実行されていれば、次に入力スレッドが取得されるまで入力は検出されません。実行するため、10mSの遅延が発生する可能性があります。(さらに悪いことに、ユーザーがボタンを離すのが早すぎると、

継続的なポーリングに対する改善は、スケジュールされたポーリングです。上記と同じように機能しますが、入力スレッドがループでポーリングするのではなく、1回ポーリングしてからしばらくスリープしてから、再度ポーリングする点が異なります。

void inputThread()
{
   while(1)
   {
      if (some_register_indicates_the_button_is_pressed()) react();
      usleep(3000);  // sleep for 30 milliseconds
   }
}

usleep()が呼び出されるたびに、スレッドスケジューラが入力スレッドをスリープ状態にし、CPUが他のスレッドですぐに使用できるようになるため、これは最初のケースよりもはるかに非効率的です。usleep()もハードウェアタイマーを設定し、そのハードウェアタイマーがオフになると(30ミリ秒後)、割り込みを発生させます。割り込みにより、CPUは実行中の処理をすべて中断し、スレッドスケジューリングコードを再度実行します。スレッドスケジューリングコードは、(ほとんどの場合)usleep()が戻る時間を認識し、入力スレッドをウェイクアップします。そのため、ループをもう一度繰り返すことができます。これはまだ完全ではありません。inputThreadは継続的に少量のCPUを使用していますが、それほど多くはありませんが、これを何度も実行すると、合計が増え始めます。また、

これにより、割り込み駆動型I/Oが実現します。このモデルでは、入力スレッドはまったくポーリングしません。代わりに、ボタンが押されたときに通知するようにOSに指示します。

void inputThread()
{
   while(1)
   {
      sleep_until_button_is_pressed();
      react();
   }
}

次に、OSの通知機能は、ボタンが押されたときにOSに通知されるように設定する必要があります。これにより、OSはウェイクアップして、入力スレッドに通知できます。OSは、ボタンが押されたときに割り込みを生成するようにボタンの制御ハードウェアに指示することによってこれを行います。その割り込みがオフになると、前の例のタイマー割り込みとほとんど同じように機能します。CPUはスレッドスケジューラコードを実行します。これにより、入力スレッドをウェイクアップする時間であることがわかり、入力スレッドが実行されます。このメカニズムには非常に優れた特性があります。(1)ボタンが押されたときに入力スレッドができるだけ早くウェイクアップされ(計算スレッドが最初にクォンタムを終了するのを待つ必要はありません)、(2)入力スレッドが消費されませんボタンが押されたときを除いて、すべてのCPUサイクル。これらの利点のために、それは」

最近のPCまたはMacでは、2つのスレッドとハードウェアボタンだけでなく、さらに多くのことが行われていることに注意してください。たとえば、数十のハードウェアデバイス(キーボード、マウス、ビデオカード、ハードドライブ、ネットワークカード、サウンドカードなど)と数十のプログラムが同時に実行され、必要に応じてそれらすべてを仲介するのはオペレーティングシステムの仕事です。それにもかかわらず、一般的な原則は同じです。あなたの例では、ユーザーがクリックしたボタンは物理的なボタンではなく、画面上のGUIボタンだったとしましょう。その場合、次の一連のイベントのようなものが発生します。

  1. ユーザーの指がマウスの左ボタンを押した
  2. マウスの内部ハードウェアは、マウスボタンを押したメッセージをUSBケーブルを介してコンピューターのUSBコントローラーに送信します
  3. コンピューターのUSBコントローラーが割り込みを生成します
  4. 割り込みにより、CPUは計算スレッドのコードから抜け出し、OSのスケジューラルーチンを実行します
  5. スレッドスケジューラは、USB割り込みラインがUSBイベントの準備ができていることを示していることを確認し、USBドライバの割り込みハンドラコードを実行して応答します。
  6. USBドライバーの割り込みハンドラーコードはイベントを読み取り、マウスボタンが押されたイベントであることを確認し、ウィンドウマネージャーに渡します。
  7. ウィンドウマネージャーは、どのウィンドウにフォーカスがあるかを知っているので、マウスボタンが押されたイベントを転送するプログラムを知っています。
  8. ウィンドウマネージャーは、そのウィンドウに関連付けられている入力スレッドをウェイクアップするようにOSに指示します
  9. 入力スレッドが起動し、react()を呼び出します
于 2013-02-10T00:13:58.737 に答える
1

シングルプロセッサシステムで実行している場合は、はい。

于 2013-02-09T16:19:17.093 に答える
1

さて、スレッドが互いに通信する方法は複数あります。それらの1つはグローバル変数を持ち、それを通信用のバッファーとして使用します。
ボタンについて尋ねたとき、イベントローダーループを含むスレッドが必要です。このスレッド内では、私の経験によれば、入力は無視されません。

このトピックに関する私のスレッドのいくつかを見ることができます。
ここでは、イベントを介して通信する3スレッドアプリケーションを作成する方法に興味がありました。

于 2013-02-09T16:19:27.503 に答える
1

簡単な答え:はい、スレッドは常に相互作用します。問題は、予測できない方法で相互作用すると現れ始めます。プロセス内のすべてのスレッドはプロセスメモリスペース全体にアクセスできるため、あるスレッドのメモリを変更すると、別のスレッドのデータが損なわれる可能性があります。

于 2013-02-09T16:19:29.797 に答える
1

ユーザー入力を待機しているスレッドは、「すぐに」準備が整います。ほとんどのOSでは、I / Oを待機して準備ができたスレッドに一時的な優先度のブーストが与えられ、シングルコアCPUでも、同じ優先度で実行されていた別のスレッドを「すぐに」プリエンプトします。

したがって、シングルコアCPUが計算を実行していて、同じ優先度の別の待機中のスレッドが入力を取得した場合、おそらくすぐに実行されます。

于 2013-02-09T19:38:39.793 に答える