Объект ядра ос windows это структура данных в памяти доступная только

Обновлено: 02.07.2024

Объекты ядра Windows используются системой и приложениями для управления самыми разнообразными ресурсами, например, процессами, потоками, файлами и др.

Каждый объект ядра – блок памяти, выделяемый ядром и доступном только ему. Блок этот – структура данных, содержащих информацию об объекте. Некоторые элементы этой структуры (например, дескриптор защиты, счетчик числа пользователей и другое) присутствуют во всех объектах, но большинство специфично для объектов конкретного типа.

Приложение не имеет прямого доступа к объектам ядра, для этого существуют специальные функции Windows. Доступ к объектам ядра программа может получить только через эти функции. Каждая функция, создающая объект ядра, возвращает хэндл созданного объекта (в русскоязычной литературе используется также слово «описатель»). Хэндл - это всего лишь некое значение, уникально идентифицирующее объект ядра в пределах данного процесса. Следует заметить, что значения описателей зависят от конкретного процесса. То есть, если с помощью какого-либо способа Вы передадите значение хэндла потоку другого процесса, то использование этого значения во втором процессе приведет к ошибке.

Объекты принадлежат не процессу, а ядру. Другими словами, если процесс создает какой-либо объект ядра, а затем завершается, то объект может быть и не разрушен. Чаще всего, конечно, объект разрушается, но если этим объектом пользуется другой процесс, ядро не даст его разрушить до тех пор, пока второй процесс не откажется от него. Это происходит потому как в каждом объекте ядра существует счетчик пользователей этого объекта. Когда объект только создается, этот счетчик равняется единице. Когда к этому объекты обращается другой процесс, счетчик увеличивается на 1, а когда процесс завершается, счетчики всех используемых им объектов ядра уменьшаются на 1. Как только счетчик пользователей объекта ядра становится равным нулю, ядро разрушает этот объект.

Объекты ядра можно защитить с помощью дескриптора защиты. Он описывает, кто создал процесс, и кто имеет доступ к нему. Почти все функции создания объекта ядра принимают указатель на структуру SECURITY_ATTRIBUTES.

В большинстве случаев, вместо этого параметра можно передать NULL, тогда объект создается с защитой по умолчанию. Такая защита подразумевает, что создатель объекта и любой член группы администраторов получают полный доступ к объекту, а остальные пользователи к нему не допускаются. Однако можно инициализировать и передать структуру SECURITY_ATTRIBUTES, а затем передать ее адрес. Собственно, структура:

Лишь один элемент этой структуры касается непосредственно защиты объекта ядра – lpSecurityDescriptor. Если нужно ограничить доступ к создаваемому объекту, то инициализируйте эту структуру примерно так:

При инициализации процесса система создает в нем таблицу хэндлов, используемую только для объектов ядра. Официально эта таблица недокументирована, но Джеффри Рихтер в своей книге «Создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows» в общих чертах ее описывает, однако, предупреждая при этом, что реализация этой таблицы сильно различается в разных версиях Windows. Таблица представляет собой массив структур данных. Каждая структура содержит указатель на объект ядра, маску доступа и некоторые флаги.

Когда процесс инициализируется в первый раз, таблица его хэндлов еще пуста. Как только процесс вызывает функцию, создающую объект ядра, ядро выделяет для этого объекта область памяти и инициализирует его. Далее ядро посматривает таблицу хэндлов создающего процесса и находит свободную запись. Указатель устанавливается на внутренний адрес структуры данных объекта, соответствующим же образом устанавливаются маска доступа и флаги.

Как было сказано ранее, все функции, создающие объекты ядра, возвращают хэндл новосозданного объекта, который привязан к конкретному процессу и может быть использован в дочерних потоках данного процесса. Значение хэндла представляет собой индекс в таблице хэндлов данного процесса, и таким образом определяет место, где хранится информация об объекте ядра. Нужно помнить, что реальное содержание этих хэндлов недокументировано и может быть изменено в следующей версии Windows.

