Windows Messaging System
Windows Messaging System — это компонент операционной системы Microsoft Windows, обеспечивающий межпроцессное взаимодействие (IPC) и передачу системных уведомлений между приложениями, драйверами и ядром системы. Основой системы является очередь сообщений (message queue), которая управляется диспетчером окон (Window Manager) и обрабатывается через цикл сообщений (message loop) в каждом потоке GUI-приложений. Система сообщений лежит в основе архитектуры Win32 API и является ключевым механизмом для обработки пользовательского ввода, управления окнами, таймерами и синхронизации потоков.
История и развитие
Ранние версии Windows (1.0 — 3.x)
В Windows 1.0 (1985) система сообщений была заимствована из прототипов графической оболочки для MS-DOS. Сообщения передавались синхронно через глобальную очередь, что приводило к блокировкам приложений. В Windows 3.0 (1990) была введена кооперативная многозадачность: каждое приложение поочерёдно обрабатывало сообщения из общей очереди, а зависшее приложение могло заблокировать всю систему.
Windows 9x и NT
С выпуском Windows NT 3.1 (1993) и Windows 95 (1995) архитектура была переработана. В Windows NT система сообщений стала вытесняющей: каждое приложение имело собственную очередь сообщений, а диспетчер окон (User32.dll) обрабатывал сообщения в контексте потока, создавшего окно. В Windows 95 была реализована 32-битная версия очереди с поддержкой многопоточности, но сохранялась совместимость с 16-битными приложениями через thunking-слой.
Windows 2000 и XP
В Windows 2000 (2000) был введён механизм SendMessageTimeout, позволяющий задавать тайм-ауты для блокирующих вызовов. В Windows XP (2001) добавлена поддержка очередей сообщений для служб (SERVICE_INTERACTIVE_PROCESS) и улучшена обработка сообщений в консольных приложениях.
Windows Vista и новее
В Windows Vista (2006) была внедрена подсистема Desktop Window Manager (DWM), которая перевела рендеринг окон в графический процессор (GPU). Система сообщений осталась в ядре, но часть обработки была вынесена в DWM для анимаций и эффектов. В Windows 10 и 11 (2015–2021) добавлена поддержка универсальных приложений (UWP), использующих асинхронные сообщения через CoreDispatcher, что отличается от классической Win32-модели.
Архитектура
Компоненты
- Очередь сообщений (Message Queue) — структура данных, хранящая сообщения для каждого потока, создавшего хотя бы одно окно. Очередь управляется ядром (win32k.sys) и находится в адресном пространстве ядра.
- Диспетчер окон (Window Manager) — часть User32.dll, отвечающая за маршрутизацию сообщений от мыши, клавиатуры и других устройств к соответствующим окнам.
- Цикл сообщений (Message Loop) — программный цикл в приложении, который извлекает сообщения из очереди и передаёт их оконной процедуре (Window Procedure) через вызов DispatchMessage.
- Оконная процедура (WindowProc) — функция обратного вызова, определённая разработчиком, которая обрабатывает конкретные сообщения (например, WM_PAINT, WM_DESTROY).
Типы сообщений
Сообщения классифицируются по источнику и назначению:
| Тип | Описание | Примеры |
|---|---|---|
| Системные | Генерируются ядром или диспетчером окон | WM_TIMER (таймер), WM_PAINT (перерисовка), WM_QUIT (завершение) |
| Пользовательские | Отправляются приложениями через SendMessage или PostMessage | WM_USER + N (пользовательские коды) |
| Аппаратные | Возникают при вводе с устройств | WM_KEYDOWN (клавиша нажата), WM_MOUSEMOVE (движение мыши) |
| Широковещательные | Рассылаются всем окнам верхнего уровня | WM_SETTINGCHANGE (изменение системных настроек) |
Механизмы доставки
- PostMessage — помещает сообщение в очередь потока-получателя и возвращает управление немедленно. Используется для асинхронной передачи.
- SendMessage — блокирует поток-отправитель до тех пор, пока поток-получатель не обработает сообщение. Может вызывать взаимоблокировки (deadlocks) при неправильном использовании.
- SendMessageCallback — асинхронная версия SendMessage, вызывающая функцию обратного вызова после обработки.
- SendNotifyMessage — отправляет сообщение и возвращает управление, не дожидаясь обработки, если поток-получатель принадлежит тому же процессу.
Применение
Обработка пользовательского ввода
Система сообщений преобразует аппаратные события (нажатия клавиш, движения мыши) в сообщения, которые направляются в фокусное окно. Например, при нажатии клавиши «A» генерируется последовательность WM_KEYDOWN, WM_CHAR, WM_KEYUP. Это позволяет приложениям реагировать на ввод без прямого доступа к драйверам устройств.
Управление окнами
Сообщения WM_CREATE, WM_SIZE, WM_MOVE, WM_CLOSE управляют жизненным циклом окна. При изменении размеров окна система автоматически отправляет WM_SIZE, что позволяет приложению перераспределять ресурсы (например, буферы DirectX).
Таймеры и асинхронные операции
WM_TIMER генерируется через заданные интервалы (от 10 мс до нескольких секунд). Используется для анимаций, автосохранения или опроса состояния. В современных приложениях WM_TIMER часто заменяется на SetWaitableTimer или таймеры из библиотеки .NET.
Межпроцессное взаимодействие
Через SendMessage и PostMessage приложения могут обмениваться данными, если окна принадлежат разным процессам, но выполняются на одном рабочем столе. Для этого используется механизм message-only windows (окна, невидимые пользователю). Однако для IPC между разными сессиями или удалёнными системами применяются более надёжные средства (каналы, сокеты, COM).
Ограничения и критика
Производительность
Классическая система сообщений плохо масштабируется на многопоточные приложения: каждое сообщение требует переключения контекста и синхронизации с очередью. При большом количестве окон (например, в браузерах с сотнями вкладок) нагрузка на диспетчер окон возрастает, что может приводить к задержкам ввода. В Windows 10 и 11 для UWP-приложений используется асинхронный CoreDispatcher, который обрабатывает сообщения в пуле потоков, а не в одном цикле.
Безопасность
Сообщения могут быть перехвачены или подделаны с помощью SetWindowsHookEx или SendMessage из другого процесса. Это использовалось для внедрения кейлоггеров и манипуляции интерфейсом. Начиная с Windows Vista, для защиты от таких атак введён UIPI (User Interface Privilege Isolation): процессы с более низким уровнем целостности не могут отправлять сообщения процессам с более высоким уровнем (например, SendMessage из приложения с уровнем «средний» в окно с уровнем «высокий» блокируется).
Устаревание модели
С развитием веб-технологий и фреймворков (Electron, React Native) классическая Win32-система сообщений используется реже. Современные приложения часто работают в изолированных средах (песочницы UWP, контейнеры), где IPC реализован через AppContainer и API-мосты, а не через оконные сообщения. Однако для системных утилит, драйверов и legacy-программ Windows Messaging System остаётся обязательным компонентом.
Интересные факты
- Максимальный размер очереди сообщений для одного потока — 10 000 сообщений (ограничение введено в Windows 2000 для предотвращения переполнения памяти).
- Сообщение WM_NULL (0x0000) не выполняет никаких действий и используется для проверки работоспособности окна или для синхронизации.
- В Windows 3.x существовало сообщение WM_DROPFILES для перетаскивания файлов, которое в Windows 95 было заменено на OLE Drag and Drop, но WM_DROPFILES остаётся совместимым.
- В Windows 11 сообщение WM_DPICHANGED обрабатывается автоматически для адаптации интерфейса под разные масштабы дисплея.
Источники
- Microsoft Docs: «About Messages and Message Queues» (Win32 API documentation).
- Petzold, Charles. «Programming Windows» (5th edition, Microsoft Press, 1998).
- Russinovich, Mark; Solomon, David; Ionescu, Alex. «Windows Internals» (7th edition, Part 1, Microsoft Press, 2017).
- MSDN Magazine: «The Windows Message Loop: A Primer» (2006).
- Chen, Raymond. «The Old New Thing» (blog, Microsoft, 2003–2023).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →