Посылка асинхронных сообщений в очередь потока

Когда с потоком связывается структура THREADINFO, он получает свой набор очередей сообщений. Если процесс создает три потока и все они вызывают функцию Create Window, то и наборов очередей сообщений будет тоже три Сообщения ставятся в очередь асинхронных сообщений вызовом функции PostMessage:

BOOL PostMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

При вызове этой функции система определяет, каким потоком создано окно, иден тифицируемое параметром hwnd, Далее система выделяет блок пямяти, сохраняет в нем параметры сообщения и записывает этот блок в очередь асинхронных сообще ний данного потока. Кроме того, функция устанавливает флаг пробуждения QS_POST MESSAGE (о нем — чуть позже). Возврат из PostMessage происходит сразу после того, как сообщение поставлено в очередь, поэтому вызывающий поток остается в неведе нии, обработано ли оно процедурой соответствующего окна На самом деле вполне вероятно, что окно даже не получит это сообщение Такое возможно, если поток, создавший это окно, завершится до того, как обработает все сообщения из своей очереди.

28. Системная очередь аппаратного ввода сообщений.

При запуске система создает себе особый поток необработанного ввода (raw input thread, RIT) и системную очередь аппаратного ввода (system hardware input queue, SHIQ). RIT и SHIQ — это фундамент, на котором построена вся модель аппаратного ввода.

Обычно RIT бездействует, ожидая появления какого-нибудь элемента в SHIQ Когда пользователь нажимает и отпускает клавишу на клавиатуре или кнопку мыши, либо перемещает мышь, соответствующий драйвер устройства добавляет аппаратное событие в SHIQ Тогда RIT пробуждается, извлекает этот элемент из SHIQ, преобразует его в сообщение (WM_KEY*, WM_?BUTTON* или WM_MOUSEMOVE) и ставит в конец очереди виртуального ввода (virtualized input queue, VIQ) нужного потока. Далее RIT воз вращается в начало цикла и ждет появления следующего элемента в SHIQ RIT никогда не перестает реагировать на события аппаратного ввода — весь его код написан самой Microsoft и очень тщательно протестирован.

Как же RIT узнает, в чью очередь надо пересылать сообщения аппаратного ввода? Ну, с сообщениями от мыши все ясно: RIT просто выясняет, в каком окне находится ее курсор, и, вызвав GetWindowThreadProcessId, определяет поток, создавший это окно. Поток с данным идентификатором и получит сообщение от мыши.

В случае сообщений от клавиатуры все происходит несколько иначе. В любой момент с RIT "связан" лишь какой-то один поток, называемый активным (foreground thrcad). Именно сму принадлежит окно, с которым работает пользователь в данное время.

Когда пользователь входит в систему, процесс Windows Explorer порождает поток, который создает панель задач и рабочий стол. Этот поток привязывается к RIT. Если Вы запустите Calculator, то его поток, создавший окно, немедленно подключится к RIT После этого поток, принадлежащий Explorer, отключается от RIT, так как единовременно с RIT может быть связан только один поток. При нажатии клавиши в SHIQ появится соответствующий элемент. Это приведет к тому, что RIT пробудится, преобразует событие аппаратного ввода в сообщение от клавиатуры и поместит его в VIQ потока Calculator.

Каким образом различные потоки подключаются к RIT? Если при создании про цесса его поток создает окно, последнее автоматически появляется на переднем пла не (становится активным), и этот поток присоединяется к RIT. Кроме того, RIT отве чает за обработку особых комбинаций клавиш- Alt+Tab, AIr+Esc и Ctrl+Alt+Del. Поскольку эти комбинации клавиш RIT обрабатывает самостоятельно, пользователи могут в любой момент активизировать соответствующие окна с клавиатуры; ни одно приложение не в состоянии перехватить упомянутые комбинации клавиш Как только пользователь нажимает одну из таких комбинаций клавиш, RIT активизирует выбранное окно, и в результате его поток подключается к RIT. Кстати, в Windows есть функции, позволяющие программно активизировать окно, присоединив его поток к ШТ. Мы обсудим их несколько позже.

