web-dev-qa-db-ja.com

ポーリングまたは割り込みベースの方法

いつポーリングメソッドを使用し、いつ割り込みベースのメソッドを使用する必要がありますか?両方を使用できるシナリオはありますか?

37

関心のあるイベントが次の場合:

  1. 非同期
  2. 緊急
  3. まれに

その後、割り込みベースのハンドラーが意味をなします。

関心のあるイベントが次の場合:

  1. 同期(つまり、小さなウィンドウ内でいつそれを期待するかを知っています)
  2. 緊急ではありません(つまり、ポーリング間隔を遅くしても悪影響はありません)
  3. 頻繁(つまり、ポーリングサイクルの大部分が「ヒット」を作成します)

ポーリングが適している場合があります。

その他の考慮事項には、OSのデバイスドライバーを作成するか、スレッドをサポートしないベアメタルコードを作成するだけかが含まれます。ベアメタルの状況では、CPUがビジーでないときにループすることがよくあるため、何かをポーリングしている可能性もあります。

57
Amardeep AC9MF

ポーリングは通常、不必要に多くのCPUサイクルを消費するため、可能な場合は回避する必要があります((a)短時間だけポーリングする場合、または(b)ポーリングループで妥当な時間スリープできる場合を除く) )。 CPUサイクルの浪費は、パフォーマンスの観点から悪いだけでなく、消費電力も増加させます。これは、バッテリー駆動の組み込みアプリケーションの問題になる可能性があります。

15
Paul R

ポーリングまたは割り込みを決定するときは、フォローしようとしているイベントの性質とそれに対する応答を完全に理解する必要があります。

割り込みは、何も起きていないときには処理を必要としませんが、何かが起こっているときには注意を払う必要があります。イベントが外部でノイズの多いエッジまたは高速パルスを持っている場合、これは割り込みで大きな頭痛の種になる可能性があります。割り込みのセットアップには注意する必要があります。

この例では、割り込みルーチンは、レーザービームがクリアになったことに応答し、ブロックされたイベントに対して自身をセットアップしています。

   BEAM_INTR_EN = TRUE;   /*re-enable the beam interrupts*/

   /*Set the beam interrupt for the next clear to blocked event*/
   BEAM_INTR_Edge = CLEAR_TO_BLOCKED;
   BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/

このコードには2つの弱点があります。1)割り込みフラグがクリアされる前にレーザービームが再びブロックされた場合(BEAM_INTR_FLAG = FALSE;)。割り込みが失われ、コードはレーザービームの状態と同期しなくなります。

2)バックグラウンドルーチンで、またはこのコードがオンになっている優先度よりも高い優先度で割り込みを設定する場合、割り込みを有効にするときは注意が必要です。割り込みフラグが有効になる前に(誤って)すでに設定されている場合、割り込みルーチンは有効になると、おそらく間違ったEdgeに対して誤って呼び出されます。

1)を修正する最も簡単な方法は、割り込みを設定した後、再確認し、発生した場合は割り込みを強制することです。修正するには2)割り込みの有効化を二重チェックの後に移動します。

   /*Set the beam interrupt for the next clear to blocked event*/
   BEAM_INTR_Edge = CLEAR_TO_BLOCKED;
   BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/

   /*Double check beam state to see if it has already gone blocked*/
   if (BEAM_STATE == BEAM_BLOCKED)
   {
      BEAM_INTR_FLAG = TRUE; /*Force the interrupt to re-enter the ISR after exiting*/
   }
   BEAM_INTR_EN = TRUE;    /*re-enable the beam interrupts*/

割り込みを強制すると、システムが同じステートマシンで動作し、手動で強制的に死角をカバーするように強制します。

基本的に:

   Set the Edge to detect the next interrupt event
   Clear the interrupt flag
   if (the event has already occurred)
   {
      Set the interrupt flag to force the interrupt
   }
   Enable the interrupt

イベントへの応答の時間を一定にする必要がある場合(たとえば、入力ラインがハイになった後、1ms +/- 10us、イベント信号を送信する)、通常は割り込みが最適です。

イベントへの応答の時間が特定の時間内にある必要がある場合(たとえば、入力ラインがハイになる1ms以内にイベント信号を送信する場合)、割り込みが最適です。

割り込みの問題は、スレッド化について考え始める必要があり、2つのコードが同じデータに同時にアクセスできることです。

割り込みは、何かが起こるのを待っている間、プロセッサが低電力モード(スリープ/アイドルなど)に移行できるようにするのにも適しています。

プロセッサが実行することが1つしかない場合、ポーリングはイベントに非常に厳しい時間応答を与えることができると言いましたが、多くの場合、割り込みハードウェアはイベントに応答するのに数サイクルかかりますが、タイトなポーリングループは実行します。

イベントのタイミングが重要ではなく、ノイズが発生する可能性がある場合(誰かがスイッチを押すなど)、ポーリングを行うと、長期的な移行を逃すことなく簡単にフィルタリングできます。よくある間違いは、設定時に複数回ポーリングすることです。

void fnInitialiseSystem(void)
{
   if (MODE_INPUT == MODE_A) /*First polling of the MODE_INPUT*/
   {
      PR2 = PR2_MODE_A;
   }
   else
   {  
      PR2 = PR2_MODE_B;
   }
   OpenTimer2( TIMER_INT_ON &
               T2_PS_1_1     &
               T2_POST_1_8   );

   if (MODE_INPUT == MODE_A) /*Second polling of the MODE_INPUT*/
   {
      CurrentMode = MODE_A;
      PROBE_INT_Edge = CLEAR_TO_BLOCKED;
   }
   else
   {  
      CurrentMode = MODE_B;
      PROBE_INT_Edge = BLOCKED_TO_CLEAR;
   }
}

上記の例では、MODE_INPUTは外部スイッチです。MODE_INPUTの2回のポーリングが異なる場合、動作は予期されていません。これらの種類の信号を読み取るときは、フィルタリングを使用して入力の長期的な状態を判断し、フィルタリングされたバージョンでアクションを実行するのが最善です。

たとえば、スイッチのデバウンスでは、定期的に(1msごとに)スイッチをチェックし、それらの数(たとえば16)がフィルターバージョン(スイッチを開く)と異なる場合(スイッチを閉じる)、結果を更新し、必要なアクションを実行します。信号のエイリアシングには注意してください、発振信号は安定しているように見えるかもしれません!

ポーリングと割り込みの使用例は、頻繁に変更されることはありませんが、変更するとノイズが多い入力を使用する場合です。やはりスイッチはこの良い例です。コードはスイッチ状態の変化を確認するために割り込みを設定できます。割り込みが発生すると、スイッチはスイッチ状態が「安定」になるまで定期的にポーリングできます。状態または元の状態に戻ります)。これにより、何も起きていないときの処理オーバーヘッドが低く、何かが起こっているときのノイズフィルタリングという利点が得られます。

8
fluffyben

実際には両方を使用する必要がある場合があります。たとえば、イベントが散発的であるが、高速バーストが発生する場合。最初に割り込みに応答し、次に割り込みポーリングを再度有効にしてから、別のイベントが既に発生しているかどうかを確認してから、割り込みコンテキストスイッチングのオーバーヘッドの一部を回避する必要があります。 Linux Network Interfaceはこのモードで動作すると思います。

7
simon
4

簡単な答えは、ポーリングが遅すぎる場合に割り込みメソッドを使用することです。 (遅すぎると、ポーリングでデータが失われた場合、割り込み方法が必要になります)

3
KevinDTimm

意思決定を促進できる設計上の制約は多数あります。私のアプリには割り込みとポーリングの組み合わせがあります:

  • 外部および内部のクロックソースが割り込みをトリガーします。それらを同期できるように、正確にタイムスタンプすることが重要です。
  • 着信シリアルメッセージは割り込みをトリガーします。受信FIFOは、オーバーフローする前に処理する必要があります。
  • FIFOが部分的に空の場合、発信メッセージは割り込みをトリガーします。アンダーフローする前に補充する必要があります。
  • バックグラウンドでポーリングされるISRのセットセマフォ。これには2つの利点があります。
    • 着信イベントを処理するために必要な計算には時間がかかる場合があります。 ISRに残っている場合、サービスの期限を超えて他のISRを遅延させる可能性があります。
    • イベントをシーケンスできます。たとえば、ポーリングループにより、メッセージが予想より少し早く到着する場合でも、ADCデータの収集と受信メッセージの解析の間で計算Xが常に行われることが保証されます。
3
AShelly

低レイテンシが必要な場合は、割り込みが優先されます。ある条件を1秒間にN回ポーリングすると、平均して、実際に発生してから1/Nの半分の時間でその条件を発見できます。

絶対的な決定論的タイミングが必要な場合、ポーリングが好ましい場合があります。本質的に、割り込みは予測不可能な時間に発生する可能性があり、タイミング分析を非常に複雑にしますが、ポーリングされたシステムでは、期限の充足について証明可能なステートメントを作成するのは比較的簡単です。

3
JustJeff

基本的に、ポーリングモードは、ハードウェアまたはソフトウェアの何らかの理由で割り込みモードが利用できない場合に使用されます。そのため、電力消費、パフォーマンスなどの観点から割り込みモードの方が望ましい(Paul Rに同意)。ポーリングモードは、プロトタイピング、周辺機器が不要なコア、およびテスト目的でも使用できます。

