Читаем 1.Внутреннее устройство Windows (гл. 1-4) полностью

Ha процессорах x86 до Pentium II использовалась инструкция int 0x2e (десятичное значение 46). B результате выполнения этой инструкции срабатывает ловушка, и Windows заносит в запись IDT под номером 46 указатель на диспетчер системных сервисов (см. таблицу 3–1). Эта ловушка заставляет выполняемый поток переключиться в режим ядра и войти в диспетчер системных сервисов. Номер запрошенного системного сервиса указывается числовым аргументом, переданным в регистр процессора EAX. Содержимое регистра EBX указывает на список параметров, передаваемый системному сервису вызывающей программой.

Ha х86-процессорах Pentium II и выше Windows использует инструкцию sysenter, которую Intel специально определил для быстрой диспетчеризации системных сервисов. Для поддержки этой инструкции Windows сохраняет на этапе загрузки адрес процедуры ядра — диспетчера системных сервисов в регистре, сопоставленном с данной инструкцией. Выполнение инструкции приводит к переключению в режим ядра и запуску диспетчера системных сервисов. Номер системного сервиса передается в регистре процессора EAX, а регистр EDX указывает на список аргументов, предоставленных вызвавшим кодом. Для возврата в пользовательский режим диспетчер системных сервисов обычно выполняет инструкцию sysexit. (B некоторых случаях, например, когда в процессоре включен флаг single-step, диспетчер системных сервисов использует вместо sysexit инструкцию iretd.)

Ha 32-разрядных процессорах AMD Кб и выше Windows применяет специальную инструкцию syscall, которая функционирует аналогично х86-ин-струкции sysenter; Windows записывает в регистр процессора, связанный с инструкцией syscall, адрес диспетчера системных сервисов ядра. Номер системного вызова передается в регистре EAX, а в стеке хранятся аргументы, предоставленные вызвавшим кодом. После диспетчеризации ядро выполняет инструкцию sysret.

При загрузке 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, копирует аргументы вызвавшего кода из стека потока пользовательского режима в свой стек режима ядра (поэтому вызвавший код не может изменить значения аргументов после того, как они переданы ядру) и выполняет системный сервис. Если переданные системному сервису аргументы содержат ссылки на буферы в пользовательском пространстве, код режима ядра проверяет возможность доступа к этим буферам, прежде чем копировать в них (или из них) данные.

Перейти на страницу:

Похожие книги

1С: Управление небольшой фирмой 8.2 с нуля. 100 уроков для начинающих
1С: Управление небольшой фирмой 8.2 с нуля. 100 уроков для начинающих

Книга предоставляет полное описание приемов и методов работы с программой "1С:Управление небольшой фирмой 8.2". Показано, как автоматизировать управленческий учет всех основных операций, а также автоматизировать процессы организационного характера (маркетинг, построение кадровой политики и др.). Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, формировать разнообразные отчеты, выводить данные на печать. Материал подан в виде тематических уроков, в которых рассмотрены все основные аспекты деятельности современного предприятия. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов. Все приведенные в книге примеры и рекомендации основаны на реальных фактах и имеют практическое подтверждение.

Алексей Анатольевич Гладкий

Экономика / Программное обеспечение / Прочая компьютерная литература / Прочая справочная литература / Книги по IT / Словари и Энциклопедии