Посылая сообщение в окно B1 или B2, RIT помещает его в очередь виртуального ввода потока В. Обрабатывая это сообщение, поток — при синхронизации на каком-либо объекте ядра — может войти в бесконечный цикл или попасть в ситуацию взаимной блокировки. Если так и случится, он все равно останется присоединенным к RIT, и сообщения будут поступать именно в его очередь виртуального ввода

Однако пользователь, заметив, что ни окно B1, ни окно B2 не реагируют на его действия, может переключиться, например, в окно А1 нажатием клавиш Alt+Tab Поскольку RIT сам обрабатывает комбинацию клавиш Alt+Tab, переключение пройдет без всяких проблем. После активизации окна A1 к RIT будет подключен поток А. Теперь пользователь может спокойно работать с окном A1, даже несмотря на то что поток В и оба его окна зависли.

29. Работа с окнами в ОС Windows. Классы окон. Z-порядок окон. Описание окон в ОС Windows. Структуры управления окнами.

Управления окнами.

Окном в приложении, написанном в ОС Microsoft® Windows®, называется прямоугольная область экрана, где приложение отображает выходные данные и получает данные от пользователя. Окно использует экран совместно с другими окнами, включая окна других приложений. В каждый момент времени только одно окно может получать входные данные от пользователя. Пользователь может использовать мышь, клавиатуру или другое устройство ввода данных для взаимодействия с этим окном и приложением, которому оно принадлежит.
Окно - это в первую очередь средство, с помощью которого графическое приложение Win32 должно взаимодействовать с пользователем и выполнять задачи, поэтому одной из первых задач графического приложения Win32 является создание окна.

При запуске Windows автоматически создается окно рабочего стола (desktop window).

Функция GetDesktopWindow() возвращает дескриптор окна рабочего стола. Заголовок окна отображает заданный приложением значок и строку текста;

Большинство приложений содержат меню, которое представляет собой список команд, поддерживаемых приложением.

Системное меню создается и управляется Windows. Оно содержит стандартный набор пунктов, которые, будучи выбраны пользователем, устанавливают размер окна или его позицию, закрывают приложение или исполняют другие задачи.

Клиентская область - это часть окна, в которой приложение отображает выходные данные такие, как текст или графику.

Заголовок окна, меню, системное меню, кнопки свертывания и развертывания, рамка окна и полосы прокрутки все вместе считаются не клиентской областью окна (nonclient area).

Z-порядок (Z order) окна указывает позицию, которую оно занимает в стеке перекрывающихся (overlapping) окон. Этот оконный стек ориентирован вдоль мнимой оси z, направленной наружу из экрана. Окно, находящееся наверху Z-порядка, перекрывает все другие окна. Окно, находящееся внизу Z-порядка, оказывается перекрытым всеми остальными окнами.

Приоритетное окно перекрывает все другие неприоритетные окна независимо от того, является ли оно само активным. Приоритетное окно имеет стиль WS_EX_TOPMOST. Все приоритетные окна появляются в Z-порядке прежде любых неприоритетных окон. Дочерние окна группируются в Z-порядке вместе со своими родителями.

Вы можете использовать функциюBringWindowToTop(), чтобы перенести окно на вершину Z-порядка для окон того же типа. Вы также можете перестроить Z-порядок, используя функции SetWindowPos() и DeferWindowPos().

Каждое окно принадлежит какому-либо классу окна. Приложение должно зарегистрировать класс окна до создания любых окон этого класса. Класс окна определяет большинство аспектов вида и поведения окна. Главный компонент класса окна - функция окна - функция, которая получает и обрабатывает все входные данные и запросы, посланные окну. Windows поддерживает входные данные и запросы в форме сообщений.

30. Существующие форматы исполняемых файлов. Формат PE-файла. Заголовок PE-файла. Основные секции PE-файла.

Формат PE-файла.

Фирма Microsoft разработала переносимый формат файла Portable Executable для использования во всех ОС.

Эта же фирма разработала новый формат для объектных (obj) и для библиотечных (lib) файлов.

В ОС UNIX же использовался другой формат (VAX VMS).При разработке Windows NT в Microsoft перешли разработчики ОС UNIX. Они использовали привычные структуры. Форматы файлов, с которыми работали разработчики файлов, назывались COFF (Common Object File Format).

РЕ-файлы явились усовершенствованием формата COFF. Этот формат назывался переносимым, потому что все реализации Windows NT в различных системах (MIPS, Alpha, Intel и т.д.) используют один и тот же формат файла.

С вводом нового формата Microsoft использовала OMF (Object Module Format).В результате разработчики объектных и библиотечных файлов вынуждены были поставлять различные версии своих файлов.

Особенности РЕ-формата.

1. Исполняемый файл на диске и модуль, получаемый после загрузки практически идентичны. Загрузчик должен создать из файла процесс без усилий механизмом проецирования в память.

2. Использование относительного виртуального адреса (RVA – Relation Virtual Address). Многие поля в РЕ используют RVA. Смещение данного элемента по отношению к адресу, с которого начинается отображение файлов в память. Например, загрузчик Windows. Отобразим РЕ файл, начиная с адреса 400000h. Некоторая таблица начинается с адреса 40146h. Тогда RVA=1464h, то есть, чтобы перевести RVA в указатель нужно перевести RVA к базовому адресу.

3. Понятие раздела или секции. Все exe файлы Windows 95 используют плоскую модель памяти, однако в них используется условное деление на секции и разделы. Каждая секция содержит или код или данные.

Заголовок РЕ-файла.

Заголовок – это набор полей, который определяет, как будет выглядеть остальная часть файла.

Несколько сотен байт РЕ-файлов заняты под заглушку (‘This program must be run under Windows’). В DOS MZ заголовке находится указатель RVA на заголовок РЕ-файла. База данных модуля начинается с сигнатуры, с помощью которой определяется тип файла.

РЕ – Исполняемый Win32; NE – Исполняемый Win16; LE – Драйверы; LX – Исполняемый OS/2.

В базе данных модуля содержатся следующие поля:

1. Тип процессора, для которого предназначен файл;

2. Время, когда файл был создан компоновщиком (ехе) или компилятором (obj). В этом поле указывается количество секунд, прошедших с 16:00 31 декабря 1969 года.

3. Версия компоновщика, который создал данный файл в формате minor/major, то есть х.х.

4. Суммарный размер программных секций, округлённых к верхней границе. Обычно это одна секция. Верхняя граница составляет 4 Кб.

5. Общий размер всех секций, состоящий из инициализированных данных, то есть глобальные переменные и константы, начальные значения которых определены.

6. Адрес, с которого начинается выполнение программного кода.

7. RVA, с которого начинаются программные секции файла. RVA обычно равен дляехе файлов 1000h.

text

RVA

8. RVA, с которого начинается секция данных.

9. Адрес, с которого файл должен отображаться в виртуальное адресное пространство. Для Windows 95,98 это 400000h, для Windows NT/2000 – это 010000h.

10. Самая старая версия ОС, которая может использовать данный файл в формате х.х.

11. Размер заголовка РЕ-файла и таблица секций.

12. Объём виртуальной памяти, которая резервируется под начальный стек потока.

13. Количество памяти, которое изначально выделяется под стек потока.

14. Объём виртуальной памяти, резервируемый под кучу процесса по умолчанию.

15. Объём физической памяти, который выделяется под кучу и другие поля.

После заголовка идёт таблица секций. Она содержит информацию о каждой секции файла. Записи в таблице секций упорядочиваются по стартовому адресу.

Каждая запись в таблице секций состоит из следующих полей:

1. 8 байтовое имя секции в стандарте ASCII. Имена секций присваиваются обычно компилятором. Мы можем и сами создать секцию (надо уметь использовать ASM).

Пример (MS Visual C).

#pragma code_seg <имя>

#pragma data_seg <имя>

Если имя секции занимает 8 байт, то отсутствует завершающий нуль.

2. RVA, когда загрузчик должен отобразить секцию.

3. Размер секции, выровненный на ближайшую верхнюю границу размера файла. Файл делится на области, кратные 512 байт.

Наши рекомендации