3
pmod

常に割り込みを使用してください。そうすれば、データを失うことはありません。イベント駆動型またはスレッド型のアプリケーションでは、最も遅い信号でも割り込み駆動する必要があります。

ポーリングを使用する必要があるのは、スケジューラを使用していて、ハードウェアのバッファがデータの損失がないことを保証するのに十分な深さである場合のみです。

3
Gerhard

ポーリングモードは、高頻度のイベントが発生するシステムで役立ちます。割り込みハンドラの開始と終了に関連するオーバーヘッドは、単純なポーリングよりも多くのCPUサイクルを使用します。たとえば、IPルーターでポーリングを使用して、パケット処理に使用できるCPU帯域幅を最大化できます。

2
ukembedded

Interrupt based designと比較してpolling basedを使用する方がはるかに優れていますすべてのポーリングでデータが返されることを期待するという意味でポーリングベースに欠陥があるためです。今、あなたは私が単一のポーリングが私にエラーを返したこのケースを回避すると言うかもしれませんが、なぜそれがエラーを返す可能性があるのに何かのためにポーリングするすべてのCPUサイクルを無駄にするのですか?そして、投票が失敗するかもしれないと予想することは、実用的な製品シナリオです。

Interrupt based designsは、単一の投票に関与する関数のレイヤーが多数ある場合にさらに意味があります。私にとって、それは一般的な慣行です:友人に必要な情報があるかどうか、毎日繰り返し(polling)尋ねますかORあなたが私に必要な情報を手に入れたら、interruptと私に言ってくれませんか。私たちは日々の生活の中で正しいことをしていると思いますが、気づきません。

ただし、interrupt based architecturesを実装する場合は、publish-subscribe design principleを確実に理解する必要があります。また、アプリドメインで実行する場合、割り込みを送信するコードの一部を本当に適切に記述する必要があります。複雑さを1か所に絞り込んでいるので、これは良いことです。

上記に加えて、ポーリングベースのアーキテクチャが無料で提供する他の利点を次に示します。

  • 非同期
  • まれなイベント/更新の場合に適合
  • データ利用可能なシナリオがある場合にのみ更新する
  • より良いエラー処理と管理
  • CPUサイクルのより良い使用法
  • より良いバッテリー寿命管理
  • リスナーをその下の複雑さから解放します

swを設計する場合、およびこの選択肢がある場合は、interruptベースの設計が満たされる可能性があるため、pollingベースよりも常にinterruptベースの設計を選択する必要があります。リスナーを使用したpollingベースの状況に対応しますが、ポーリングベースの設計はinterruptベースの設計を必要とする要件を満たすことはできません。

以下は簡単な比較マトリックスです

                     -INTERRUPT-      -LOOP-
Speed                  fast            slow
Eficiency              good            poor
CPU waste              low             high
multitasking           yes             no
complexity             high            low
debugging              +/- easy        easy
critical in time       excellent       poor
code bloat             low impact      high impact
0
Game_Of_Threads

ホストをビジーループで長時間待機させることは望ましくありません。また、頻繁に存在しないデータを頻繁にチェックすると、ポーリングが非効率になる可能性があります。そのため、ホストとデバイスが両方とも高速であれば、かなり高速であればポーリングを行います。

0
Jake Cook

主な5つの方法があります。

1)ブラインド

CPUはx msごとにデータをチェックします。 ETCチェックピン12。

2)ポーリング(ビジー/待機)

CPUは常に、UARTパケットの転送後にフラグを立てる。Flagレジスタを常にチェックします。ベストレスポンスタイム)のように、フラグが立てられるのを待っています。そうしないと。

3)割り込み:

CPUは正常に動作し、割り込みが発生すると、CPUはコンテキストをISRに切り替えます。ピン18が立ち下がりエッジを見た場合、ISR(1)を実行します。 ISRがアクティブでない間、悪い応答時間とCPUは何もできません。いつ発生するかわからない緊急アプリでそれを行います。

4)定期的なポーリング:

CPUは処理を行っていますが、ms秒ごとにチェックピン11を実行しています。ブラインドはその間に何も実行していません。緊急のアプリではなく、応答時間が悪いのは、ハードウェアが割り込みを発生させることを信頼していないときに行います。タイマー割り込みを使用して作成できます。

5)ダイレクトメモリアクセス。

高度なインターフェイスアプローチ。メモリとの間でデータを直接転送します。入力はメモリに直接読み込まれます。出力はメモリから直接書き込まれます。両方ともコントローラーを使用します。

0
M.Noufale