Марк Руссинович - 1.Внутреннее устройство Windows (гл. 1-4)
Интересно, что поначалу Win32 не рассматривался как интерфейс программирования для Microsoft Windows NT. Поскольку проект Windows NT начинался как замена OS/2 версии 2, основным интерфейсом программирования был 32-разрядный OS/2 Presentation ManagerAPI. Однако год спустя на рынке появилась Microsoft Windows 3.0, быстро ставшая очень популярной. B результате Microsoft сменила курс и перенацелила проект Windows NT на будущую замену семейства продуктов Windows, а не OS/2. Вот на этом-то перепутье и встал вопрос о создании Windows API — до этого Windows API существовал только как 16-разрядный интерфейс.
Хотя в Windows API должно было появиться много новых функций, отсутствующих в Windows 3.1, Microsoft решила сделать новый API по возможности совместимым с именами функций, семантикой и типами данных в 16-разрядном Windows API, чтобы максимально облегчить бремя переноса существующих 16-разрядных Windows-приложений в Windows NT Поэтому тот, кто, впервые глядя на Windows API, удивляется, почему многие имена и интерфейсы функций кажутся противоречивыми, должен учитывать, что одной из причин такой противоречивости было стремление сделать Windows API совместимым со старым 16-разрядным Windows API.
Сервисы, функции и процедурыНесколько терминов в документации Windows для пользователей и программистов имеет разный смысл в разных контекстах. Например, понятие «сервис» (service) может относиться к вызываемой функции операционной системы, драйверу устройства или серверному процессу (в последнем случае сервис часто называют службой). Ниже показано, что означают подобные термины в этой книге.
• Функции Windows API Документированные, вызываемые подпрограммы в Windows API, например CreateProcess, CreateFile и GetMessage.
• Неуправляемые («родные») системные сервисы (или исполняемые системные сервисы) Недокументированные низкоуровневые сервисы операционной системы, которые можно вызывать в пользовательском режиме. Так, NtCreateProcess — это внутрисистемный сервис, вызываемый Windows-функцией CreateProcess при создании нового процесса. (Определение неуправляемых функций см. в разделе «Диспетчеризация системных сервисов» главы 3.)
• Функции (или процедуры) ядра Подпрограммы внутри операционной системы Windows, которые можно вызывать только в режиме ядра (определение мы дадим чуть позже). Например, ExAllocatePool — процедура, вызываемая драйверами устройств для выделения памяти из системных куч (динамически распределяемых областей памяти) Windows.
• Windows-сервисы Процессы, запускаемые диспетчером управления сервисами в Windows. (Хотя в документации на реестр драйверы устройств Windows определяются как сервисы, мы не пользуемся таким термином в этой книге.) Например, сервис Task Scheduler выполняется в процессе пользовательского режима, который поддерживает команду at (аналогичную UNIX-команде at или cron).
• DLL (динамически подключаемая библиотека) Набор вызываемых подпрограмм, включенных в один двоичный файл, который приложения, использующие эти подпрограммы, могут динамически загружать во время своего выполнения. B качестве примера можно привести модули Msvcrt.dll (библиотека исполняющей подсистемы C) и Kernel32.dll (одна из библиотек подсистемы Windows API). DLL активно используются компонентами и приложениями Windows пользовательского режима. Преимущество DLL над статическими библиотеками в том, что приложения могут разделять DLL-модули, a Windows гарантирует, что в памяти будет находиться лишь по одному экземпляру используемых DLL.
Процессы, потоки и заданияХотя на первый взгляд кажется, что программа и процесс — понятия практически одинаковые, они фундаментально отличаются друг от друга. Программа представляет собой статический набор команд, а процесс — это контейнер для набора ресурсов, используемых при выполнении экземпляра программы. Ha самом высоком уровне абстракции процесс в Windows включает следующее:
• закрытое виртуальное адресное пространство — диапазон адресов виртуальной памяти, которым может пользоваться процесс;
• исполняемую программу — начальный код и данные, проецируемые на виртуальное адресное пространство процесса;
• список открытых описателей (handles) различных системных ресурсов — семафоров, коммуникационных портов, файлов и других объектов, доступных всем потокам в данном процессе;
• контекст защиты (security context), называемый маркером доступа (access token) и идентифицирующий пользователя, группы безопасности и привилегии, сопоставленные с процессом;
• уникальный идентификатор процесса (во внутрисистемной терминологии называемый идентификатором клиента);
• минимум один поток.
Каждый процесс также указывает на свой родительский процесс (процесс-создатель). Однако, если родитель существует, эта информация не обновляется. Поэтому есть вероятность, что некий процесс указывает на уже несуществующего родителя. Это не создает никакой проблемы, поскольку никто не полагается на наличие такой информации. Следующий эксперимент иллюстрирует данный случай.
ЭКСПЕРИМЕНТ: просмотр дерева процессов
Большинство утилит не отображает такой уникальный атрибут, как идентификатор родительского процесса. Значение этого атрибута можно получить программно или с помощью оснастки Performance, запросив значение счетчика Creating Process ID [Код (ID) создавшего процесса]. Дерево процессов показывается утилитой Tlist.exe (из Windows Debugging Tools), если вы указываете ключ /t. Вот образец вывода этой команды:
Взаимоотношения процессов (дочерний-родительский) Tlist показывает отступами. Имена процессов, родительские процессы которых на данный момент завершились, выравниваются по левому краю, потому что установить их родственные связи невозможно — даже если процессы-прапредки еще существуют. Windows сохраняет идентификатор только родительского процесса, так что проследить его создателя нельзя. Чтобы убедиться в этом, выполните следующие операции.
1. Откройте окно командной строки.
2. Наберите start cmd для запуска второго окна командной строки.
3. Откройте диспетчер задач.
4. Переключитесь на второе окно командной строки.
5. Введите mspaint для запуска Microsoft Paint.
6. Щелкните второе окно командной строки.
7. Введите exit. (Заметьте, что окно Paint остается.)
8. Переключитесь в диспетчер задач.
9. Откройте его вкладку Applications (Приложения).
10.Щелкните правой кнопкой мыши задачу Command Prompt (Командная строка) и выберите Go To Process (Перейти к процессам).
11. Щелкните процесс Cmd.exe, выделенный серым цветом.
12. Щелкнув правой кнопкой мыши, выберите команду End Process Tree
(Завершить дерево процессов).
13. B окне Task Manager Warning (Предупреждение диспетчера задач) щелкните Yes (Да).
Первое окно командной строки исчезнет, но вы по-прежнему сможете наблюдать окно Paint, так как оно является внуком первого из завершенных процессов Command Prompt. A поскольку второй (родительский процесс Paint) тоже завершен, связь между родителем и внуком потеряна.
Для просмотра (и модификации) процессов и информации, связанной с ними, существует целый набор утилит. Следующие эксперименты демонстрируют, как получить ту или иную информацию о процессе с помощью некоторых из этих утилит. Они включаются непосредственно в саму Windows, а также в Windows Support Tools, Windows Debugging Tools, ресурсы Windows и Platform SDK. Многие из этих утилит выводят перекрывающиеся подмножества информации о базовых процессах и потоках, иногда идентифицируемые по разным именам.
Вероятно, наиболее широко применяемая утилита для анализа активности процессов — Task Manager (Диспетчер задач). (Любопытно, что в ядре Windows нет такого понятия, как задача, так что Task Manager на самом деле является инструментом для управления процессами.) Следующий эксперимент показывает разницу между тем, что Task Manager перечисляет как приложения и процессы.
ЭКСПЕРИМЕНТ: просмотр информации о процессах через диспетчер задач
Диспетчер задач Windows отображает список выполняемых в системе процессов. Его можно запустить тремя способами: 1) нажав клавиши Ctrl+Shift+Esc; 2) щелкнув панель задач правой кнопкой мыши и выбрав команду Task Manager (Диспетчер задач); 3) нажав клавиши Ctrl+Alt+Del. После запуска диспетчера задач откройте вкладку Processes (Процессы). Заметьте, что процессы идентифицируются по имени образа, экземплярами которого они являются. B отличие от некоторых объектов в Windows процессам нельзя присваивать глобальные имена. Для просмотра более подробных сведений выберите из меню View (Вид) команду Select Columns (Выбрать столбцы) и укажите, какая дополнительная информация вас интересует.
Если вкладка Processes окна диспетчера задач со всей очевидностью показывает список процессов, то содержимое вкладки Applications (Приложения) нуждается в пояснениях. Ha ней отображается список видимых окон верхнего уровня всех объектов «рабочий стол» интерактивного объекта WindowStation. (По умолчанию существуют два объекта «рабочий стол», но вы можете создать дополнительные рабочие столы через Windows-функцию CreateDesktop.) Колонка Status (Состояние) дает представление о том, находится ли поток — владелец окна в состоянии ожидания Windows-сообщения. «Running» («Выполняется») означает, что поток ожидает ввода в окно, a «Not Responding» («He отвечает») — что не ожидает (т. е. занят либо ждет завершения операции ввода-вывода или освобождения какого-либо синхронизирующего объекта).