При загрузке Windows распознает тип процессора, на котором она работает, и выбирает подходящий системный код. Этот код для NtReadFile в пользовательском режиме выглядит так:
ntdll!NtReadFile:
77f5bfa8 b8b7000000 mov eax,0xb7
77f5bfad ba0003fe7f mov edx,0x7ffe0300
77f5bfb2 ffd2 call edx
77f5bfb4 c22400 ret 0x24
Номер системного сервиса — 0xb7 (183 в десятичной форме), инструкция вызова выполняет код диспетчеризации системного сервиса, установленный ядром, который в данном примере находится по адресу 0x7ffe0300. Поскольку пример взят для Pentium M, используется sysenter.
SharedUserData!SystemCallStub: 7ffe0300 8bd4 mov edx,esp
7ffe0302 0f34 sysenter
7ffe0304 сЗ ret
Диспетчеризация 64-разрядных системных сервисов
B архитектуре x64 операционная система Windows использует инструкцию syscall, которая работает аналогично инструкции syscall на процессорах AMD Кб. Windows передает номер системного вызова в регистре EAX, первые четыре параметра в других регистрах, а остальные параметры (если они есть) в стеке:
B архитектуре IA64 для тех же целей применяется инструкция epc (Enter Privileged Mode). Первые восемь аргументов системного вызова передаются в регистрах, а остальное в стеке.
Диспетчеризация системных сервисов режима ядра
Как показано на рис. 3-14, ядро использует номер системного сервиса для поиска информации о нем в таблице диспетчеризации системных сервисов (system service dispatch table). Эта таблица похожа на описанную ранее таблицу IDT и отличается от нее тем, что каждый ее элемент содержит указатель на системный сервис, а не на процедуру обработки прерывания.
ПРИМЕЧАНИЕ Номера системных сервисов могут различаться в разных сервисных пакетах (service packs) — Microsoft время от времени добавляет или удаляет некоторые системные сервисы, а их номера генерируются автоматически при компиляции ядра.
Диспетчер системных сервисов, KiSystemService, копирует аргументы вызвавшего кода из стека потока пользовательского режима в свой стек режима ядра (поэтому вызвавший код не может изменить значения аргументов после того, как они переданы ядру) и выполняет системный сервис. Если переданные системному сервису аргументы содержат ссылки на буферы в пользовательском пространстве, код режима ядра проверяет возможность доступа к этим буферам, прежде чем копировать в них (или из них) данные.
Как будет показано в главе 6, у каждого потока есть указатель на таблицу системных сервисов. Windows располагает двумя встроенными таблицами системных сервисов, но поддерживает до четырех. Диспетчер системных сервисов определяет, в какой таблице содержится запрошенный сервис, интерпретируя 2-битное поле 32-битного номера системного сервиса как указатель на таблицу. Младшие 12 битов номера системного сервиса служат индексом внутри указанной таблицы. Эти поля показаны на рис. 3-15.
Таблицы дескрипторов сервисов
Главная таблица по умолчанию, KeServiceDescriptorTable, определяет базовые сервисы исполнительной системы, реализованные в Ntoskrnl.exe. Другая таблица, KeServiceDescriptorTableShadow, включает в себя сервисы USER и GDI, реализованные в Win32k.sys — той части подсистемы Windows, которая работает в режиме ядра. Когда Windows-поток впервые вызывает сервис USER или GDI, адрес таблицы системных сервисов потока меняется на адрес таблицы, содержащей сервисы USER и GDI. Функция KeAddSystemServiceTable позволяет Win32k.sys и другим драйверам добавлять новые таблицы системных сервисов. Если в Windows 2000 установлены службы Internet Information Services (IIS), их драйвер поддержки (Spud.sys) после загрузки определяет дополнительную таблицу сервисов. Так что после этого стороннее программное обеспечение может определить только одну дополнительную таблицу. Таблица сервисов, добавляемая KeAddSystemServiceTable (кроме таблицы Win32k.sys), копируется в таблицы KeServiceDescriptorTable и KeService-DescriptorTableSbadow. Windows поддерживает добавление лишь двух таблиц системных сервисов помимо главной и таблиц Win32.
ПРИМЕЧАНИЕ Windows Server 2003 Service Pack 1 и выше не поддерживает добавление таблиц системных сервисов, если не считать те, которые включаются Win32k.sys, так что этот способ не годится для расширения функциональности этой системы.
Читать дальше
Конец ознакомительного отрывка
Купить книгу