このエントリーをはてなブックマークに追加

メッセージキュー

対象プロダクト:Windows全般
カテゴリー:アーキテクチャ

メッセージキューの概要

すべての Windows アプリケーションはイベント駆動型(イベントドリブン)のプログラミングモデルが使用されています。
これは、アプリケーションがデバイスドライバや他のアプリケーション、システム自身からのメッセージを受け取り、そのメッセージに基づいて処理を実行する仕組みです。

Windows 3.1 までの OS では、すべての Windows アプリケーションは、システムを通して1つしかないメッセージキューからメッセージを取り出していました。
そのため、あるプロセスが CPU の制御を明け渡さない場合、システムはそれ以降のメッセージを配送できず、メッセージの流れが停止し、システムの停止が引き起こされていました。
この問題は Windows 3.1 がノンプリエンプティブな OS であるためだけではなく、メッセージキューが1つしかないことに起因しています。

Windows 95 では、複数のメッセージキューがサポートされています。
これにより、あるアプリケーションでハングアップが発生しても、システム全体が停止することはない事が保証されます。

32bit アプリケーションの場合、スレッドごとにプライベートなキューが作成されます。
その仕組みは、まず 32bit のプロセスを初めて実行した時に、プライマリスレッドに関連付けられたメッセージキューが1つ作成されます。
そして、別のスレッドがプロセスにより生成され、そのスレッドが初めてメッセージキューに関する呼び出しを行った時に、もう1つのキューが作成されます。
※別のスレッドが生成されたタイミングで直ちに新たなキューが作成されるわけではありません。
そのため、スレッドがメッセージキューを必要としない場合は、キューを作成する必要はないため、システムはシステムリソースを無駄に消費せずに済みます。

簡単なウインドウメッセージ処理の流れ

例えば、あるアプリケーションでマウスを左クリックした場合のウインドウメッセージの処理の流れは以下のようになります。
  1. マウスの左ボタンを押す
  2. システムがそれを検出し、該当のプログラムのスレッドのキューに WM_LBUTTONDOWN メッセージを入れる
  3. そのスレッドは GetMessage 関数で WM_LBUTTONDOWN メッセージを受け取る(スレッドは while ループで常に GetMessage 関数でキューにメッセージがないかをチェックしている)
  4. GetMessage 関数は WM_LBUTTONDOWN メッセージを MSG 構造体に格納する
  5. スレッドが TranslateMessage 関数と DispatchMessage 関数に MSG 構造体を渡す
  6. DispatchMessage 関数はシステムに該当ウインドウのウインドウプロシージャを呼び出すように通知する
  7. それを受けてシステムは MSG 構造体内のウインドウハンドル(hwnd)を基に、該当ウインドウのウインドウプロシージャ(WindowProc 関数)を呼び、更にウインドウプロシージャは対応する関数があればそれを呼ぶ(switch 文でメッセージ コード(uMsg)に一致する case 文を実行する)
  8. ウインドウプロシージャは処理結果を DispatchMessage 関数の戻り値として返す
  9. 再びメッセージループ (while ループ) に戻る
具体的にはこのメッセージループのコードは以下のようになります

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

公開日時: 2011年11月20日  01:25:13

このエントリーをはてなブックマークに追加
仮想マシン(VM)と仮想マシンマネージャ(VMM) | Windowsサブシステム(User、Kernel、GDI)とサンクレイヤ

Windows技術情報の一覧に戻る

「アーキテクチャ」に関する他の技術情報
技術情報のカテゴリ

このページのトップに戻る