Event Structure は実際には、実行のスレッドをユーザーから隠す単なる抽象化です。これらのイベントをチェックし、イベント ハンドラーを呼び出すコードがコンピューターのどこかで実行されている必要があります。C では、このコード (プログラムの「メイン ループ」) を自分で提供する必要があります。このコードは、関心のあるさまざまなイベント ソースをチェックし、イベント ハンドラー関数を呼び出します。
トリックは、このメイン ループが CPU を乱暴に回転させないようにする方法です。簡単な方法の 1 つは、メイン ループを一定期間スリープさせてから、処理が必要なイベントがあるかどうかを確認してから、再びスリープ状態にすることです。これには、レイテンシが発生するという欠点があります。適切な場合は、オペレーティング システムにこれらのチェックを通常の操作の一部として実行させ、興味深いことが起こったときにアプリケーションのメイン ループを起動させることをお勧めします。Linux では、これは 'select' システム コールで行われますが、select には、ファイル記述子に関連付けることができるリソースしか指定できないという制限があるため、デバイス、stdin、ファイル、ネットワーク ポートは問題ありません。
編集:反対票を投じた人のために明確にするために:私はハードウェア割り込みの存在を否定していません。はい、コードが処理したいすべてのイベント (組み込みシステムやデバイス ドライバーなど) のハードウェア割り込みに直接アクセスできる場合は、ビジー待機またはスリープしない複数のエントリ ポイントを持つ真の「イベント ドリブン」コードを記述できます。 . ただし、Linux で実行される通常のアプリケーション レベルの C プログラムでは、このコード アーキテクチャは文字どおりには存在せず、アプリケーション レベルでエミュレートされます。どの Linux アプリケーションにも、メイン ループと少なくとも 1 つの実行スレッドがあります。このスレッドはスケジューラによって一時停止される場合がありますが、常に存在し、特定の命令に常に命令ポインタがあります。コードが main() を離れると、プログラムは終了します。コードがメインから戻り、後でカーネルからコールバックを取得する機能はありません。コードには単一のエントリ ポイントがあり、さまざまなイベント ハンドラーを手動で呼び出す必要があります。デバイスドライバー (またはシグナルを使用する非常に特定のシステムコード) 以外では、ユーザーが特定のメニュー項目をクリックした場合、カーネルまたはハードウェアに特定の関数を自動的に呼び出すことはできません。代わりに、コードが実行され、このイベント自体が検出されます。正しいイベント ハンドラを呼び出します。
LabView に「XX が発生したときにこの関数を呼び出す」ように指示できます。C では、独自のイベント ディスパッチ コードに「XX が発生したときにこの関数を呼び出す」と指示します。
私が言おうとしているのは (悪い意味で?)、イベント フレームワーク アーキテクチャは C / Linux アプリケーションに固有のものではないということです。イベント ドリブン フレームワークの外観を与えるメイン ディスパッチ スレッドを使用して、コードでエミュレートする必要があります。これを手動で行うか、舞台裏でこれを行うイベント ライブラリを使用して、イベント ドリブン モデルの外観を提供します。LabView は 2 番目のアプローチを採用しているため、イベントが発生していないときはコードが実行されていないように見えますが、実際にはイベント キューを管理する LabView 独自の C++ コードが実行されています。これは、前に述べたように、コードが実行する作業がない場合に CPU 時間を生成するために使用できる select や sleep などのシステム コールがあるように、常に待機中であることを意味するわけではありませんが、コードは単純にはできません。実行を停止します。
2 つのイベント ハンドラを持つ「イベント ドリブン」プログラムを書きたいとしましょう。10 秒ごとに呼び出されるものは tick() と呼ばれ、キーが押されるたびに呼び出されるものは key() と呼ばれ、単語「foobar」が入力されるたびに呼び出されるものは foobar() と呼ばれます。これら 3 つのイベント ハンドラーを定義できますが、さらに、基本的に行ういくつかのディスパッチ メイン スレッドが必要です。
while not quitting
If 10 seconds have elapsed, call tick()
If Key has been Pressed
call key()
add save the key to our key buffer
If buffer now contains "foobar" call foobar() and clear buffer
Wait()
関心のあるすべてのイベントがシステム レベルのイベントまたは時間レベルのイベントである場合、Wait() は単にカーネルに「これらのいずれかが発生したときに私を起こしてください」と伝えることができるので、「ビジー待機」する必要はありません。 、しかし、「foobar が押されたときに foobar() を呼び出す」ことをカーネルに単純に指示することはできません。イベント構造をエミュレートするアプリケーション レベルのディスパッチ コードが必要です。C プログラムには、カーネルからの単一のエントリ ポイントしかありません。 Qt などのイベント ディスパッチ モデルを提供するライブラリを見ると、内部でこのように動作していることがわかります。