メッセージキュー
対象プロダクト:Windows全般
カテゴリー:アーキテクチャ
メッセージキューの概要
すべての Windows アプリケーションはイベント駆動型(イベントドリブン)のプログラミングモデルが使用されています。
これは、アプリケーションがデバイスドライバや他のアプリケーション、システム自身からのメッセージを受け取り、そのメッセージに基づいて処理を実行する仕組みです。
Windows 3.1 までの OS では、すべての Windows アプリケーションは、システムを通して1つしかないメッセージキューからメッセージを取り出していました。
そのため、あるプロセスが CPU の制御を明け渡さない場合、システムはそれ以降のメッセージを配送できず、メッセージの流れが停止し、システムの停止が引き起こされていました。
この問題は Windows 3.1 がノンプリエンプティブな OS であるためだけではなく、メッセージキューが1つしかないことに起因しています。
Windows 95 では、複数のメッセージキューがサポートされています。
これにより、あるアプリケーションでハングアップが発生しても、システム全体が停止することはない事が保証されます。
32bit アプリケーションの場合、スレッドごとにプライベートなキューが作成されます。
その仕組みは、まず 32bit のプロセスを初めて実行した時に、プライマリスレッドに関連付けられたメッセージキューが1つ作成されます。
そして、別のスレッドがプロセスにより生成され、そのスレッドが初めてメッセージキューに関する呼び出しを行った時に、もう1つのキューが作成されます。
※別のスレッドが生成されたタイミングで直ちに新たなキューが作成されるわけではありません。
そのため、スレッドがメッセージキューを必要としない場合は、キューを作成する必要はないため、システムはシステムリソースを無駄に消費せずに済みます。
簡単なウインドウメッセージ処理の流れ
例えば、あるアプリケーションでマウスを左クリックした場合のウインドウメッセージの処理の流れは以下のようになります。
- マウスの左ボタンを押す
- システムがそれを検出し、該当のプログラムのスレッドのキューに WM_LBUTTONDOWN メッセージを入れる
- そのスレッドは GetMessage 関数で WM_LBUTTONDOWN メッセージを受け取る(スレッドは while ループで常に GetMessage 関数でキューにメッセージがないかをチェックしている)
- GetMessage 関数は WM_LBUTTONDOWN メッセージを MSG 構造体に格納する
- スレッドが TranslateMessage 関数と DispatchMessage 関数に MSG 構造体を渡す
- DispatchMessage 関数はシステムに該当ウインドウのウインドウプロシージャを呼び出すように通知する
- それを受けてシステムは MSG 構造体内のウインドウハンドル(hwnd)を基に、該当ウインドウのウインドウプロシージャ(WindowProc 関数)を呼び、更にウインドウプロシージャは対応する関数があればそれを呼ぶ(switch 文でメッセージ コード(uMsg)に一致する case 文を実行する)
- ウインドウプロシージャは処理結果を DispatchMessage 関数の戻り値として返す
- 再びメッセージループ (while ループ) に戻る
MSG msg = { }; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
公開日時:2011年11月20日 01:25:13