Если вызов функции, создающей объект ядра, оказывается неудачен, то обычно возвращается 0 (NULL). Такая ситуация возможна при острой нехватке памяти, при наличии проблем с защитой и других ситуаций. К сожалению, отдельные функции возвращают в таких случаях не 0, а -1 (INVALID_HANDLE_VALUE) Например, если CreateFile() не сможет открыть указанный файл, она вернет именно INVALID_HANDLE_VALUE. Будьте очень осторожны при проверке значения, возвращаемого функцией, которая создает объект ядра. Так, для CreateMutex() проверка на INVALID_HANDlE_VALUE бессмысленна:

Точно так же бессмыслен и следующий код:

Всякий раз, когда Вы вызываете функцию, принимающую хэндл объекта ядра как аргумент, Вы передаете ей значение, переданное одной из Create-функций. При этом функция смотрит в таблицу хэндлов, принадлежащую вызывающему процессу, и считывает адрес нужного объекта ядра.

Если Вы передаете неверный индекс (хэндл), то функция завершается с ошибкой и GetLastError() вернет ERROR_INVALID_HANDLE (6).

Вне зависимости от того, как объект ядра был создан, то по окончанию работы с ним, хэндл нужно закрыть. Для этого существует функция CloseHandle():

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

Перед самым возвратом управления CloseHandle() удаляет соответствующую запись из таблицы хэндлов: данный хэндл теперь недействителен в создавшем объект процессе, и использовать его нельзя. При этом запись удаляется независимо от того, разрушен объект ядра или нет. После вызова CloseHandle() невозможно больше получить доступ к этому объекту ядра; но, если его счетчик не обнулен, объект остается в памяти. Тут все нормально, это означает лишь то, что объект используется другим процессом (или процессами). Когда и остальные процессы завершат свою работу с этим объектом (тоже вызвав CloseHandle()), он будет разрушен.

Стоит заметить, что не все хэндлы закрываются функцией CloseHandle(). Существуют особые хэндлы, создаваемые функцией FindFirstFile(), для их закрытия служит функция CloseFind().

А вдруг Вы забыли вызвать CloseHandle() - будет ли утечка памяти? И да, и нет. Утечка ресурсов (тех же объектов ядра) вполне вероятна, пока процесс еще исполняется. Однако по завершении процесса операционная система гарантированно освобождает все ресурсы, принадлежавшие этому процессу, и в случае объектов ядра действует так: в момент завершения процесса просматривает его таблицу описателей и закрывает любые открытые описатели.

Каждый объект ядра - это блок памяти, выделенный ядром ОС и доступный только ядру ОС.
Этот блок памяти представляет собой структуру данных, члены которой хранят информацию об объекте (дескриптор безопасности, счетчик использования и т.д.).
Некоторые члены этих структур одинаковы для всех типов объектов, но большинство относятся к конкретному типу объекта.
Например, объект процесса имеет идентификатор процесса, базовый приоритет и код выхода, тогда как объект файла имеет байтовое смещение, режим sharing mode и режим open mode.
Поскольку структуры данных объекта ядра доступны только ядру ОС, приложение не может найти эти структуры данных в памяти и напрямую изменить их содержимое.
Windows API предлагает набор функций, которые документированными способами взаимодействуют с этими структурами.
Когда используется функция, которая создает объект ядра, она возвращает дескриптор, который идентифицирует объект.
Передавая этот дескриптор различным функциям Windows, система точно знает с каким объектом ядра необходимо взаимодействовать.

Объекты ядра принадлежат ядру ОС, а не процессу.
Процесс вызывает функцию, которая создает объект ядра. Если процесс завершается, объект ядра не обязательно уничтожается.
Если другой процесс использует данный объект ядра, ОС ​​знает, что нельзя уничтожать этот объект, пока другой процесс не перестанет его использовать.
Для этого в ОС предусмотрен счетчик использования. Когда объект ядра создается впервые, его счетчик использования устанавливается на 1.
Затем, когда другой процесс получает доступ к существующему объекту ядра, счетчик использования увеличивается на единицу.
Когда процесс завершается, ядро ОС ​​автоматически уменьшает счетчик использования для всех объектов ядра на единицу.
Если счетчик использования объекта становится равным 0, ядро ОС ​​уничтожает объект.

Дескриптор безопасности (Security Descriptor).
Объекты ядра могут быть защищены дескриптором безопасности.
Почти все функции, которые создают объекты ядра, имеют указатель на структуру SECURITY_ATTRIBUTES в качестве аргумента.
Именно этим и отличается Kernel object от других категорий (ни у User object, ни у GDI object нет дескрипторов безопасности).

Более подробно что из себя представляет дескриптор безопасности рассмотрим на примере функции CreateProcess

Большинство приложений просто передают NULL для этого аргумента, поэтому объект ядра создается с безопасностью по умолчанию.
Безопасность по умолчанию означает, что любой пользователь группы администраторов и создатель объекта ядра имеют определённый доступ к создаваемому объекту, всем остальным доступ запрещен.
Структура SECURITY_ATTRIBUTES описывается следующим образом
Несмотря на то, что эта структура называется SECURITY_ATTRIBUTES, на самом деле она включает только один член, имеющий какое-либо отношение к безопасности: lpSecurityDescriptor.
Если требуется ограничить доступ к создаваемому объекту ядра, необходимо создать дескриптор безопасности, а затем инициализировать структуру SECURITY_ATTRIBUTES следующим образом:

*PSECURITY_DESCRIPTOR в данном случае определен как LPVOID, не путайте со структурой PISECURITY_DESCRIPTOR

Существуют два способа получить инициализированный Security Descriptor:
- наследовать уже созданный дескриптор безопасности другим процессом
- сформировать специальную строку типа SDDL (Security Descriptor Definition Language) и конвертировать её в указатель с помощью функции ConvertStringSecurityDescriptorToSecurityDescriptor

Первое на что необходимо обратить внимание - это на двоеточие, оно служит разделением для групп

Список SID строк можно расшифровать на сайте MSDN
Таким образом
O:BA - владелец (Owner) данного дескриптора безопасности является SDDL_BUILTIN_ADMINISTRATORS (DOMAIN_ALIAS_RID_ADMINS)
G:BA - группа (Group), в которую входит дескриптор безопасности, также является SDDL_BUILTIN_ADMINISTRATORS (DOMAIN_ALIAS_RID_ADMINS)

Список управления доступом на уровне пользователя DACL (Discretionary Access Control List)
D:(A;;CCDCLCSWRP;;;SY)(A;;CCDCLCSWRP;;;BA)(A;;CCDCLCSWRP;;;I U)(A;;CCDCLCSWRP;;;LS)(A;;0xb;;;AC)

И системный список управления доступом SACL (System Access Control List)
S:(ML;;NX;;;LW)

Синтаксис SDDL строк для DACL и SACL имеет следующий вид

Список ACE строк можно расшифровать на сайте MSDN

Следовательно для первой части DACL получается следующая расшифровка (данный DACL относится к группе Directory service object):
A - SDDL_ACCESS_ALLOWED (флаг ACCESS_ALLOWED_ACE_TYPE)
CC - SDDL_CREATE_CHILD (флаг ADS_RIGHT_DS_CREATE_CHILD)
DC - SDDL_DELETE_CHILD (флаг ADS_RIGHT_DS_DELETE_CHILD)
LC - SDDL_LIST_CHILDREN (флаг ADS_RIGHT_ACTRL_DS_LIST)
SW - SDDL_SELF_WRITE (флаг ADS_RIGHT_DS_SELF)
RP - SDDL_READ_PROPERTY (флаг ADS_RIGHT_DS_READ_PROP)
SY - SDDL_LOCAL_SYSTEM (SECURITY_LOCAL_SYSTEM_RID)

и для SACL
ML - SDDL_MANDATORY_LABEL (флаг SYSTEM_MANDATORY_LABEL_ACE_TYPE)
NX - SDDL_NO_EXECUTE_UP (флаг SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP)
LW - Low Mandatory Level (SID S-1-16-4096)

Моя программа KernelExplorer (её консольная версия) выводит всю возможную информацию об ACL

По мере нахождения новых комбинаций ACE флагов я обновляю код, поэтому возможно заместо текстового представления флагов будет отображаться его цифровое представление.
*В данный момент занят адаптацией информации о ACL для GUI версии.

Таблица дескрипторов объекта ядра процесса.
В первой части я вскользь упомянул, что каждый дескриптор имеет записи во внутренней таблице, которые содержат адреса ресурсов и средства идентификации типа ресурса.
Когда процесс инициализируется, система выделяет для него таблицу дескрипторов.
Эта таблица дескрипторов используется только для объектов ядра, User object или GDI object не имеют доступа к ней.
Подробности того, как структурирована и управляется таблица дескрипторов не документированы.
Но при этом, структуру таблицы дескрипторов процесса схематично можно представить следующим образом

Каждая структура содержит указатель на объект ядра, маску доступа и набор флагов.
При первой инициализации процесса его таблица дескрипторов пуста.
Затем, когда поток в процессе вызывает функцию, которая создает объект ядра, ядро ОС выделяет блок памяти для объекта и инициализирует его.
Ядро ОС сканирует таблицу дескрипторов процесса на наличие пустой записи.
Для указателя будет установлен адрес внутренней памяти структуры данных объекта ядра.
Для маски доступа будет установлен гарантированный доступ (granted access).
Набор флагов соответственно устанавливается из переданного Security Descriptor, а в случае NULL - устанавливается безопасность по умолчанию.

Все функции, создающие объекты ядра, возвращают относительные к процессу дескрипторы.
Это значение дескриптора является индексом в таблице дескрипторов процесса, который определяет, где хранится информация об объекте ядра.
Когда вызывается функция, которая принимает дескриптор объекта ядра в качестве аргумента, происходит передача значения.
Внутри функция просматривает таблицу дескрипторов процесса, чтобы получить адрес объекта ядра, с которым необходимо взаимодействовать.

Пулы памяти.
Выгружаемый и невыгружаемый пулы служат ресурсами памяти, которые ОС использует для хранения своих структур данных.
Невыгружаемый пул (Non-paged pool) - используется операционной системой для хранения данных.
Ядро ОС взаимодействует с невыгружаемым пулом когда выполняются подпрограммы обслуживания прерываний (ISR) и отложенные вызовы процедур (DPC), которые являются функциями, связанными с прерываниями.
Примерами могут служить такие системные прерывания, как переключение режима UserMode в KernelMode - syscall либо sysenter (в Windows XP данное прерывание обозначалось int 2e и в ntdll.dll сохранилось в качестве совместимости с более старым ПО).
Невыгружаемый пул расположен только в физической памяти, а виртуальной памяти невыгружаемого пула назначается физическая память.
Общие системные структуры данных, хранящиеся в невыгружаемом пуле, включают ядро ОС ​​и объекты ядра, которые представляют процессы, потоки, мьютексы, семафоры, события, файловые объекты, IRP и др.
Выгружаемый пул (Paged pool) - буфер памяти операционной системы, куда записываются данные файла подкачки, позволяя переориентировать физическую память.
Когда ОС обращается к памяти выгружаемого пула, которая находится в файле подкачки, происходит системное исключение Page fault, и затем диспетчер памяти считывает данные обратно в физическую память.
Из всех объектов ядра реестр (Registry) является основным программным средством, использующим выгружаемый пул.

Важно понимать, что к физической памяти из пользовательского режима доступа нет.
Также как системные потоки не имеют адресного пространства пользовательского режима.
Физической памятью оперирует только ядро ОС, пользователю для этого отведено виртуальное адресное пространство.
Взаимодействие виртуального адресного пространства с физической памятью осуществляется пулами и кучами (Heap) и только функциями ядра ОС.
Поэтому, выделяя память какой-нибудь VirtualAlloc (или любой другой аналогичной функцией), вы даже близко не находитесь к оперативной памяти, физически установленной в компьютере.

Для работы с важными системными ресурсами ОС Windows создает объекты, управление которыми осуществляет менеджер объектов. Когда приложение открывает файл , создает поток или семафор, оно получает описатель ( handle ) соответствующего объекта (см. рис. 4.1). Например, после выполнения программного оператора

создающего семафор, возвращаемый описатель hSemaphore необходим приложению для последующей работы с этим семафором.

Создание объекта

В данном разделе дается краткое описание того, как функционирует менеджер объектов. С объектами придется сталкиваться на протяжении всего курса. Объекты - абстрактная концепция, которая активно используется в ОС Windows для регулирования доступа к системным ресурсам.

Наличие объектов является несомненным достоинством системы. Во-первых, это единый интерфейс ко всем системным ресурсам и структурам данных, таким, как процессы, потоки, семафоры и т.д. Именование объектов и доступ к ним осуществляются по одной и той же схеме. Использование объектов дает Microsoft возможность обновлять функциональность системы, не затрагивая программного интерфейса приложений. Во-вторых, это очень удобно с точки зрения системной безопасности. Каждый объект имеет список прав доступа, который проверятся каждый раз, когда приложение создает свой описатель объекта. Соответственно, все проверки, связанные с защитой, могут быть выполнены в одном модуле - диспетчере объектов (в соответствии с требованиями безопасности), с гарантией, что ни один процесс не может их обойти. Наконец, легко организовать совместный доступ к объектам, несложно отследить объекты, которые больше не используются, и т.д.

Объекты присутствуют почти во всех компонентах системы, особенно там, где есть данные, которые нужно разделять, защищать, именовать или сделать доступными. Например, посредством объектов реализованы программные и аппаратные прерывания, а также многие другие функции ядра. Некоторые объекты доступны пользовательским приложениям через вызовы Win32. Поэтому иногда ОС Windows называют объектно-ориентированной системой, - так, доступ к ресурсу возможен только через методы соответствующего объекта ( инкапсуляция данных ). Вместе с тем в данной схеме отсутствуют наследование и полиморфизм , поэтому ОС Windows нельзя считать объектно-ориентированной в строгом смысле этого слова.

Объекты ядра

В рамках данного курса нам придется активно использовать объекты, называемые в руководствах по Win32-программированию объектами ядра ( kernel objects). Поддержка объектов ядра осуществляется собственно ядром и исполнительной системой. Помимо объектов ядра имеются также объекты, предназначенные для управления окнами ( User ), и объекты, предназначенные для управления графикой ( GDI ). Изучение этих категорий объектов, реализуемых подсистемой поддержки окон и графики и ориентированных на разработку графических интерфейсов пользователя, выходит за пределы данного курса.

К сожалению, понятие " объект ядра" имеет разный смысл у разных авторов (ср., например, это понятие в MSDN или в [ Рихтер ] , c одной стороны, и в [ Руссинович ] - с другой), поэтому для дальнейшего изложения потребуется уточнение терминологии.

Дело в том, что совокупность объектов образует слоеную структуру. Ядро поддерживает базовые объекты двух видов: объекты диспетчера (события, мьютексы , семафоры, потоки ядра, таймеры и др.) и управляющие ( DPC , APC , прерывания, процессы, профили и др.) Более подробно эти внутриядерные объекты описаны в [ Руссинович ] .

Над объектами ядра находятся объекты исполнительной системы, каждый из которых инкапсулирует один или более объектов ядра. Объекты исполнительной системы предназначены для управления памятью, процессами и межпроцессным обменом. Они экспортируются в распоряжение пользовательских приложений через Win32 функции. К ним относятся такие объекты, как: процесс, поток , открытый файл , семафор, мьютекс , маркер доступа и ряд других. Полный список можно увидеть в MSDN . Эти объекты и называются объектами ядра в руководствах по программированию.

Внешнее отличие объектов ядра (объектов исполнительной системы) от объектов User и GDI состоит в наличии у первых атрибутов защиты, которые являются одним из параметров, создающих объект ядра функций. Далее эти объекты ядра (объекты исполнительной системы) будут называться просто объектами.

Объект представляет собой блок памяти в виртуальном адресном пространстве ядра. Этот блок содержит информацию об объекте в виде структуры данных (см. ниже "структура объекта"). Структура содержит как общие, так и специфичные для каждого объекта элементы. Объекты создаются в процессе загрузки и функционирования ОС и теряются при перезагрузке и выключении питания.

Содержимое объектов доступно только ядру, приложение не может модифицировать его непосредственно. Доступ к объектам можно осуществить только через его функции-методы ( инкапсуляция данных ), которые инициируются вызовами некоторых библиотечных Win32-функций.

Структура объекта. Методы объекта

Структура объекта

Как показано на рис. 4.2, каждый объект имеет заголовок с информацией, общей для всех объектов, а также данные, специфичные для объекта. Например, в поле заголовка имеется список процессов, открывших данный объект , и информация о защите, определяющая, кто и как может использовать объект .

Счетчик ссылок на объект увеличивается на 1 при открытии объекта и уменьшается на 1 при его закрытии. Значение счетчика ссылок, равное нулю, означает, что объект больше не используется и выделенное ему адресное пространство ядра может быть освобождено. Наличие счетчика означает, что даже после завершения процесса, создавшего объект , этот объект может не быть разрушен (если его счетчик не обнулен).

Квота устанавливает ограничения на объемы ресурсов. Несмотря на то, что в ОС Windows реализован код для отслеживания квот, в настоящее время квоты не применяются и существуют достаточно мягкие ограничения. Например, по умолчанию лимит на открытые объекты для процесса - 230. Множество объектов делится на типы, а у каждого из объектов есть атрибуты, неизменные для объектов данного типа. Ссылка на тип объекта также входит в состав заголовка. Поля имя объекта и каталог будут описаны в разделе "именование объектов".

Методы объекта

В состав компонентов объекта типа входит атрибут методы - указатели на внутренние процедуры для выполнения стандартных операций. Методы вызываются диспетчером объектов при создании и уничтожении объекта, открытии и закрытии описателя объекта, изменении параметров защиты. Система позволяет динамически создавать новые типы объектов. В этом случае предполагается регистрация его методов у диспетчера объектов. Например, метод open вызывается всякий раз, когда создается или открывается объект и создается его новый описатель.

Описатели объектов

Создание новых объектов, или открытие по имени уже существующих, приложение может осуществить при помощи Win32-функций, таких, как CreateFile, CreateSemaphore, OpenSemaphore и т.д. Это библиотечные процедуры, за которыми стоят сервисы Windows и методы объектов. В случае успешного выполнения создается 64-битный описатель в таблице описателей процесса в памяти ядра. На эту таблицу есть ссылка из блока управления процессом EPROCESS (см. "Реализация процессов и потоков" ).

Из 64-х разрядов описателя 29 разрядов используются для ссылки на блок памяти объекта ядра, 3 - для флагов, а оставшиеся 32 - в качестве маски прав доступа. Маска прав доступа формируется на этапе создания или открытия объекта, когда выполняется проверка разрешений. Таким образом, описатель объекта - принадлежность процесса, создавшего этот объект . По умолчанию он не может быть передан другому процессу. Тем не менее, система предоставляет возможность дублирования описателя и передачи его другому процессу специальным образом (см. ниже раздел "Совместное использование объектов" и часть IV " Безопасность ").

Объекты и их описатели

Win32-функции, создающие объект , возвращают приложению не сам описатель, а индекс в таблице описателей, то есть малое число: типа 1,2 а не 64-разрядное (см. рис. 4.3). Впоследствии это значение передается одной из функций, которая принимает описатель объекта в качестве аргумента. Одной из таких функций является функция CloseHandle , задача которой - закрыть объект . Во избежание утечки памяти всегда рекомендуется закрывать объект , если в нем отпала надобность. Впрочем, по окончании работы процесса система закрывает все его объекты. Таким образом, структуры объектов ядра доступны только ядру, приложение не может самостоятельно найти эти структуры в памяти и напрямую модифицировать их содержимое.

Именование объектов. Разделяемые ресурсы

Многие объекты в системе имеют имена. Именование объектов удобно для учета объектов и поиска нужного объекта. Кроме того, знание имени объекта может быть использовано процессом для получения к нему доступа (совместное использование ресурсов). Пространство имен объектов по аналогии с пространствами имен реестра и файлов организовано в виде древовидной иерархической системы. В качестве нетерминальной вершины дерева используется объект - "каталог объектов". Каталог включает информацию, необходимую для трансляции имен объектов в указатели на сами объекты. Вследствие необходимости выполнения навигации по каталогам ссылка на объект по имени работает существенно дольше, чем по описателю.

Объекты ядра используются системой и нашими приложениями для управления множеством разных ресурсов: процессами, потоками, файлами и т.д.

Система позволяет создавать и оперировать несколькими типами таких объектов, в том числе: маркерами доступа (access token objects), файлами (file objects), проекциями файлов (file-mapping objects), портами завершения ввода вывода (I/O completion port objects), заданиями (jobs), почтовыми ящиками (mailslot objects), мьютексами (mutex objects), каналами (pipe objects), процессами (thread objects) и ожидаемыми таймерами (waitable timer objects).

Эти объекты создаются Windows-функциями. Например, CreateFileMapping заставляет систему сформировать объект проекцию файла. Каждый объект ядра на самом деле просто блок памяти, выделенный ядром и доступный только ему.

Блок представляет собой структуру данных, в элементах которой содержится информация об объекте. Некоторые элементы (дескриптор защиты, счетчик числа пользователей и др.) присутствуют во всех объектах, но большая их часть специфична для объектов конкретного типа. Например, у объекта процесс есть идентификатор, базовый приоритет и код завершения, а у объекта файл - смещение в байтах, режим разделения и режим открытия.

Приложение не может напрямую обращаться к объектам ядра читать и изменять их содержимое.

Для взаимодействия с объектами ядра у Windows предусмотрен набор функций, обрабатывающих структуры объектов ядра по строго определенным правилам. Когда мы создаем объект ядра, функция возвращает описатель идентифицирующий созданный объект (HANDLE). Все операции с текущим объектом ядра возможны только при указании этого описателя управляющей функции.

Для большей защиты, описатели уникальны только внутри конкретного процесса. Поэтому, передавая по межпроцессорной связи описатель объекта другому процессу, используя описатель в другом процессе, мы получим ошибку. Это ограничение можно обойти, но об этом позже.

Учет пользователей объектов ядра.

Объекты ядра принадлежат ядру, а не процессу. Это говорит о том, что завершая работу с процессом, мы не обязательно разрушаем объект ядра. В большинстве случаев объект разрушается, но если созданный вами объект ядра используется другим процессом, ядро запретит разрушение объекта до тех пор, пока от него не откажется последний пользователь.

В каждом объекте, как уже говорилось, есть счетчик пользователей объектом. В момент создания счетчику присваивается значение 1. Соответственно, при обращении к нему другого процесса, счетчик увеличивается на 1. Когда пользовательский процесс завершается, счетчик уменьшается. Система удаляет объект ядра, когда счетчик обнуляется.

Почти во всех функциях, создающих объекты, есть параметр SECURITY_ATTRIBUTES. Он необходим для защиты объектов ядра от несанкционированного доступа. Чаще всего это свойство используют в серверных приложениях, в клиентских приложениях этот объект можно игнорировать.

Если вы пишете для win98, то там такое свойство отсутствует, но для корректной работы таких приложений в Win2000 и выше, стоит помнить о работе с соответствующими механизмами.

При передаче в таком атрибуте NULL большинство объектов будут созданы со стандартными свойствами защиты, когда к объекту допускаются: создатель и администраторская группа. Остальные игнорируются.

Читайте также: