logo
Ответы_ОСиСП

40. Структура api ядра ос Windows: Kernel api, Windowing api, Messaging api. Функции ZwXxx/NtXxx в пользовательском режиме и в режиме ядра.

Ядро состоит из следующих компонентов:

Ядро ( Kernel ) работает в тесном контакте с уровнем аппаратных абстракций. Этот модуль занимается планированием действий компьютерного процессора. В случае если компьютер содержит несколько процессоров, ядро синхронизирует их работу с целью достижения максимальной производительности системы. Ядро осуществляет диспетчеризацию нитей управления ( threads ) таким образом, чтобы максимально загрузить процессоры системы и обеспечить первоочередную обработку нитей с более высоким приоритетом.

Исполняющая система ( Executive ), в состав которой входит ядро и уровень аппаратных абстракций HAL, обеспечивает общий сервис системы, который могут использовать все подсистемы среды. Каждая группа сервиса находится под управлением одной из отдельных составляющих исполняющей системы: диспетчера объектов ( Object Manager ) диспетчера виртуальной памяти ( Virtual Memory Manager ); диспетчера процессов ( Process Manager ) средства вызова локальных процедур ( Local Procedure Call Facility ); диспетчера ввода - вывода (E/O Maneger ); мониторы безопасности ( Security Reference Monitor ). Монитор безопасности совместно с процессором входа в сиситему ( Logon ) и защищёнными подсистемами реализует модель безопасности Windows NT. Верхний уровень исполняющей системы называется системным сервисом ( System Services ).

Native API для Windows NT является средством, которое реализует контролируемый вызов системных сервисов, исполняемых в режиме ядра. Этот интерфейс API является интерфейсом системных вызовов и не предназначается для непосредственного использования пользовательскими программами, кроме того, его документация ограничена. Native API предоставляется коду пользовательского режима библиотекой ntdll.dll . Библиотека ntdll.dll, имеющая точки входа в Native API для кода пользовательского режима, содержит также код загрузки модуля и запуска потока процесса. Однако большинство входов в Native API являются заглушками, которые просто передают управление режиму ядра.

Все функции прикладного уровня, вызывающие это прерывание, сосредоточены в модуле ntdll.dll и имеют в своем названии префикс Nt либо Zw , например, NtCreateFile ()/ ZwCreateFile (). Точка входа для двух таких имен одна. Вызов многих функций различных подсистем рано или поздно приведет к вызову соответствующей функции из ntdll.dll. При этом не все, что есть в ntdll.dll вызывается из подсистемы Win32.

Вызов системных сервисов возможен не только из прикладной программы, но и из ядра ОС, то есть из драйверов. Имена соответствующих функций ядра имеют префикс либо Zw , либо Nt ( ZwCreateFile (), NtCreateFile ()). Функции с префиксом Zw обращаются к сервисам посредством прерывания 2Е, тогда как функции с префиксом Nt являются собственно точками входа стандартных системных сервисов. Из этого следует, что число функций с префиксом Nt неизменно, а множество этих функций является подмножеством функций с префиксом Zw .

41. Переход из пользовательского режима в режим ядра. Таблицы описателей функций ОС Windows. Диспетчеризация вызова Kernel API и Windowing+ Messaging API. Понятие UI-потока.

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

Все функции, создающие объекты ядра, возвращают описатели, которые привязаны к конкретному процессу и могут быть использованы в любом потоке данного процесса Значение описателя представляет собой индекс в таблице описателей, принадлежащей процессу, и таким образом идентифицирует место, где хранится информация, связанная с объектом ядра. Всякий раз, когда Вы вызываете функцию, принимающую описатель объекта ядра как аргумент, Вы передаете ей значение, возвращенное одной из Create-функций. При этом функция смотрит в таблицу описателей, принадлежащую Вашему процессу, и считывает адрес нужного объекта ядра. Если Вы передаете неверный индекс (описатель), функция завершается с ошибкой и GetLastError возвращает 6 (ERROR_INVALID_HANDLE). Это связано с тем, что на самом деле описатели представляют собой индексы в таблице, их значения привязаны к конкретному процессу и недейовительны в других процессах.

Потоки пользовательского режима классифицируются в ядре как потоки, имеющие пользовательский интерфейс(UI-потоки) и не имеющие его (non UI-потоки). Non UI-поток становится UI автоматически, как только делает вызов функции Windowing или Messaging API.

UI-потоки: