Поскольку практическая часть данного курса предполагает разработку и выполнение разнообразных Win32-приложений, которые работают в среде, создаваемой Win32-подсистемой, необходимо рассмотреть ее более подробно. Взаимодействие между приложением и операционной системой осуществляется при помощи системных вызовов (системных сервисов в терминологии Microsoft). Однако приложение не может вызвать системный вызов напрямую (более того, системные вызовы не документированы). Вместо этого приложение должно воспользоваться программным интерфейсом ОС - Win32 API.
Win32 API (Application Programming Interface) - основной интерфейс программирования в семействе операционных систем Microsoft Windows. Функции Win32 API , например, CreateProcess или CreateFile, - документированные, вызываемые подпрограммы, реализуемые Win32 подсистемой.
В состав Win32 подсистемы (см. рис. 1.4) входят: cерверный процесс подсистемы окружения csrss.exe, драйвер режима ядра Win32k.sys, dll - модули подсистем (kernel32.dll, advapi32.dll, user32.dll и gdi32.dll), экспортирующие Win32-функции и драйверы графических устройств. В процессе эволюции структура подсистемы претерпела изменения. Например, функции окон и рисования с целью повышения производительности были перенесены из серверного процесса, работающего в режиме пользователя, в драйвер режима ядра Win32k.sys. Однако это и подобные изменения никак не отразились на работоспособности приложений, поскольку существующие вызовы Win32 API не изменяются с новыми выпусками системы Windows, хотя их состав постоянно пополняется.
Приложение, ориентированное на использование Win32 API, может работать практически на всех версиях Windows, несмотря на то, что сами системные вызовы в различных системах различны (см. рис. 1.5). Таким путем корпорация Microsoft обеспечивает преемственность своих операционных систем.
При запуске процесса все требуемые динамические библиотеки отображаются на его виртуальное адресное пространство, а для быстрого вызова библиотечной процедуры используется специальный вектор передачи.
При вызове приложением одной из Win32-функций dll-подсистем может возникнуть одна из трех ситуаций (см. рис. 1.6).
Функция полностью выполняется внутри данной dll (шаг 1). Для выполнения функции привлекается сервер csrss, для чего ему посылается сообщение (шаг 2a, за которым обычно следуют шаги 2b и 2c). Данный вызов транслируется в системный сервис (системный вызов), который обычно обрабатывается в модуле ntdll.dll (шаги 3a и 3b). Например, Win32-функция ReadFile выполняется с помощью недокументированного сервиса NtReadFile. Некоторые функции (например, CreateProcess ) требуют выполнения обоих последних пунктов.
В первых версиях ОС Windows практически все вызовы Win32 API выполнялись, следуя маршруту 2 (2a, 2b, 2c). После того, как существенная часть кода системы для увеличения производительности была перенесена в ядро (начиная с Windows NT 4.0), вызовы Win32 API, как правило, идут напрямую по 3-му (3a, 3b) пути, минуя подсистему окружения Win32. В настоящее время лишь небольшое число вызовов выполняется по длинному 2-му маршруту.
Помимо перечисленных, наиболее важных dll-библиотек, в системном каталоге system32 имеется большое количество других dll-файлов. В настоящее время количество вызовов API составляет несколько десятков тысяч.
Список экспортируемых каждой конкретной dll функций можно посмотреть с помощью утилиты depends, входящей в пакет Platform SDK. Так, на рис. 1.7 приведена информация о структуре библиотеки kernel32.dll ОС Windows XP, экспортирующей 949 функций.