Содержание
- KasperskyOS API
- Коды возврата
- Библиотека libkos
- Управление дескрипторами (handle_api.h)
- Управление виртуальной памятью (vmm_api.h)
- Выделение и освобождение памяти (alloc.h)
- Использование DMA (dma.h)
- Ввод-вывод через память (mmio.h)
- Управление обработкой прерываний (irq.h)
- Управление потоками исполнения (высокоуровневый API thread.h)
- Управление потоками исполнения (низкоуровневый API thread_api.h)
- Управление процессами (высокоуровневый API task.h)
- Управление процессами (низкоуровневый API task_api.h)
- Инициализация IPC-транспорта для межпроцессного взаимодействия и управление обработкой IPC-запросов (transport-kos.h, transport-kos-dispatch.h)
- Инициализация IPC-транспорта для обращения к модулю безопасности (transport-kos-security.h)
- Генерация случайных чисел (random_api.h)
- Получение и изменение значений времени (time_api.h)
- Использование уведомлений (notice_api.h)
- Динамическое создание IPC-каналов (cm_api.h, ns_api.h)
- Использование примитивов синхронизации (event.h, mutex.h, rwlock.h, semaphore.h, condvar.h)
- Управление изоляцией памяти для ввода-вывода (iommu_api.h)
- Использование очередей (queue.h)
- Использование барьеров памяти (barriers.h)
- Выполнение системных вызовов (syscalls.h)
- Прерывание IPC (ipc_api.h)
- Использование сессий (session.h)
- Использование объектов KosObject (objects.h)
- Использование контейнеров объектов KosObject (objcontainer.h)
- Использование строк KosString (strings.h)
- Управление драйвером XHCI DbC ядра KasperskyOS (xhcidbg_api.h)
- Получение данных аудита безопасности (vlog_api.h)
- Использование фьютексов (sync.h)
- Получение IPC-дескрипторов и идентификаторов служб для использования статически созданных IPC-каналов (sl_api.h)
- Управление электропитанием (pm_api.h)
- Поддержка POSIX
- Получение статистических сведений о системе через API библиотеки libc
- Динамическое создание IPC-каналов с использованием системной программы DCM
- Компонент MessageBus
- Компонент LogRR
- Компонент ExecutionManager
- Компонент PackageManager
Коды возврата
Общие сведения
В решении на базе KasperskyOS коды возврата функций различных API (например, API библиотек libkos
и kdf
, драйверов, транспортного кода, прикладного ПО) имеют тип 32-битного знакового целого числа. Этот тип определен в заголовочном файле sysroot-*-kos/include/rtl/retcode.h
из состава KasperskyOS SDK так:
Множество кодов возврата состоит из кода успеха со значением 0
и кодов ошибок. Код ошибки интерпретируется как структура данных, формат которой описан в заголовочном файле sysroot-*-kos/include/rtl/retcode.h
из состава KasperskyOS SDK. Этот формат предусматривает наличие нескольких полей, которые содержат не только сведения о результатах вызова функции, но и следующую дополнительную информацию:
- Флаг в поле
Customer
, сигнализирующий о том, что код ошибки определен разработчиками решения на базе KasperskyOS, а не разработчиками ПО из состава KasperskyOS SDK.Благодаря флагу в поле
Customer
разработчики решения на базе KasperskyOS и разработчики ПО из состава KasperskyOS SDK могут определять коды ошибок из непересекающихся множеств. - Глобальный идентификатор кода ошибки в поле
Space
.Глобальные идентификаторы позволяют определять непересекающиеся множества кодов ошибок. Коды ошибок могут быть общими и специфичными. Общие коды ошибок могут использоваться в API любых компонентов решения и в API любых составных частей компонентов решения (например, драйвер или VFS могут быть составной частью компонента решения). Специфичные коды ошибок используются в API одного или нескольких компонентов решения или в API одной или нескольких составных частей компонентов решения.
Например, идентификатору
RC_SPACE_GENERAL
соответствуют коды общих ошибок, идентификаторуRC_SPACE_KERNEL
соответствуют коды ошибок ядра, идентификаторуRC_SPACE_DRIVERS
соответствуют коды ошибок драйверов. - Локальный идентификатор кода ошибки в поле
Facility
.Локальные идентификаторы позволяют определять непересекающиеся подмножества кодов ошибок в рамках множества кодов ошибок, которые соответствуют одному глобальному идентификатору. Например, множество кодов ошибок с глобальным идентификатором
RC_SPACE_DRIVERS
включает непересекающиеся подмножества кодов ошибок с локальными идентификаторамиRC_FACILITY_I2C
,RC_FACILITY_USB
,RC_FACILITY_BLKDEV
.
Глобальные и локальные идентификаторы специфичных кодов ошибок назначаются разработчиками решения на базе KasperskyOS и разработчиками ПО из состава KasperskyOS SDK независимо друг от друга. То есть формируется два множества глобальных идентификаторов. Каждый глобальный идентификатор имеет уникальное смысловое значение в рамках одного множества. Каждый локальный идентификатор имеет уникальное смысловое значение в рамках множества локальных идентификаторов, относящихся к одному глобальному идентификатору. Общие коды ошибок могут использоваться в любых API.
Такой централизованный подход позволяет избежать появления в решении на базе KasperskyOS одинаковых кодов ошибок с разными смысловыми значениями. Это нужно, чтобы исключить проблему транзита кодов ошибок через разные API. Например, такая проблема возникает, когда драйверы вызывают функции библиотеки kdf
, получают коды ошибок и возвращают эти коды через свои API. Если формировать коды ошибок без централизованного подхода, то один и тот же код ошибки может иметь разные смысловые значения для библиотеки kdf
и для драйвера. В таких условиях драйверы возвращают корректные коды ошибок, если только выполняется преобразование кодов ошибок библиотеки kdf
в коды ошибок каждого из драйверов. То есть коды ошибок в решении на базе KasperskyOS назначаются так, чтобы не выполнять конвертацию этих кодов при транзите через разные API.
Приведенные здесь сведения о кодах возврата не относятся к функциям интерфейса POSIX и API стороннего ПО, используемого в решениях на базе KasperskyOS.
Общие коды возврата
Коды возврата, которые являются общими для API любых компонентов решения и их составных частей, определены в заголовочном файле sysroot-*-kos/include/rtl/retcode.h
из состава KasperskyOS SDK. Описание общих кодов возврата приведено в таблице ниже.
Общие коды возврата
Код возврата |
Описание |
---|---|
|
Функция завершилась успешно. |
|
Параметр функции некорректен. |
|
Нет соединения между клиентской и серверной сторонами взаимодействия. Например, отсутствует серверный IPC-дескриптор. |
|
Недостаточно памяти для выполнения операции. |
|
Недостаточный размер буфера. |
|
Функция завершилась с внутренней ошибкой, которая связана с некорректной логикой. Примерами внутренних ошибок являются: выход значений за допустимые пределы, появление нулевых указателей и значений там, где этого быть не должно. |
|
Ошибка отправки IPC-сообщения. |
|
Ошибка приема IPC-сообщения. |
|
IPC-сообщение не было передано из-за источника IPC-сообщения. |
|
IPC-сообщение не было передано из-за приемника IPC-сообщения. |
|
IPC прервано другим потоком процесса. |
|
Сигнализирует, что функцию нужно вызвать повторно. |
|
Функция завершилась с ошибкой. |
|
Операция над ресурсом недоступна. |
|
Инициализация не выполнена. |
|
Функция не реализована. |
|
Большой размер буфера. |
|
Ресурс временно недоступен. |
|
Ресурс не найден. |
|
Время ожидания истекло. |
|
Операция запрещена механизмами безопасности. |
|
Операция приведет к блокировке. |
|
Операция прервана. |
|
В обработчике прерывания вызвана недопустимая функция. |
|
Множество элементов уже содержит добавляемый элемент. |
|
Операция не может быть выполнена. |
|
Права доступа к ресурсу отозваны. |
|
Квота на ресурс превышена. |
|
Устройство не найдено. |
|
Произошло переполнение. |
|
Операция уже выполнена. |
|
Операция не была запущена. |
Определение кодов ошибок
Чтобы определить код ошибки, разработчику решения на базе KasperskyOS нужно использовать макрос MAKE_RETCODE()
, определенный в заголовочном файле sysroot-*-kos/include/rtl/retcode.h
из состава KasperskyOS SDK. При этом через параметр customer
нужно передать символьную константу RC_CUSTOMER_TRUE
.
Пример:
Описание ошибки, которое передается через параметр desc
, не используется макросом MAKE_RETCODE()
. Это описание требуется, чтобы создать базу данных кодов ошибок при сборке решения на базе KasperskyOS. В настоящее время механизм для создания и использования такой базы данных не реализован.
Чтение полей структуры кода ошибки
Макросы RC_GET_CUSTOMER()
, RC_GET_SPACE()
, RC_GET_FACILITY()
и RC_GET_CODE()
, определенные в заголовочном файле sysroot-*-kos/include/rtl/retcode.h
из состава KasperskyOS SDK, позволяют читать поля структуры кода ошибки.
Макросы RETCODE_HR_PARAMS()
и RETCODE_HR_FMT()
, определенные в заголовочном файле sysroot-*-kos/include/rtl/retcode_hr.h
из состава KasperskyOS SDK, используются для форматированного вывода сведений об ошибке.
Библиотека libkos
Библиотека libkos
является базовой библиотекой KasperskyOS, предоставляющей набор API, через которые программы и другие библиотеки (например, libc
, kdf
) используют службы ядра. API, предоставляемые библиотекой libkos
, обеспечивают для разработчиков решения следующие возможности:
- управление процессами, потоками исполнения, виртуальной памятью;
- управление доступом к ресурсам;
- осуществление ввода-вывода;
- создание IPC-каналов;
- управление электропитанием;
- получение статистических сведений о системе;
- другие возможности, поддерживаемые службами ядра.
На аппаратных платформах с процессорной архитектурой Arm входные и выходные параметры API библиотеки libkos
нельзя сохранять в памяти типа "Device memory", поскольку это может привести к неопределенному поведению. (Исключениями являются: параметр addr
функции KnVmQuery()
из API vmm_api.h, параметры reg
и baseReg
функций из API mmio.h, параметр va
функции KnHalFlushCache()
из API hal_api.h, параметр va
функции KosCpuCacheFlush()
из API cpucache.h.) Параметры API библиотеки libkos
нужно сохранять в памяти типа "Normal memory". Чтобы копировать данные из памяти типа "Device memory" в память типа "Normal memory" и обратно, нужно использовать функцию RtlPedanticMemcpy()
, объявленную в заголовочном файле sysroot-*-kos/include/rtl/string_pedantic.h
из состава KasperskyOS SDK.
Управление дескрипторами (handle_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
API предназначен для выполнения операций с дескрипторами. Дескрипторы имеют тип Handle
, который определен в заголовочном файле sysroot-*-kos/include/handle/handletype.h
из состава KasperskyOS SDK.
Локальность дескрипторов
Каждый процесс получает дескрипторы из своего пространства дескрипторов независимо от других процессов. Пространства дескрипторов разных процессов абсолютно идентичны, то есть представляют собой одно и то же множество значений. Поэтому дескриптор является уникальным (имеет уникальное значение) только в рамках пространства дескрипторов одного процесса, который владеет этим дескриптором. То есть разные процессы могут иметь: одинаковые дескрипторы, которые идентифицируют разные ресурсы, или разные дескрипторы, которые идентифицируют один и тот же ресурс.
Маска прав дескриптора
Маска прав дескриптора имеет размер 32 бита и состоит из общей и специальной части. Общая часть описывает права, неспецифичные для любых ресурсов (флаги этих прав определены в заголовочном файле sysroot-*-kos/include/services/ocap.h
из состава KasperskyOS SDK). Например, в общей части находится флаг OCAP_HANDLE_TRANSFER
, который определяет право на передачу дескриптора. Специальная часть описывает права, специфичные для пользовательского или системного ресурса. Флаги прав специальной части для системных ресурсов определены в заголовочном файле ocap.h
. Структура специальной части для пользовательских ресурсов определяется поставщиком ресурсов с использованием макроса OCAP_HANDLE_SPEC()
, который определен в заголовочном файле ocap.h
. Поставщику ресурсов необходимо экспортировать публичные заголовочные файлы с описанием флагов специальной части.
При создании дескриптора системного ресурса маска прав задается ядром KasperskyOS, которое применяет маски прав из заголовочного файла ocap.h
. Применяются маски прав с именами вида OCAP_*_FULL
(например, OCAP_IOPORT_FULL
, OCAP_TASK_FULL
, OCAP_FILE_FULL
) и вида OCAP_IPC_*
(например, OCAP_IPC_SERVER
, OCAP_IPC_LISTENER
, OCAP_IPC_CLIENT
).
При создании дескриптора пользовательского ресурса маска прав задается пользователем.
При передаче дескриптора маска прав задается пользователем, но передаваемые права доступа не могут быть повышены относительно прав доступа, которые имеет процесс.
В началоСоздание дескрипторов
Сведения о функциях API приведены в таблице ниже.
Создание дескрипторов системных ресурсов
Дескрипторы системных ресурсов создаются при создании этих ресурсов, например, при регистрации прерывания или региона памяти MMIO, создании буфера DMA, потока исполнения или процесса.
Создание дескрипторов пользовательских ресурсов
Дескрипторы пользовательских ресурсов создаются поставщиками ресурсов с использованием функции KnHandleCreateUserObject()
или KnHandleCreateUserObjectEx()
.
Через параметр context
нужно задать контекст пользовательского ресурса. Контекст пользовательского ресурса – данные, позволяющие поставщику ресурса идентифицировать ресурс и его состояние, когда запрашивается доступ к ресурсу другими процессами. В общем случае это набор разнотипных данных (структура). Например, для файла контекст может включать имя, путь, положение курсора. Контекст пользовательского ресурса используется в качестве контекста передачи ресурса или совместно с несколькими контекстами передачи ресурса.
Через параметр rights
нужно задать маску прав дескриптора.
Создание IPC-дескрипторов
IPC-дескриптор (англ. IPC handle) – это дескриптор, который идентифицирует IPC-канал. IPC-дескрипторы используются для выполнения системных вызовов. Клиентский IPC-дескриптор нужен для выполнения системного вызова Call()
. Серверный IPC-дескриптор требуется для выполнения системных вызовов Recv()
и Reply()
. Серверный IPC-дескриптор, который имеет расширенные права, позволяющие добавлять IPC-каналы в набор идентифицируемых этим дескриптором IPC-каналов, называется слушающим дескриптором (англ. listener handle). Клиентский IPC-дескриптор, который идентифицирует одновременно IPC-канал до сервера и службу этого сервера, называется callable-дескриптором (англ. callable handle).
Сервер создает callable-дескриптор и передает его клиенту, чтобы клиент мог использовать службу сервера. Клиент инициализирует IPC-транспорт, используя полученный callable-дескриптор. При этом в функции инициализации прокси-объекта клиент указывает значение INVALID_RIID
в качестве идентификатор службы (RIID). Чтобы создать callable-дескриптор, нужно вызвать функцию KnHandleCreateUserObjectEx()
, указав в параметрах ipcChannel
и riid
серверный IPC-дескриптор и идентификатор службы (RIID) соответственно. Через параметр context
можно задать данные для ассоциации с callable-дескриптором. Сервер сможет получить указатель на эти данные при разыменовании callable-дескриптора. (Несмотря на то что callable-дескриптор является IPC-дескриптором, он помещается ядром в поле base_.self
фиксированной части IPC-запроса.)
Чтобы создать и ассоциировать между собой клиентский, серверный и слушающий IPC-дескрипторы, нужно вызвать функцию KnHandleConnect()
или KnHandleConnectEx()
. Эти функции используются для статического создания IPC-каналов. Функция KnHandleConnect()
создает IPC-дескрипторы из пространства дескрипторов вызывающего процесса. При этом клиентский IPC-дескриптор может быть передан другому процессу. Функция KnHandleConnectEx()
может создать IPC-дескрипторы как из пространства дескрипторов вызывающего процесса, так и из пространств дескрипторов других процессов: клиента и сервера.
При вызове функции KnHandleConnect()
или KnHandleConnectEx()
со значением INVALID_HANDLE
в параметре, задающем слушающий дескриптор, создается новый слушающий дескриптор. При этом серверный и слушающий IPC-дескрипторы в выходных параметрах являются одним и тем же дескриптором. Если вызвать функцию KnHandleConnect()
или KnHandleConnectEx()
, указав слушающий дескриптор, то созданный серверный IPC-дескриптор обеспечит возможность получать IPC-запросы по всем IPC-каналам, ассоциированным с этим слушающим дескриптором. В этом случае серверный и слушающий IPC-дескрипторы в выходных параметрах являются разными дескрипторами. (Первый IPC-канал, ассоциированный со слушающим дескриптором, создается при вызове функции KnHandleConnect()
или KnHandleConnectEx()
со значением INVALID_HANDLE
в параметре, задающем слушающий дескриптор. Второй и последующие IPC-каналы, ассоциированные со слушающим дескриптором, создаются при втором и последующих вызовах функции KnHandleConnect()
или KnHandleConnectEx()
с указанием слушающего дескриптора, полученного при первом вызове.)
Чтобы создать слушающий дескриптор, не связанный с клиентским и серверным IPC-дескрипторами, нужно вызвать функцию KnHandleCreateListener()
. (Функции KnHandleConnect()
и KnHandleConnectEx()
создают слушающий дескриптор, связанный с клиентским и серверным IPC-дескрипторами.) Функцию KnHandleCreateListener()
удобно использовать, чтобы создать слушающий дескриптор, с которым впоследствии будут связаны callable-дескрипторы.
Чтобы создать клиентский IPC-дескриптор для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности, нужно вызвать функцию KnHandleSecurityConnect()
. Эта функция вызывается библиотекой libkos
при инициализации IPC-транспорта для обращения к модулю безопасности.
Сведения о функциях API
Функции handle_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает дескриптор. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает дескриптор. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает и связывает между собой клиентский, серверный и слушающий IPC-дескрипторы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает и связывает между собой клиентский, серверный и слушающий IPC-дескрипторы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает клиентский IPC-дескриптор для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает слушающий дескриптор, не связанный с клиентским и серверным IPC-дескрипторами. Параметры
Возвращаемые значения В случае успеха возвращает |
Передача дескрипторов
Сведения о функциях API приведены в таблице ниже.
Общие сведения о передаче дескрипторов
Передача дескрипторов между процессами осуществляется, чтобы потребители ресурсов получили доступ к требуемым ресурсам. По причине локальности дескрипторов передача дескриптора инициирует на стороне принимающего процесса создание дескриптора из его пространства дескрипторов. Этот дескриптор регистрируется как потомок отправленного дескриптора и идентифицирует тот же ресурс.
Один дескриптор может быть передан многократно одному или нескольким процессам. Каждая передача порождает нового потомка переданного дескриптора на стороне принимающего процесса. Процесс может передавать дескрипторы, которые он получил от других процессов или ядра KasperskyOS. Поэтому у дескриптора может быть несколько поколений потомков. Иерархия порождения дескрипторов для каждого ресурса хранится в ядре KasperskyOS в виде дерева наследования дескрипторов.
Процесс может передавать дескрипторы как пользовательских, так и системных ресурсов, если права доступа этих дескрипторов разрешают выполнять передачу (в маске прав установлен флаг OCAP_HANDLE_TRANSFER
). У потомка может быть меньше прав доступа, чем у предка. Например, передающий процесс имеет права доступа к файлу на чтение и запись, а передает права доступа только на чтение. Передающий процесс также может запретить принимающему процессу дальнейшую передачу дескриптора. Права доступа задаются в передаваемой маске прав дескриптора.
Условия для передачи дескрипторов
Чтобы процессы могли передавать дескрипторы между собой, должны выполняться следующие условия:
- Между процессами создан IPC-канал.
- Политика безопасности решения (
security.psl
) разрешает взаимодействие классов процессов. - Реализованы интерфейсные методы для передачи дескрипторов.
API task.h позволяет родительскому процессу передавать дескрипторы дочернему процессу, который еще не запущен.
В IDL-описании сигнатуры интерфейсных методов для передачи дескрипторов имеют входные (in
) и/или выходные (out
) параметры типа Handle
или array
с элементами типа Handle
. Через входные параметры одного метода можно передать до 255 дескрипторов. Столько же дескрипторов можно получить через выходные параметры.
Пример IDL-описания, где заданы сигнатуры интерфейсных методов для передачи дескрипторов:
Для каждого параметра типа Handle
компилятор NK генерирует в структурах IPC-запросов *_req
и/или IPC-ответов *_res
поле типа nk_handle_desc_t
(далее также транспортный контейнер дескриптора). Этот тип объявлен в заголовочном файле sysroot-*-kos/include/nk/types.h
из состава KasperskyOS SDK и представляет собой структуру, состоящую из трех полей: поля дескриптора handle
, поля маски прав дескриптора rights
и поля контекста передачи ресурса badge
.
Контекст передачи ресурса
Контекст передачи ресурса – данные, позволяющие серверу идентифицировать ресурс и его состояние, когда запрашивается доступ к ресурсу через потомков переданного дескриптора. В общем случае это набор разнотипных данных (структура). Например, для файла контекст передачи может включать имя, путь, положение курсора. Сервер получает указатель на контекст передачи ресурса при разыменовании дескриптора.
Сервер независимо от того, является ли она поставщиком ресурса или нет, может ассоциировать каждую передачу дескриптора с отдельным контекстом передачи ресурса. Этот контекст передачи ресурса связывается только с теми потомками дескриптора (поддеревом наследования дескриптора), которые порождены в результате конкретной его передачи. Это позволяет определять состояние ресурса по отношению к отдельной передаче дескриптора этого ресурса. Например, в случае множественного доступа к одному файлу контекст передачи файла позволяет определить, какому именно открытию этого файла соответствует полученный IPC-запрос.
Если сервер является поставщиком ресурса, то по умолчанию каждая передача дескриптора этого ресурса ассоциируется с контекстом пользовательского ресурса. То есть контекст пользовательского ресурса используется в качестве контекста передачи ресурса для каждой передачи дескриптора, если эта передача не ассоциируется с отдельным контекстом передачи ресурса.
Сервер, который является поставщиком ресурса, может использовать совместно контекст пользовательского ресурса и контексты передачи ресурса. Например, имя, путь и размер файла хранятся в контексте пользовательского ресурса, а положение курсора хранится в нескольких контекстах передачи ресурса, так как каждый клиент может работать с разными частями файла. Технически совместное использование контекста пользовательского ресурса и контекстов передачи ресурса достигается тем, что контексты передачи ресурса хранят указатель на контекст пользовательского ресурса.
Если клиент использует несколько разнотипных ресурсов сервера, контексты передачи ресурсов (или контексты пользовательских ресурсов, если они используются в качестве контекстов передачи ресурсов) должны быть типизированными объектами KosObject
(об объектах KosObject
см. "Использование объектов KosObject (objects.h)"). Это нужно, чтобы сервер мог проверить, что клиент при использовании ресурса передал в интерфейсный метод дескриптор того ресурса, который соответствует этому методу. Такая проверка требуется, поскольку клиент может ошибочно передать в интерфейсный метод дескриптор ресурса, который не соответствует этому методу. Например, клиент получил дескриптор файла и передал его в интерфейсный метод для работы с томами.
Чтобы ассоциировать передачу дескриптора с контекстом передачи ресурса, сервер помещает в поле badge
структуры nk_handle_desc_t
дескриптор объекта контекста передачи ресурса. Объект контекста передачи ресурса – объект ядра, в котором хранится указатель на контекст передачи ресурса. Чтобы создать объект контекста передачи ресурса, нужно вызвать функцию KnHandleCreateBadge()
. Работа этой функции связана с механизмом уведомлений, так как серверу нужно знать, когда объект контекста передачи ресурса будет закрыт и удален. Эти сведения требуются серверу, чтобы освободить или использовать повторно память, которая отведена для хранения контекста передачи ресурса.
Объект контекста передачи ресурса будет закрыт, когда будут закрыты или отозваны потомки дескриптора, которые образуют поддерево наследования дескрипторов, корневой узел которого порожден передачей этого дескриптора в ассоциации с этим объектом. (Переданный дескриптор может быть закрыт не только целенаправленно, но и, например, при неожиданном завершении работы принимающего клиента.) Получив уведомление о закрытии объекта контекста передачи ресурса, сервер закрывает дескриптор этого объекта. После этого объект контекста передачи ресурса будет удален. Получив уведомление, что объект контекста передачи ресурса удален, сервер освобождает или использует повторно память, которая отведена для хранения контекста передачи ресурса.
Один объект контекста передачи ресурса может быть ассоциирован только с одной передачей дескриптора.
Упаковка данных в транспортный контейнер дескриптора
Чтобы упаковать дескриптор, маску прав дескриптора и дескриптор объекта контекста передачи ресурса в транспортный контейнер дескриптора, нужно использовать макрос nk_handle_desc()
, который определен в заголовочном файле sysroot-*-kos/include/nk/types.h
из состава KasperskyOS SDK. Этот макрос принимает переменное число параметров.
Если не передавать макросу ни одного параметра, то в поле дескриптора handle
структуры nk_handle_desc_t
будет записано значение NK_INVALID_HANDLE
. Если передать макросу один параметр, то этот параметр интерпретируется как дескриптор. Если передать макросу два параметра, то первый параметр интерпретируется как дескриптор, второй параметр интерпретируется как маска прав дескриптора. Если передать макросу три параметра, то первый параметр интерпретируется как дескриптор, второй параметр интерпретируется как маска прав дескриптора, третий параметр интерпретируется как дескриптор объекта контекста передачи ресурса.
Извлечение данных из транспортного контейнера дескриптора
Чтобы извлечь дескриптор, маску прав дескриптора и указатель на контекст передачи ресурса из транспортного контейнера дескриптора, нужно использовать соответственно функции nk_get_handle()
, nk_get_rights()
и nk_get_badge_op()
(или nk_get_badge()
), которые определены в заголовочном файле sysroot-*-kos/include/nk/types.h
из состава KasperskyOS SDK. Функции nk_get_badge_op()
и nk_get_badge()
нужно использовать только при разыменовании дескрипторов.
Сценарии передачи дескрипторов
Сценарий передачи дескрипторов от клиента к серверу включает следующие шаги:
- Клиент упаковывает дескрипторы и маски прав дескрипторов в поля структуры IPC-запросов
*_req
типаnk_handle_desc_t
. - Клиент вызывает интерфейсный метод для передачи дескрипторов серверу. При вызове этого метода выполняется системный вызов
Call()
. - Сервер получает IPC-запрос, выполняя системный вызов
Recv()
. - Диспетчер на стороне сервера вызывает метод, который соответствует IPC-запросу. Этот метод извлекает дескрипторы и маски прав дескрипторов из полей структуры IPC-запросов
*_req
типаnk_handle_desc_t
.
Сценарий передачи дескрипторов от сервера к клиенту включает следующие шаги:
- Клиент вызывает интерфейсный метод для получения дескрипторов от сервера. При вызове этого метода выполняется системный вызов
Call()
. - Сервер получает IPC-запрос, выполняя системный вызов
Recv()
. - Диспетчер на стороне сервера вызывает метод, который соответствует IPC-запросу. Этот метод упаковывает дескрипторы, маски прав дескрипторов и дескрипторы объектов контекстов передачи ресурсов в поля структуры IPC-ответов
*_res
типаnk_handle_desc_t
. - Сервер отвечает на IPC-запрос, выполняя системный вызов
Reply()
. - На стороне клиента интерфейсный метод возвращает управление. После этого клиент извлекает дескрипторы и маски прав дескрипторов из полей структуры IPC-ответов
*_res
типаnk_handle_desc_t
.
Если передающий процесс задает в передаваемой маске прав дескриптора больше прав доступа, чем задано для передаваемого дескриптора (владельцем которого он является), то передача не осуществляется. В этом случае выполнение системного вызова Call()
передающим или принимающим клиентом, а также выполнение системного вызова Reply()
передающим сервером завершается с ошибкой rcSecurityDisallow
.
Сведения о функциях API
Функции handle_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает объект контекста передачи ресурса и настраивает механизм уведомлений для контроля жизненного цикла этого объекта. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Приемник уведомлений настраивается на получение уведомлений о событиях, которые соответствуют флагам маски событий |
Копирование дескрипторов
Копирование дескриптора представляет собой операцию, похожую на передачу дескриптора, но выполняемую внутри процесса. Потомок дескриптора создается в том же процессе и из того же пространства дескрипторов. Права потомка дескриптора могут быть меньше либо равны правам оригинального дескриптора. Копирование дескриптора можно ассоциировать с объектом контекста передачи ресурса. Это позволит отследить через механизм уведомлений, когда будут закрыты или отозваны все потомки дескриптора, образующие поддерево наследования дескрипторов, корневой узел которого порожден копированием. Также это обеспечит возможность отозвать этих потомков.
Чтобы выполнить копирование дескриптора, нужно вызвать функцию KnHandleCopy()
. При этом в маске прав дескриптора должен быть установлен флаг OCAP_HANDLE_COPY
.
Сведения о функциях API приведены в таблице ниже.
Функции handle_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Копирует дескриптор. В результате копирования вызывающий процесс получает потомка дескриптора. Параметры
Возвращаемые значения В случае успеха возвращает |
Разыменование дескрипторов
Разыменование дескриптора – это операция, при которой клиент отправляет серверу дескриптор, а сервер получает указатель на контекст передачи ресурса, маску прав отправленного дескриптора и предка отправленного клиентом дескриптора, которым сервер уже владеет. Разыменование выполняется, когда потребитель ресурсов, вызывая методы работы с ресурсом (например, чтение, запись, закрытие доступа), передает поставщику ресурсов дескриптор, который был получен от этого поставщика ресурсов при открытии доступа к ресурсу.
Разыменование дескрипторов требует выполнения тех же условий и использует те же механизмы и типы данных, что и передача дескрипторов. Сценарий разыменования дескриптора включает следующие шаги:
- Клиент упаковывает дескриптор в поле структуры IPC-запросов
*_req
типаnk_handle_desc_t
. - Клиент вызывает интерфейсный метод для отправки дескриптора серверу с целью выполнения действий с ресурсом. При вызове этого метода выполняется системный вызов
Call()
. - Сервер принимает IPC-запрос, выполнив системный вызов
Recv()
. - Диспетчер на стороне сервера вызывает метод, который соответствует IPC-запросу. Этот метод проверяет, что выполнена именно операция разыменования, а не передача дескриптора. Затем вызванный метод опционально проверяет, что права доступа разыменованного дескриптора (который отправлен клиентом) разрешают запрашиваемые действия с ресурсом, и извлекает указатель на контекст передачи ресурса из поля структуры запросов
*_req
типаnk_handle_desc_t
.
Для выполнения проверок сервер использует функции nk_is_handle_dereferenced()
и nk_get_badge_op()
, которые объявлены в заголовочном файле sysroot-*-kos/include/nk/types.h
из состава KasperskyOS SDK.
types.h (фрагмент)
В общем случае серверу не требуется дескриптор, который получен в результате разыменования, поскольку сервер, как правило, сохраняет дескрипторы, которыми владеет, например, в составе контекстов пользовательских ресурсов. Но при необходимости сервер может извлечь этот дескриптор из транспортного контейнера дескриптора.
В началоОтзыв дескрипторов
Процесс может отозвать потомков дескриптора, которым он владеет. Отзыв дескрипторов осуществляется на основе дерева наследования дескрипторов.
Отзыв дескрипторов не закрывает их, но через отозванные дескрипторы невозможно обращаться к ресурсам. Любая функция, которая принимает дескриптор, завершается с ошибкой rcHandleRevoked
, если эта функция вызвана с отозванным дескриптором.
Чтобы отозвать потомков дескриптора, нужно вызвать функцию KnHandleRevoke()
или KnHandleRevokeSubtree()
. Функция KnHandleRevokeSubtree()
использует объект контекста передачи ресурса, который создается при передаче дескрипторов.
Если каждый из дескрипторов системного ресурса во всех процессах, которые владеют этими дескрипторами, будет закрыт (см. "Закрытие дескрипторов") или отозван, то этот системный ресурс будет удален.
Сведения о функциях API приведены в таблице ниже.
Функции handle_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Закрывает дескриптор и отзывает его потомков. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отзывает дескрипторы, которые образуют поддерево наследования заданного дескриптора. Параметры
Возвращаемые значения В случае успеха возвращает |
Закрытие дескрипторов
Процесс может закрыть дескрипторы, которыми он владеет. Закрытие дескриптора прекращает ассоциацию идентификатора с ресурсом, тем самым освобождая идентификатор. Закрытие дескриптора не делает недействительными его предков и потомков (в отличие от отзыва дескриптора, который делает недействительными его потомков). То есть через предков и потомков закрытого дескриптора обеспечивается доступ к ресурсу, который они идентифицируют. Также закрытие дескриптора не нарушает целостность дерева наследования дескрипторов, которое относится к ресурсу, идентифицируемому этим дескриптором. Место закрытого дескриптора занимает его предок. То есть предок закрытого дескриптора становится непосредственным предком потомков закрытого дескриптора.
Чтобы закрыть дескриптор, нужно вызвать функцию KnHandleClose()
.
Если каждый из дескрипторов системного ресурса во всех процессах, которые владеют этими дескрипторами, будет отозван (см. "Отзыв дескрипторов") или закрыт, то этот системный ресурс будет удален.
Сведения о функциях API приведены в таблице ниже.
Функции handle_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Закрывает дескриптор. Параметры
Возвращаемые значения В случае успеха возвращает |
Получение идентификатора безопасности (SID)
Получив значения идентификаторов безопасности для разных дескрипторов, можно определить, идентифицируют ли эти дескрипторы разные ресурсы или один и тот же ресурс.
Чтобы получить идентификатор безопасности по дескриптору, нужно вызвать функцию KnHandleGetSidByHandle()
. При этом в маске прав дескриптора должен быть установлен флаг OCAP_HANDLE_GET_SID
.
Сведения о функциях API приведены в таблице ниже.
Функции handle_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Позволяет получить идентификатор безопасности (SID) по дескриптору. Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования OCap
В этом примере приведен сценарий использования OCap, в котором поставщик ресурсов предоставляет следующие методы доступа к своим ресурсам:
OpenResource()
– открытие доступа к ресурсу;UseResource()
– использование ресурса;CloseResource()
– закрытие доступа к ресурсу.
Потребитель ресурсов использует эти методы.
IDL-описание:
Сценарий включает следующие шаги:
- Поставщик ресурсов создает контекст пользовательского ресурса и вызывает функцию
KnHandleCreateUserObject()
для создания дескриптора ресурса. Поставщик ресурсов сохраняет дескриптор ресурса в контексте пользовательского ресурса. - Потребитель ресурсов вызывает метод открытия доступа к ресурсу
OpenResource()
.- Поставщик ресурсов создает контекст передачи ресурса и вызывает функцию
KnHandleCreateBadge()
для создания объекта контекста передачи ресурса и настройки приемника уведомлений на получение уведомлений о закрытии и удалении объекта контекста передачи ресурса. Поставщик ресурсов сохраняет дескриптор объекта контекста передачи ресурса и указатель на контекст пользовательского ресурса в контексте передачи ресурса. - Поставщик ресурсов, используя макрос
nk_handle_desc()
, упаковывает дескриптор ресурса, маску прав дескриптора и указатель на объект контекста передачи ресурса в транспортный контейнер дескриптора. - Выполняется передача дескриптора от поставщика ресурсов к потребителю ресурсов, в результате которой потребитель ресурсов получает потомка дескриптора, которым владеет поставщик ресурсов.
- Вызов метода
OpenResource()
завершается успешно. Потребитель ресурсов извлекает дескриптор и маску прав дескриптора из транспортного контейнера дескриптора функциямиnk_get_handle()
иnk_get_rights()
соответственно. Маска прав дескриптора не требуется потребителю ресурсов для обращения к ресурсу и передается, чтобы потребитель ресурсов мог узнать свои права доступа к ресурсу.
- Поставщик ресурсов создает контекст передачи ресурса и вызывает функцию
- Потребитель ресурсов вызывает метод использования ресурса
UseResource()
.- Дескриптор, который получен от поставщика ресурсов на шаге 2, используется в качестве параметра метода
UseResource()
. Перед вызовом этого метода потребитель ресурсов упаковывает дескриптор в транспортный контейнер дескриптора макросомnk_handle_desc()
. - Выполняется разыменование дескриптора, в результате которого поставщик ресурсов получает указатель на контекст передачи ресурса.
- Поставщик ресурсов, используя функцию
nk_is_handle_dereferenced()
, проверяет, что выполнена операция разыменования, а не передача дескриптора. - Поставщик ресурсов проверяет, что права доступа разыменованного дескриптора (который отправлен потребителем ресурсов) разрешают запрашиваемую операцию с ресурсом, и извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора. Для этого поставщик ресурсов использует функцию
nk_get_badge_op()
, которая извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора, если в полученной маске прав установлены флаги, соответствующие запрашиваемой операции. - Поставщик ресурсов, используя контекст передачи ресурса и контекст пользовательского ресурса, выполняет запрашиваемую потребителем ресурсов операцию с ресурсом. Затем поставщик ресурсов отправляет потребителю ресурсов результат выполнения этой операции.
- Вызов метода
UseResource()
завершается успешно. Потребитель ресурсов получает результат выполнения операции с ресурсом.
- Дескриптор, который получен от поставщика ресурсов на шаге 2, используется в качестве параметра метода
- Потребитель ресурсов вызывает метод закрытия доступа к ресурсу
CloseResource()
.- Дескриптор, который получен от поставщика ресурсов на шаге 2, используется в качестве параметра метода
CloseResource()
. Перед вызовом этого метода потребитель ресурсов упаковывает дескриптор в транспортный контейнер дескриптора макросомnk_handle_desc()
. После вызова методаCloseResource()
потребитель ресурсов закрывает дескриптор функциейKnHandleClose()
. - Выполняется разыменование дескриптора, в результате которого поставщик ресурсов получает указатель на контекст передачи ресурса.
- Поставщик ресурсов, используя функцию
nk_is_handle_dereferenced()
, проверяет, что выполнена операция разыменования, а не передача дескриптора. - Поставщик ресурсов, используя функцию
nk_get_badge()
, извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора. - Поставщик ресурсов отзывает дескриптор, которым владеет потребитель ресурсов, функцией
KnHandleRevokeSubtree()
. В качестве параметров этой функции используются дескриптор ресурса, которым владеет поставщик ресурсов, и дескриптор объекта контекста передачи ресурса. Поставщик ресурсов получает доступ к этим дескрипторам через указатель на контекст передачи ресурса. (Технически не требуется отзывать дескриптор, которым владеет потребитель ресурсов, так как потребитель ресурсов его уже закрыл. Но поставщик ресурсов не может быть уверен в том, что потребитель ресурсов закрыл дескриптор, поэтому выполняется отзыв). - Вызов метода
CloseResource()
завершается успешно.
- Дескриптор, который получен от поставщика ресурсов на шаге 2, используется в качестве параметра метода
- Поставщик ресурсов освобождает память, которая была выделена для контекста передачи ресурса и контекста пользовательского ресурса.
- Поставщик ресурсов вызовом функции
KnNoticeGetEvent()
получает уведомление, что объект контекста передачи ресурса закрыт, и закрывает дескриптор объекта контекста передачи ресурса функциейKnHandleClose()
. - Поставщик ресурсов вызовом функции
KnNoticeGetEvent()
получает уведомление, что объект контекста передачи ресурса удален, и освобождает память, которая была выделена для контекста передачи ресурса. - Поставщик ресурсов закрывает дескриптор ресурса функцией
KnHandleClose()
и освобождает память, которая была выделена для контекста пользовательского ресурса.
- Поставщик ресурсов вызовом функции
Управление виртуальной памятью (vmm_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/vmm/vmm_api.h
из состава KasperskyOS SDK.
API предназначен для выделения и освобождения памяти, создания разделяемой памяти, а также подготовки сегментов ELF-образа к загрузке в память процесса.
Выделение и освобождение памяти
Сведения о функциях API приведены в таблице ниже.
Использование API
Страницы виртуальной памяти могут быть свободными, зарезервированными или зафиксированными. Свободные страницы, которые были использованы для выделения региона виртуальной памяти, становятся зарезервированными. Зарезервированные страницы могут как отображаться, так и не отображаться на физическую память. Зарезервированные страницы, которые отображаются на физическую память, являются зафиксированными.
Фиксация страниц региона виртуальной памяти, который выделен вызовом функции KnVmAllocate()
, может выполняться тремя способами:
- В полном объеме при выделении региона.
- В полном объеме или частично после выделения региона (вызовом функции
KnVmCommit()
). - По мере обращения к виртуальным адресам (в "ленивом" режиме).
При использовании первого способа весь требуемый объем физической памяти выделяется сразу после резервирования региона виртуальной памяти. При использовании второго и третьего способов регион виртуальной памяти резервируется без выделения физической памяти. Это позволяет экономить физическую память, если зарезервированный регион виртуальной памяти фактически не потребуется или будет использован частично. Также выделение региона виртуальной памяти без фиксации быстрее, чем с фиксацией.
В "ленивом" режиме физическая память выделяется при фактическом обращении к региону виртуальной памяти. При этом фиксируется страница, содержащая адрес обращения, и несколько страниц до или после нее.
Если вызвать функцию KnVmAllocate()
с флагами VMM_FLAG_COMMIT
и VMM_FLAG_LOCKED
, то будет зарезервирован регион виртуальной памяти с фиксацией в полном объеме. Если вызвать функцию KnVmAllocate()
с флагом VMM_FLAG_COMMIT
, но без флага VMM_FLAG_LOCKED
, то будет зарезервирован регион виртуальной памяти с фиксацией в "ленивом" режиме. Если вызвать функцию KnVmAllocate()
с флагом VMM_FLAG_LOCKED
, но без флага VMM_FLAG_COMMIT
, то будет зарезервирован регион виртуальной памяти без фиксации, а последующий вызов функции KnVmCommit()
обеспечит фиксацию этого региона в полном объеме. Если вызвать функцию KnVmAllocate()
без флагов VMM_FLAG_COMMIT
и VMM_FLAG_LOCKED
, то будет зарезервирован регион виртуальной памяти без фиксации, а последующий вызов функции KnVmCommit()
обеспечит фиксацию этого региона в "ленивом" режиме.
При отображении буфера MDL, буфера DMA или региона памяти MMIO на память процесса выделяется регион виртуальной памяти. Этот регион выделяет функция, выполняющая отображение.
В начале и/или конце региона виртуальной памяти может располагаться охранная страница. Эта страница никогда не фиксируется, и при обращении к ней возникает исключение, которое сигнализирует о выходе за границы региона.
Чтобы изменить права доступа к региону виртуальной памяти, нужно вызвать функцию KnVmProtect()
. Можно полностью закрыть, а затем снова открыть доступ к региону с сохранением содержимого.
Чтобы освободить физическую память, сохранив резервирование виртуальных адресов, нужно вызвать функцию KnVmDecommit()
или KnVmReset()
. При этом содержимое региона виртуальной памяти будет потеряно. После освобождения физической памяти вызовом функции KnVmDecommit()
для последующего использования региона виртуальной памяти нужно вызвать функцию KnVmCommit()
. После освобождения физической памяти вызовом функции KnVmReset()
регион виртуальной памяти можно использовать без дополнительных действий. Этот регион виртуальной памяти будет соответствовать выделенному вызовом функции KnVmAllocate()
с флагом VMM_FLAG_COMMIT
, но без флага VMM_FLAG_LOCKED
.
Функции KnVmProtect()
, KnVmDecommit()
и KnVmReset()
нельзя использовать, если на регион виртуальной памяти отображен буфер MDL, буфер DMA или регион памяти MMIO.
Чтобы освободить регион виртуальной памяти, нужно вызвать функцию KnVmUnmap()
. В результате вызова этой функции зарезервированные страницы становятся свободными независимо от того, зафиксированы они или нет, а также освобождается физическая память, отображенная на зафиксированные страницы.
Функция KnVmUnmap()
освобождает виртуальные адреса региона, на который отображен буфер MDL, но не удаляет буфер MDL. Также эту функцию нельзя использовать, если на регион виртуальной памяти отображен буфер DMA или регион памяти MMIO.
Функции KnVmCommit()
, KnVmProtect()
, KnVmDecommit()
, KnVmReset()
и KnVmUnmap()
можно применять как для всего выделенного региона виртуальной памяти, так и для его части.
Приведенные в этом разделе функции являются базой для реализации функций выделения и освобождения памяти библиотеки libkos, а также таких интерфейсов POSIX, как malloc()
, calloc()
, realloc()
, free()
, mmap()
, munmap()
.
Сведения о функциях API
Функции vmm_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Выделяет (резервирует и опционально фиксирует) регион виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает базовый адрес выделенного региона виртуальной памяти, иначе возвращает Дополнительные сведения В параметре
Допустимые комбинации флагов, задающих права доступа к региону виртуальной памяти:
|
|
Назначение Фиксирует регион виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отменяет фиксацию региона виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Изменяет права доступа к региону виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Освобождает регион виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о странице виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отменяет фиксацию региона виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
Создание разделяемой памяти
Сведения о функциях API приведены в таблице ниже.
Использование API
Для создания разделяемой памяти используется буфер MDL. Буфер MDL – это буфер, состоящий из одного или нескольких регионов физической памяти, которые могут быть отображены на память нескольких процессов одновременно. Для отображения буфера MDL на память процесса используется объект ядра – таблица описания памяти. Таблица описания памяти (англ. Memory Descriptor List, MDL) – структура данных, содержащая адреса и размеры регионов физической памяти, из которых состоит буфер MDL. Дескриптор буфера MDL идентифицирует таблицу описания памяти.
Чтобы создать разделяемую память, процессу нужно создать буфер MDL, отобразить его на свою память и передать дескриптор буфера MDL через IPC другим процессам, которым также нужно отобразить этот буфер MDL на свою память.
Чтобы создать буфер MDL, нужно вызвать функцию KnPmmMdlCreate()
, KnPmmMdlCreateFromBuf()
или KnPmmMdlCreateFromVm()
. Функция KnPmmMdlCreateFromBuf()
создает буфер MDL и копирует в него данные. Функция KnPmmMdlCreateFromVm()
создает буфер MDL и отображает его на память вызывающего процесса.
Чтобы зарезервировать регион виртуальной памяти и отобразить на него буфер MDL, нужно вызвать функцию KnPmmMdlMap()
. Буфер MDL можно отобразить на несколько регионов виртуальной памяти одного процесса.
Буфер MDL можно использовать для передачи больших объемов данных между процессами без создания разделяемой памяти. В этом случае необходимо обеспечить, чтобы буфер MDL не отображался на память нескольких процессов одновременно. Взаимодействующие процессы должны поочередно отображать буфер MDL в свою память, считывать и/или записывать данные и освобождать регион виртуальной памяти, на который отображен этот буфер MDL.
Модуль безопасности Kaspersky Security Module не может контролировать данные, которые передаются между процессами через буфер MDL.
Удаление буфера MDL
Чтобы удалить буфер MDL, нужно выполнить следующие шаги:
- Освободить регионы виртуальной памяти, на которые отображается буфер MDL, во всех процессах, которые используют этот буфер MDL.
Чтобы выполнить этот шаг, нужно использовать функцию
KnVmUnmap()
. - Закрыть или отозвать каждый дескриптор буфера MDL во всех процессах, которые владеют этими дескрипторами.
Чтобы выполнить этот шаг, нужно использовать функцию
KnHandleClose()
и/илиKnHandleRevoke()
, которые объявлены в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Сведения о функциях API
Функции vmm_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает буфер MDL. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Создает буфер MDL из физической памяти, отображенной на заданный регион виртуальной памяти, и отображает созданный буфер MDL на этот регион. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функцию можно использовать, если заданный регион виртуальной памяти выделен с фиксацией. В параметре
|
|
Назначение Создает буфер MDL и копирует в него данные из заданного буфера. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Позволяет получить размер буфера MDL. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Резервирует регион виртуальной памяти и отображает на него буфер MDL. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
Допустимые комбинации флагов, задающих права доступа к региону виртуальной памяти:
|
|
Назначение Создает буфер MDL на основе существующего. Буфер MDL создается из тех же регионов физической памяти, что и оригинальный. Параметры
Возвращаемые значения В случае успеха возвращает |
Подготовка сегментов ELF-образа к загрузке в память процесса
Сведения о функциях API приведены в таблице ниже.
Использование API
Буферы MDL используются не только для создания разделяемой памяти, но и для загрузки сегментов ELF-образа в память нового процесса. (Загрузку сегментов ELF-образа выполняет, например, инициализирующая программа Einit
.)
Функции KnVmSegInitFromVm()
и KnVmSegInitFromBuf()
создают буфер MDL и помещают в него сегмент ELF-образа для последующей загрузки этого сегмента в память нового процесса.
Удаление буферов MDL, содержащих сегменты ELF-образа
Чтобы буферы MDL, содержащие сегменты ELF-образа, были удалены, необходимо, чтобы завершился новый процесс, на память которого эти буферы MDL отображены. А также до или после завершения этого процесса нужно выполнить следующие шаги:
- Освободить регионы виртуальной памяти, на которые отображены буферы MDL, в процессе, который создал эти буферы MDL.
Этот шаг нужно выполнить только для тех буферов MDL, которые созданы с использованием функции
KnVmSegInitFromVm()
.Чтобы выполнить этот шаг, нужно использовать функцию
KnVmUnmap()
. - Закрыть дескрипторы буферов MDL в процессе, который создал эти буферы MDL.
Чтобы выполнить этот шаг, нужно использовать функцию
KnHandleClose()
, которая объявлена в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Сведения о функциях API
Функции vmm_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает буфер MDL из физической памяти, отображенной на заданный регион виртуальной памяти, который содержит сегмент ELF-образа. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функцию можно использовать, если заданный регион виртуальной памяти выделен с фиксацией. В параметре
|
|
Назначение Создает буфер MDL и копирует в него сегмент ELF-образа из заданного буфера. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
Выделение и освобождение памяти (alloc.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/alloc.h
из состава KasperskyOS SDK.
API предназначен для выделения и освобождения памяти. Выделенная память представляет собой зафиксированный регион виртуальной памяти, к которому разрешен доступ на чтение и запись.
Сведения о функциях API приведены в таблице ниже.
Функции alloc.h
Функция |
Сведения о функции |
---|---|
|
Назначение Выделяет память. Параметры
Возвращаемые значения В случае успеха возвращает указатель на выделенную память, иначе возвращает |
|
Назначение Выделяет память. Параметры
Возвращаемые значения В случае успеха возвращает указатель на выделенную памяти, иначе возвращает |
|
Назначение Выделяет память и инициализирует ее нулями. Параметры
Возвращаемые значения В случае успеха возвращает указатель на выделенную память, иначе возвращает |
|
Назначение Освобождает память. Параметры
Возвращаемые значения Нет. |
|
Назначение Выделяет память и опционально копирует во вновь выделенную память содержимое ранее выделенной памяти, освобождая после копирования ранее выделенную память. Параметры
Возвращаемые значения В случае успеха возвращает указатель на выделенную память, иначе возвращает |
|
Назначение Выделяет память и опционально копирует во вновь выделенную память содержимое ранее выделенной памяти, освобождая после копирования ранее выделенную память. Параметры
Возвращаемые значения В случае успеха возвращает указатель на выделенную память, иначе возвращает |
Использование DMA (dma.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/dma.h
из состава KasperskyOS SDK.
API предназначен для организации обмена данными между устройствами и оперативной памятью в режиме прямого доступа к памяти (англ. Direct Memory Access, DMA), при котором процессор не используется.
Сведения о функциях API приведены в таблице ниже.
Использование API
Типовой сценарий использования API включает следующие шаги:
- Создание буфера DMA.
Буфер DMA –это буфер, состоящий из одного или нескольких регионов физической памяти (блоков), используемых для DMA. Буфер DMA, состоящий из нескольких блоков, можно использовать, если устройство поддерживает режим "scatter/gather DMA". Буфер DMA, состоящий из одного блока, можно использовать, если устройство поддерживает режим "scatter/gather DMA" или "continuous DMA". Вероятность создать буфер DMA, состоящий из одного большого блока, ниже, чем вероятность создать буфер DMA, состоящий из нескольких небольших блоков. Это особенно актуально при высокой фрагментации физической памяти.
Если устройство поддерживает только режим "continuous DMA", то даже при задействовании IOMMU нужно использовать буфер DMA, состоящий из одного блока.
Чтобы выполнить этот шаг, нужно вызвать функцию
KnIoDmaCreate()
илиKnIoDmaCreateContinuous()
. ФункцияKnIoDmaCreateContinuous()
создает буфер DMA, состоящий из одного блока. ФункцияKnIoDmaCreate()
создает буфер DMA, состоящий из одного блока, если значение 2^order равно значению size/размер страницы памяти, или значение 2^order является ближайшим большим к значению size/размер страницы памяти в упорядоченном по возрастанию множестве {2^(order-1);size/размер страницы памяти;2^order}. Если значение size/размер страницы памяти больше значения 2^order, функцияKnIoDmaCreate()
может создать буфер DMA, состоящий из нескольких блоков.Дескриптор буфера DMA можно передать другому процессу через IPC.
- Отображение буфера DMA на память процессов.
Один буфер DMA может быть отображен на несколько регионов виртуальной памяти одного или нескольких процессов, которые владеют дескриптором этого буфера DMA. В результате отображения процессы получают доступ к буферу DMA на чтение и/или запись.
Чтобы зарезервировать регион виртуальной памяти и отобразить на него буфер DMA, нужно вызвать функцию
KnIoDmaMap()
.Дескриптор, полученный при вызове функции
KnIoDmaMap()
, нельзя передать другому процессу через IPC. - Открытие доступа к буферу DMA для устройства вызовом функции
KnIoDmaBegin()
илиKnIoDmaBeginEx()
.Вызов функции
KnIoDmaBegin()
илиKnIoDmaBeginEx()
необходим, чтобы создать объект ядра, содержащий адреса и размеры блоков, из которых состоит буфер DMA. Эти сведения необходимы устройству, чтобы использовать буфер DMA. Устройство может работать как с физическими, так и с виртуальными адресами в зависимости от того, задействован ли IOMMU. Если IOMMU задействован, нужно использовать функциюKnIoDmaBegin()
илиKnIoDmaBeginEx()
, и объект будет содержать виртуальные и физические адреса блоков. Если IOMMU не задействован, нужно использовать функциюKnIoDmaBegin()
, и объект будет содержать только физические адреса блоков.При задействовании IOMMU устройство должно быть прикреплено к домену IOMMU.
Дескриптор, полученный при вызове функции
KnIoDmaBegin()
илиKnIoDmaBeginEx()
, нельзя передать другому процессу через IPC. - Получение сведений о буфере DMA.
На этом шаге нужно получить адреса и размеры блоков из объекта ядра, созданного вызовом функции
KnIoDmaBegin()
илиKnIoDmaBeginEx()
. Полученные адреса и размеры в дальнейшем требуется передать устройству, используя, например, MMIO. После получения этих сведений устройство может записывать в буфер DMA и/или читать из него.Чтобы выполнить этот шаг, нужно вызвать одну из следующих функций:
KnIoDmaGetInfo()
;KnIoDmaGetPhysInfo()
;KnIoDmaContinuousGetDmaAddr()
;KnIoDmaContinuousGetPhysAddr()
.
Функции
KnIoDmaGetInfo()
иKnIoDmaGetPhysInfo()
позволяют получить номер страницы памяти (frame
) и порядок (order
) для каждого блока. (Номер страницы памяти, умноженный на размер страницы памяти, дает адрес блока. Значение 2^order представляет собой размер блока в страницах памяти.) Через выходной параметрoutInfo
эти функции передают объектKosObject
, который содержит структуру со сведениями о буфере DMA (об объектахKosObject
см. "Использование объектов KosObject (objects.h)"). Тип структуры определен в заголовочном файлеsysroot-*-kos/include/io/io_dma.h
из состава KasperskyOS SDK. ФункцияKnIoDmaGetInfo()
заполняет данными все поля структуры, а функцияKnIoDmaGetPhysInfo()
заполняет данными только поляcount
иdescriptors
, записывая в остальные поля нули. При использовании функцииKnIoDmaGetInfo()
массивdescriptors
содержит номера виртуальных страниц памяти, если IOMMU задействован, и номера физических страниц памяти, если IOMMU не задействован. При использовании функцииKnIoDmaGetPhysInfo()
массивdescriptors
содержит номера физических страниц памяти независимо от того, задействован IOMMU или нет.Функции
KnIoDmaContinuousGetDmaAddr()
иKnIoDmaContinuousGetPhysAddr()
можно использовать, если буфер DMA состоит из одного блока. Эти функции позволяет получить адрес блока. (В качестве размера блока нужно принять размер буфера DMA, заданный при его создании.) ФункцияKnIoDmaContinuousGetDmaAddr()
передает через выходной параметрaddr
виртуальный адрес, если IOMMU задействован, и физический адрес, если IOMMU не задействован. ФункцияKnIoDmaContinuousGetPhysAddr()
передает через выходной параметрaddr
физический адрес независимо от того, задействован IOMMU или нет.На Raspberry Pi 4 B функция
KnIoDmaGetPhysInfo()
позволяет получить действительные номера физических страниц, а функцияKnIoDmaGetInfo()
позволяет получить номера физических страниц со смещением, обусловленным тем, что некоторые устройства используют при DMA трансляцию VPU (Visual Processing Unit). Аналогично функцииKnIoDmaContinuousGetPhysAddr()
иKnIoDmaContinuousGetDmaAddr()
позволяют получить действительный и смещенный физический адрес соответственно.
Закрытие доступа к буферу DMA для устройства
Закрыть доступ к буферу DMA для устройства можно только при задействовании IOMMU. Если удалить объект ядра, созданный при вызове функции KnIoDmaBegin()
или KnIoDmaBeginEx()
, то доступ устройства к буферу DMA будет закрыт. Чтобы удалить этот объект, нужно закрыть его дескриптор.
Удаление буфера DMA
Чтобы удалить буфер DMA, нужно выполнить следующие шаги:
- Освободить регионы виртуальной памяти, зарезервированные при вызовах функции
KnIoDmaMap()
.Чтобы выполнить этот шаг, нужно закрыть дескрипторы, которые были получены при вызовах функции
KnIoDmaMap()
.Этот шаг нужно выполнить для всех процессов, на память которых отображен буфер DMA.
- Удалить объект ядра, созданный вызовом функции
KnIoDmaBegin()
илиKnIoDmaBeginEx()
.Чтобы выполнить этот шаг, нужно закрыть дескриптор, который был получен при вызове функции
KnIoDmaBegin()
илиKnIoDmaBeginEx()
. - Закрыть или отозвать каждый дескриптор буфера DMA во всех процессах, которые владеют этими дескрипторами.
Сведения о функциях API
Функции dma.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает буфер DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Создает буфер DMA, состоящий из одного блока. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Резервирует регион виртуальной памяти и отображает на него буфер DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Изменяет параметры кеширования буфера DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функцию можно использовать, если выполняются следующие условия:
В параметре
|
|
Назначение Позволяет получить сведения о буфере DMA. Сведения включают адреса и размеры блоков. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Чтобы удалить объект, полученный через параметр |
|
Назначение Позволяет получить физические адреса и размеры блоков буфера DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Чтобы удалить объект, полученный через параметр |
|
Назначение Позволяет получить адрес блока для буфера DMA, состоящего из одного блока. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить физический адрес блока для буфера DMA, состоящего из одного блока. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Открывает доступ к буферу DMA для устройства. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Открывает доступ к буферу DMA для устройства. Параметры
Возвращаемые значения В случае успеха возвращает |
Ввод-вывод через память (mmio.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/mmio.h
из состава KasperskyOS SDK.
API предназначен для работы с памятью MMIO. Память MMIO – это физические адреса, на которые отображены регистры и память устройств. (Для адресации физической памяти и доступа к регистрам и памяти устройств используются части одного пространства физических адресов.)
Сведения о функциях API приведены в таблице ниже.
Использование API
Типовой сценарий использования API включает следующие шаги:
- Регистрация региона памяти MMIO, соответствующего устройству, с которым нужно работать.
Чтобы выполнить этот шаг, нужно вызвать функцию
KnRegisterPhyMem()
.Дескриптор региона памяти MMIO можно передать другому процессу через IPC.
- Отображение региона памяти MMIO на память процесса.
В один момент времени регион памяти MMIO может быть отображен только на один регион виртуальной памяти только одного процесса. (В разные моменты времени регион памяти MMIO может отображаться на виртуальную память разных процессов, владеющих дескриптором этого региона.) В результате отображения процесс получает доступ к региону памяти MMIO на чтение и/или запись.
Чтобы зарезервировать регион виртуальной памяти и отобразить на него регион памяти MMIO, нужно вызвать функцию
KnIoMapMem()
.Дескриптор, полученный при вызове функции
KnIoMapMem()
, нельзя передать другому процессу через IPC. - Чтение данных из региона памяти MMIO и запись данных в него через память процесса.
8-, 16- и 32-битные слова, считанные из региона памяти MMIO или записанные в него, представляют собой значения регистров устройства или содержимое памяти устройства.
Чтобы выполнить этот шаг, нужно использовать функции
IoReadMmReg8|16|32()
,IoReadMmBuffer8|16|32()
,IoWriteMmReg8|16|32()
,IoWriteMmBuffer8|16|32()
.
Дерегистрация региона памяти MMIO
Чтобы дерегистрировать регион памяти MMIO, нужно выполнить следующие шаги:
- Освободить регион виртуальной памяти, выделенный при вызове функции
KnIoMapMem()
.Чтобы выполнить этот шаг, нужно вызвать функцию
KnHandleClose()
, указав дескриптор, который был получен при вызове функцииKnIoMapMem()
. (ФункцияKnHandleClose()
объявлена в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.) - Закрыть или отозвать каждый дескриптор региона памяти MMIO во всех процессах, которые владеют этими дескрипторами.
Чтобы выполнить этот шаг, нужно использовать функцию
KnHandleClose()
и/илиKnHandleRevoke()
, которые объявлены в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Сведения о функциях API
Функции mmio.h
Функция(и) |
Сведения о функции(ях) |
---|---|
|
Назначение Регистрирует регион памяти MMIO. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Резервирует регион виртуальной памяти и отображает на него регион памяти MMIO. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
В параметре
|
|
Назначение Позволяют получить 8-, 16- или 32-битное слово из региона памяти MMIO. Параметры
Возвращаемые значения 8-, 16- или 32-битное слово из региона памяти MMIO. |
|
Назначение Сохраняют в буфер последовательность 8-, 16-или 32-битных слов из региона памяти MMIO. Параметры
Возвращаемые значения Нет. Дополнительные сведения Функции можно использовать, если процессор имеет архитектуру x86 или x86-64. |
|
Назначение Записывают 8-, 16- или 32-битное слово в регион памяти MMIO. Параметры
Возвращаемые значения Нет. |
|
Назначение Записывают в регион памяти MMIO последовательность 8-, 16-или 32-битных слов из буфера. Параметры
Возвращаемые значения Нет. Дополнительные сведения Функции можно использовать, если процессор имеет архитектуру x86 или x86-64. |
Управление обработкой прерываний (irq.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/irq.h
из состава KasperskyOS SDK.
API позволяет управлять обработкой аппаратных прерываний. Аппаратное прерывание – это сигнал процессору от устройства о необходимости немедленно переключиться с исполнения текущей программы на обработку события, связанного с этим устройством. Например, нажатие клавиши на клавиатуре вызывает аппаратное прерывание, которое обеспечивает требуемую реакцию на это нажатие (к примеру, ввод символа).
Аппаратное прерывание возникает при обращении устройства к контроллеру прерываний. Это обращение может осуществляться через линию аппаратного прерывания между устройством и контроллером прерываний или через память MMIO. Во втором случае устройство выполняет запись в память MMIO, вызывая прерывание MSI (англ. Message Signaled Interrupt).
В настоящее время функции для управления обработкой прерываний MSI не реализованы.
Каждой линии аппаратного прерывания соответствует одно прерывание с уникальным номером.
Сведения о функциях API приведены в таблице ниже.
Использование API
Чтобы связать прерывание с его обработчиком, нужно выполнить следующие шаги:
- Регистрация прерывания вызовом функции
KnRegisterIrq()
.Одно прерывание можно зарегистрировать несколько раз в одном или нескольких процессах.
Дескриптор прерывания можно передать другому процессу через IPC.
- Привязка потока исполнения к прерыванию вызовом функции
KnIoAttachIrq()
.Этот шаг выполняется потоком исполнения, в контексте которого будет выполняться обработка прерывания.
Используя дескриптор, полученный при вызове функции
KnRegisterIrq()
, можно привязать к прерыванию только один поток исполнения. Чтобы привязать к прерыванию несколько потоков исполнения в одном или нескольких процессах, нужно использовать разные дескрипторы этого прерывания, полученные при отдельных вызовах функцииKnRegisterIrq()
. В этом случае функциюKnIoAttachIrq()
нужно вызывать с одними и теми же флагами в параметреflags
.Дескриптор, полученный при вызове функции
KnIoAttachIrq()
, нельзя передать другому процессу через IPC.
Чтобы запретить (маскировать) прерывание, нужно вызвать функцию KnIoDisableIrq()
. Чтобы разрешить (демаскировать) прерывание, нужно вызвать функцию KnIoEnableIrq()
. И хотя эти функции принимают дескриптор прерывания, через который к прерыванию привязан только один поток исполнения, их действие распространяется на все потоки исполнения, привязанные к этому прерыванию. Эти функции нужно вызывать вне потоков исполнения, привязанных к прерыванию. После регистрации прерывания и привязки к нему потока исполнения это прерывание не требуется демаскировать.
Чтобы инициировать отвязывание потока исполнения от прерывания, нужно вызвать функцию KnIoDetachIrq()
вне потока исполнения, привязанного к прерыванию. Отвязывание выполняет поток исполнения, привязанный к прерыванию, вызовом функции KnThreadDetachIrq()
, объявленной в заголовочном файле sysroot-*-kos/include/coresrv/thread/thread_api.h
. из состава KasperskyOS SDK.
Обработка прерывания
После выполнения привязки к прерыванию поток исполнения вызывает функцию Call()
, объявленную в заголовочном файле sysroot-*-kos/include/coresrv/syscalls.h
из состава KasperskyOS SDK. В результате этого вызова поток исполнения блокируется. При возникновении прерывания или вызове функции KnIoDetachIrq()
ядро KasperskyOS отправляет IPC-сообщение процессу, содержащему этот поток. Это IPC-сообщение содержит запрос на обработку прерывания или запрос на отвязывание потока исполнения от прерывания. Когда процесс получает IPC-сообщение, функция Call()
в потоке исполнения, привязанном к прерыванию, возвращает управление и предоставляет потоку содержимое IPC-сообщения. Поток исполнения извлекает из IPC-сообщения запрос и обрабатывает прерывание либо выполняет отвязывание от прерывания. Если выполняется обработка прерывания, то по ее завершении сведения об успехе или неуспехе обработки добавляются в ответное IPC-сообщение, которое отправляется ядру следующим вызовом функции Call()
в цикле.
При обработке прерывания нужно использовать функции IoGetIrqRequest()
и IoSetIrqAnswer()
, которые объявлены в заголовочном файле sysroot-*-kos/include/io/io_irq.h
из состава KasperskyOS SDK. Эти функции позволяют извлекать из IPC-сообщений и добавлять в IPC-сообщения данные для информационного обмена между ядром и потоком исполнения, привязанным к прерыванию.
Типовой цикл обработки прерывания включает следующие шаги:
- Добавление в IPC-сообщение, которое будет отправлено ядру, сведений об успехе или неуспехе обработки прерывания вызовом функции
IoSetIrqAnswer()
. - Отправка IPC-сообщения ядру и получение IPC-сообщения от ядра.
Чтобы выполнить этот шаг, нужно вызвать функции
Call()
. В параметреhandle
требуется указать дескриптор, полученный при вызове функцииKnIoAttachIrq()
. Через параметрmsgOut
необходимо задать IPC-сообщение, которое будет отправлено ядру, а через параметрmsgIn
необходимо задать IPC-сообщение, которое будет получено от ядра. - Извлечение запроса из IPC-сообщения, полученного от ядра, вызовом функции
IoGetIrqRequest()
. - Обработка прерывания или отвязывание от прерывания в зависимости от запроса.
Если запрос требует выполнить отвязывание от прерывания, то нужно выйти из цикла обработки прерывания и вызвать функцию
KnThreadDetachIrq()
.
Дерегистрация прерывания
Чтобы дерегистрировать прерывание, нужно выполнить следующие шаги:
- Выполнить отвязывание потока исполнения от прерывания.
Чтобы выполнить этот шаг, нужно вызвать функцию
KnThreadDetachIrq()
. - Закрыть дескриптор, полученный при вызове функции
KnIoAttachIrq()
.Чтобы выполнить этот шаг, нужно вызвать функцию
KnHandleClose()
. (ФункцияKnHandleClose()
объявлена в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.) - Закрыть или отозвать каждый дескриптор прерывания во всех процессах, которые владеют этими дескрипторами.
Чтобы выполнить этот шаг, нужно использовать функцию
KnHandleClose()
и/илиKnHandleRevoke()
, которые объявлены в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Одно прерывание может быть зарегистрировано несколько раз, а выполнение этих шагов аннулирует только одну регистрацию. Оставшиеся регистрации продолжают действовать. Каждую регистрацию одного прерывания нужно аннулировать отдельно.
Сведения о функциях API
Функции irq.h
Функция |
Сведения о функции |
---|---|
|
Назначение Регистрирует прерывание. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Привязывает вызывающий поток исполнения к прерыванию. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Отправляет потоку исполнения запрос, в результате выполнения которого поток должен выполнить отвязывание от прерывания. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Разрешает (демаскирует) прерывание. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Запрещает (маскирует) прерывание. Параметры
Возвращаемые значения В случае успеха возвращает |
Управление потоками исполнения (высокоуровневый API thread.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/thread.h
из состава KasperskyOS SDK.
Основные возможности API:
- создавать, завершать, блокировать потоки исполнения;
- возобновлять исполнение заблокированных потоков;
- регистрировать функции, вызываемые при создании и завершении потоков исполнения.
Сведения о функциях API приведены в таблице ниже.
Библиотека libkos
также предоставляет низкоуровневый API для управления потоками исполнения, который определен в заголовочном файле sysroot-*-kos/include/coresrv/thread/thread_api.h
из состава KasperskyOS SDK. Низкоуровневый API следует использовать, если только недостаточно возможностей высокоуровневого API.
Создание потоков исполнения
Чтобы создать поток исполнения, нужно вызвать функцию KosThreadCreate()
или KosThreadCreateDetached()
. Эти функции создают стандартный поток исполнения, приоритет которого может принимать значения от 0 до 15. (О стандартных потоках исполнения см. "Управление потоками исполнения (низкоуровневый API thread_api.h)".)
Завершение потоков исполнения
Завершение потока исполнения представляет собой его перманентное удаление из планировщика. Поток исполнения завершается в следующих случаях:
- Осуществлен выход из функции, выполняемой потоком исполнения.
Должен быть осуществлен выход оператором
return
из корневой (не из вложенной) функции, выполняемой потоком исполнения. - Вызвана функция
KosThreadTerminate()
илиKosThreadExit()
.Функция
KosThreadExit()
завершает поток исполнения, даже если вызвана не из корневой функции, выполняемой потоком исполнения, а из вложенной. - Завершился или перешел в "замороженное" состояние процесс.
О "замороженном" состоянии процесса см. "Управление процессами (низкоуровневый API task_api.h)".
Коды завершения потоков исполнения определяются разработчиком решения на базе KasperskyOS. Эти коды нужно указывать в параметре exitCode
функций KosThreadTerminate()
и KosThreadExit()
, а также при вызове оператора return
в функции, выполняемой потоком исполнения. Чтобы получить код завершения потока исполнения, нужно вызвать функцию KosThreadWait()
. В случае успеха эта функция возвращает код завершения потока исполнения, иначе возвращает -1
, поэтому коды завершения потоков исполнения должны быть отличными от -1
, чтобы избежать неоднозначности.
Регистрация функций, вызываемых при создании и завершении потоков исполнения
Чтобы зарегистрировать функцию, вызываемую при создании и завершении потоков процесса, нужно вызвать из этого процесса функцию KosThreadCallbackRegister()
.
Зарегистрированная функция вызывается в следующих случаях:
- при создании потока исполнения вызовом функции
KosThreadCreate()
; - при завершении потока исполнения, созданного вызовом функции
KosThreadCreate()
, в результате выхода из функции, выполняемой этим потоком; - при завершении потока исполнения вызовом функции
KosThreadExit()
.
Можно зарегистрировать несколько функций, и каждая из них будет вызвана при создании и завершении потока исполнения. При создании потока исполнения зарегистрированная функция вызывается с аргументом KosThreadCallbackReasonCreate
в параметре reason
. При завершении потока исполнения зарегистрированная функция вызывается с аргументом KosThreadCallbackReasonDestroy
в параметре reason
.
Гарантирование невозможности вызвать функцию несколько раз
Только при первом вызове функции KosThreadOnce()
вызывается заданная через параметр initRoutine
callback-функция. При повторных вызовах функции KosThreadOnce()
(даже из других потоков исполнения) этого не происходит, и функция KosThreadOnce()
просто возвращает управление. Например, это обеспечивает однократную инициализацию драйвера, в том случае, когда несколько программных компонентов используют этот драйвер и запускают его инициализацию независимо друг от друга.
Особенности потоков исполнения, привязанных к прерываниям
После привязки к прерыванию поток исполнения становится потоком исполнения реального времени с классом планирования FIFO и приоритетом выше 31. (О привязке потока исполнения к прерыванию см. "Управление обработкой прерываний (irq.h)". О классе планирования потоков реального времени FIFO см. "Управление потоками исполнения (низкоуровневый API thread_api.h)".)
Для потоков исполнения, привязанных к прерываниям, нельзя применять многие функции API, в том числе KosThreadCreate()
, KosThreadSuspend()
, KosThreadResume()
, KosThreadTerminate()
, KosThreadWait()
, KosThreadSleep()
, KosThreadYield()
.
Задание и получение базового адреса TLS потоков исполнения
Локальная память потока исполнения (англ. Thread Local Storage, TLS) – это память процесса, где поток исполнения может хранить данные изолированно от других потоков исполнения. Задать и получить базовый адрес TLS позволяют функции KosThreadTlsSet()
и KosThreadTlsGet()
соответственно. Эти функции предназначены для использования библиотекой libc
.
Получение базового адреса и размера стека потоков исполнения
Получить базовый адрес и размер стека потока исполнения позволяет функция KosThreadGetStack()
. Эта функция предназначена для использования библиотекой libc
.
Освобождение ресурсов завершившихся потоков исполнения
Ресурсами потока исполнения являются его стек, контекст и TCB (о TCB см. "Управление потоками исполнения (низкоуровневый API thread_api.h)"). Чтобы ресурсы потока исполнения были освобождены после его завершения, нужно вызвать функцию KosThreadWait()
для ожидания завершения этого потока исполнения. (Исключением являются начальный поток процесса и поток исполнения, созданный функцией KosThreadCreateDetached()
.) Также ресурсы потоков исполнения освобождаются при завершении процесса, в который они входят.
Сведения о функциях API
Функции thread.h
Функция |
Сведения о функции |
---|---|
|
Назначение Регистрирует функцию, вызываемую при создании и завершении потоков исполнения вызывающего процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Дерегистрирует функцию, вызываемую при создании и завершении потоков исполнения вызывающего процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает незаблокированный поток исполнения и закрывает его дескриптор. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить идентификатор (TID) вызывающего потока исполнения. Параметры Нет. Возвращаемые значения Идентификатор потока исполнения. Тип идентификатора определен в заголовочном файле |
|
Назначение Блокирует вызывающий поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Возобновляет исполнение заблокированного потока. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает вызывающий поток исполнения. Параметры
Возвращаемые значения Нет. |
|
Назначение Блокирует вызывающий поток исполнения до завершения заданного потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает код завершения потока исполнения, иначе возвращает |
|
Назначение Блокирует вызывающий поток исполнения на заданное время. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отдает квант времени вызывающего потока исполнения следующему в очереди. Параметры Нет. Возвращаемые значения Нет. Дополнительные сведения Вызов функции |
|
Назначение Завершает поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить базовый адрес локальной памяти потока исполнения (TLS) для вызывающего потока исполнения. Параметры Нет. Возвращаемые значения Указатель на TLS или |
|
Назначение Задает базовый адрес локальной памяти потока исполнения (TLS) для вызывающего потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить базовый адрес и размер стека потока исполнения. Параметры
Возвращаемые значения Указатель на стек потока исполнения. |
|
Назначение Гарантирует, что заданная функция будет вызвана только один раз. Параметры
Возвращаемые значения В случае успеха возвращает |
Управление потоками исполнения (низкоуровневый API thread_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/thread/thread_api.h
из состава KasperskyOS SDK.
Основные возможности API:
- создавать, завершать, блокировать потоки исполнения;
- возобновлять исполнение заблокированных потоков;
- изменять приоритеты и классы планирования потоков исполнения;
- обрабатывать исключения;
- отвязывать потоки исполнения от прерываний;
- выполнять привязку потоков исполнения к процессорам (вычислительным ядрам).
Функции API, которые принимают на вход или возвращают идентификатор потока исполнения (TID), являются устаревшими и в будущем будут удалены. Эти функции не описаны в этом разделе.
Сведения о функциях API приведены в таблице ниже.
Библиотека libkos
также предоставляет высокоуровневый API для управления потоками исполнения, который определен в заголовочном файле sysroot-*-kos/include/kos/thread.h
из состава KasperskyOS SDK. Рекомендуется использовать именно этот API. Низкоуровневый API следует использовать, если недостаточно возможностей высокоуровневого API.
Создание потоков исполнения. Классы планирования потоков исполнения
Чтобы создать поток исполнения, нужно вызвать функцию KnThreadCreateByHandle()
. Через параметр flags
этой функции для создаваемого потока исполнения можно задать следующие классы планирования:
- класс планирования стандартных потоков;
- класс планирования потоков реального времени FIFO (англ. First In, First Out);
- класс планирования потоков реального времени RR (англ. Round-Robin).
Приоритет стандартного потока исполнения может принимать значения от 0 до 15. Чем выше приоритет стандартного потока исполнения, тем больше размер квантов времени, выделяемых этому потоку, и тем чаще эти кванты выделяются. Один стандартный поток исполнения с высоким приоритетом может занимать несколько мест подряд в очереди потоков исполнения. Стандартные потоки исполнения не могут вытеснять другие стандартные потоки исполнения, а также потоки исполнения реального времени независимо от соотношения приоритетов. Если в очереди появляется поток исполнения реального времени, то текущий стандартный поток исполнения немедленно передает ему управление. Если в очереди нет потоков исполнения реального времени, то текущий стандартный поток исполнения передает управление следующему, если завершился, стал заблокированным, исчерпал свой квант времени или отдал его следующему.
Приоритет потока исполнения реального времени может принимать значения от 0 от 31. Более приоритетные потоки исполнения реального времени вытесняют менее приоритетные. Также потоки исполнения реального времени вытесняют стандартные потоки исполнения независимо от соотношения приоритетов. Передача управления от текущего потока исполнения реального времени следующему в очереди осуществляется в следующих случаях:
- Текущий поток исполнения реального времени с классом планирования FIFO завершился или стал заблокированным, либо в очереди появился поток исполнения реального времени с более высоким приоритетом.
Пока поток исполнения реального времени с классом планирования FIFO не будет завершен, заблокирован или вытеснен потоком исполнения реального времени с более высоким приоритетом, он может сколь угодно долго не передавать управление следующему.
- Текущий поток исполнения реального времени с классом планирования RR завершился, стал заблокированным или исчерпал свой квант времени, либо в очереди появился поток исполнения реального времени с более высоким приоритетом.
Поток исполнения реального времени с классом планирования RR, который не был завершен, заблокирован или вытеснен потоком исполнения реального времени с более высоким приоритетом, передает управление следующему по истечении своего кванта времени, если следующий является потоком исполнения реального времени с таким же приоритетом. В противном случае осуществляется передача управления снова себе.
- Текущий поток исполнения реального времени отдал свой квант времени следующему в очереди потоку исполнения реального времени с таким же приоритетом.
Поток исполнения реального времени может отдать свой квант времени следующему, если следующий является потоком исполнения реального времени с таким же приоритетом. В противном случае осуществляется передача управления снова себе.
Исполнение потоков реального времени с более низким приоритетом начинается только после того, как каждый из потоков реального времени с более высоким приоритетом завершился или стал заблокированным. Потоки исполнения реального времени с одним приоритетом образуют очередь по принципу FIFO.
Класс планирования потока исполнения можно изменить вызовом функции KnThreadSetSchedPolicyByHandle()
. Также эта функция позволяет изменить размер кванта времени, выделенного потоку исполнения реального времени с классом планирования RR. Это значение является единственным параметром класса планирования потоков реального времени RR, который по умолчанию имеет значение 10 мс, но может принимать значения от 2 мс до 100 мс. Класс планирования стандартных потоков и класс планирования потоков реального времени FIFO не имеют параметров.
Приоритет потока исполнения можно изменить вызовом функции KnThreadSetSchedPolicyByHandle()
или KnThreadSetPriorityByHandle()
.
После привязки к прерыванию поток исполнения становится потоком исполнения реального времени с классом планирования FIFO и приоритетом выше 31 независимо от того, какой класс планирования и приоритет были у этого потока исполнения до привязки к прерыванию. (О привязке потока исполнения к прерыванию см. "Управление обработкой прерываний (irq.h)".)
Для потоков исполнения, привязанных к прерываниям, нельзя применять многие функции API, в том числе KnThreadCreateByHandle()
, KnThreadSetPriorityByHandle()
, KnThreadSuspendCurrent()
, KnThreadResumeByHandle()
, KnThreadTerminateByHandle()
, KnThreadWaitByHandle()
, KnSleep()
, KnThreadSetSchedPolicyByHandle()
.
Создание дескрипторов потоков исполнения
Дескриптор потока исполнения создается при создании потока исполнения вызовом функции KnThreadCreateByHandle()
. Также поток исполнения (в том числе начальный) может создать свой дескриптор вызовом функции KnThreadOpenCurrent()
.
Дескриптор потока исполнения нельзя передать другому процессу через IPC.
Обработка исключений
Чтобы зарегистрировать функцию обработки исключений для потока исполнения, нужно вызвать функцию KnThreadSetExceptionHandler()
. Эта функция дерегистрирует предыдущую функцию обработки исключений и возвращает ее идентификатор. Сохранив этот идентификатор, в дальнейшем можно снова зарегистрировать предыдущую функцию обработки исключений.
Чтобы получить сведения о последнем исключении потока исполнения, в обработчике исключений нужно вызвать функцию KnThreadGetLastException()
.
Отвязывание потоков исполнения от прерываний
Чтобы отвязать поток исполнения от прерывания, нужно вызвать функцию KnThreadDetachIrq()
. (Подробнее об использовании функции KnThreadDetachIrq()
см. "Управление обработкой прерываний (irq.h)".)
После отвязывания от прерывания поток исполнения получает класс планирования и приоритет, которые были у этого потока исполнения до привязки к прерыванию.
Привязка потоков исполнения к процессорам (вычислительным ядрам)
Чтобы ограничить набор процессоров (вычислительных ядер), которые могут быть использованы для исполнения потока, нужно задать для этого потока маску сходства. Маска сходства (англ. Affinity Mask) – битовая маска, указывающая на каких процессорах (вычислительных ядрах) должен исполняться поток.
Чтобы создавать, корректировать и выполнять другие операции с масками сходства, нужно использовать API, определенный в заголовочном файле sysroot-*-kos/include/rtl/cpuset.h
из состава KasperskyOS SDK.
Чтобы задать маску сходства потока исполнения, нужно вызвать функцию KnThreadSetAffinityByHandle()
.
Завершение потоков исполнения
Завершение потока исполнения представляет собой его перманентное удаление из планировщика. Поток исполнения завершается в следующих случаях:
- Осуществлен выход из функции, выполняемой потоком исполнения.
Должен быть осуществлен выход оператором
return
из корневой (не из вложенной) функции, выполняемой потоком исполнения. - Вызвана функция
KnThreadTerminateByHandle()
илиKnThreadExit()
.Функция
KnThreadExit()
завершает поток исполнения, даже если вызвана не из корневой функции, выполняемой потоком исполнения, а из вложенной. - Завершился или перешел в "замороженное" состояние процесс.
О "замороженном" состоянии процесса см. "Управление процессами (низкоуровневый API task_api.h)".
Коды завершения потоков исполнения определяются разработчиком решения на базе KasperskyOS . Эти коды нужно указывать в параметре code
функций KnThreadTerminateByHandle()
и KnThreadExit()
, а также при вызове оператора return
в функции, выполняемой потоком исполнения. Чтобы получить код завершения потока исполнения, нужно вызвать функцию KnThreadWaitByHandle()
.
Получение адреса TCB и задание базового адреса TLS потоков исполнения
Блок управления потоком исполнения (англ. Thread Control Block, TCB) – структура, содержащая сведения о потоке исполнения, которые используются ядром для управления этим потоком исполнения. Тип структуры определен в заголовочном файле sysroot-*-kos/include/thread/tcbpage.h
из состава KasperskyOS SDK. TCB содержит базовый адрес локальной памяти потока исполнения (TLS). Получить адрес TCB позволяет функция KnThreadGetTcb()
. Задать базовый адрес TLS позволяет функция KnThreadSetTls()
. Эти функции предназначены для использования библиотекой libc
.
Получение сведений о потоке исполнения
Получить базовый адрес и размер стека потока исполнения, а также идентификатор потока исполнения (TID) позволяет функция KnThreadGetInfoByHandle()
. Эта функция предназначена для использования библиотекой libc
.
Освобождение ресурсов завершившихся потоков исполнения
Ресурсами потока исполнения являются его стек, контекст и TCB. Чтобы ресурсы потока исполнения были освобождены после его завершения, нужно до или после завершения этого потока исполнения закрыть его дескриптор вызовом функции KnHandleClose()
, которая объявлена в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK. (Исключением является начальный поток процесса, ресурсы которого освобождаются без вызова функции KnHandleClose()
, если начальный поток не создавал свой дескриптор вызовом функции KnThreadOpenCurrent()
.) Также ресурсы потоков исполнения освобождаются при завершении процесса, в который они входят.
Сведения о функциях API
Функции thread_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
По умолчанию создается стандартный поток исполнения. Дескрипторы потоков исполнения нельзя передавать между процессами через IPC. |
|
Назначение Создает дескриптор вызывающего потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить приоритет потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает приоритет потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Блокирует вызывающий поток исполнения. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Возобновляет исполнение заблокированного потока. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает вызывающий поток исполнения. Параметры
Возвращаемые значения Код ошибки. |
|
Назначение Позволяет получить сведения о потоке исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Блокирует вызывающий поток исполнения до завершения заданного потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Блокирует вызывающий поток исполнения на заданное время. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить адрес блока управления потоком исполнения (TCB) для вызывающего потока исполнения. Параметры Нет. Возвращаемые значения Указатель на TCB. Тип данных для хранения TCB определен в заголовочном файле |
|
Назначение Задает базовый адрес локальной памяти потока исполнения (TLS) для вызывающего потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отвязывает вызывающий поток исполнения от прерывания, обрабатываемого в его контексте. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Регистрирует функцию обработки исключений для вызывающего потока исполнения. Параметры
Возвращаемые значения Идентификатор предыдущей зарегистрированной функции обработки исключений или |
|
Назначение Позволяет получить сведения о последнем исключении вызывающего потока исполнения. Параметры
Возвращаемые значения Нет. |
|
Назначение Позволяет получить маску сходства потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает маску сходства потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о классе планирования потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре В параметре |
|
Назначение Задает класс планирования и приоритет потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре В параметре |
Управление процессами (высокоуровневый API task.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/task.h
из состава KasperskyOS SDK.
API позволяет создавать, запускать и завершать процессы, а также статически создавать IPC-каналы и передавать дескрипторы.
Сведения о функциях API приведены в таблице ниже.
Библиотека libkos
также предоставляет низкоуровневый API для управления процессами, который определен в заголовочном файле sysroot-*-kos/include/coresrv/task/task_api.h
из состава KasperskyOS SDK. Низкоуровневый API следует использовать, если только недостаточно возможностей высокоуровневого API.
Создание процессов
Чтобы создать процесс, нужно вызвать одну из следующих функций:
KosTaskInitEx()
;KosTaskInit()
;KosTaskInitFromSegEx()
;KosTaskInitFromSeg()
;KosTaskLaunch()
.
Через входной параметр params
эти функции принимают параметры создаваемого процесса в виде структуры, содержащей следующие поля:
eiid
– указатель на имя класса процесса.endpointsCount
– число предоставляемых служб.Поле может иметь нулевое значение, если процесс не предоставляет службы.
endpoints
– указатель на массив структур, содержащих характеристики предоставляемых служб (имена и идентификаторы служб, имена интерфейсов).Тип структуры определен в заголовочном файле
sysroot-*-kos/include/services/handle/if_connection.h
из состава KasperskyOS SDK.Поле может иметь значение
RTL_NULL
, если процесс не предоставляет службы.args
– указатель на массив параметров запуска программы.Последним элементом массива должно быть значение
RTL_NULL
.envs
– указатель на массив переменных окружения программы.Последним элементом массива должно быть значение
RTL_NULL
.flags
– флаги:KOS_TASK_FLAGS_NONE
– отсутствие флагов.KOS_TASK_FLAG_DUMPABLE
– процесс переходит в "замороженное" состояние в результате необработанного исключения.О "замороженном" состоянии процесса см. "Управление процессами (низкоуровневый API task_api.h)".
componentTree
– указатель на структуру, содержащую сведения из формальной спецификации компонента решения.Тип структуры определен в заголовочном файле
sysroot-*-kos/include/nk/types.h
из состава KasperskyOS SDK. Эта структура является элементом автоматически генерируемого транспортного кода.Если поле имеет значение, отличное от
RTL_NULL
, то значения в поляхeiid
,endpointsCount
иendpoints
будут проигнорированы, а имя класса процесса и параметры предоставляемых служб (включая параметры служб вложенных компонентов) будут взяты из формальной спецификации компонента решения.
Функции KosTaskInitEx()
, KosTaskInit()
, KosTaskInitFromSegEx()
и KosTaskInitFromSeg()
через выходной параметр outTask
передают указатель на адрес объекта, описывающего дочерний процесс. Этот объект представляет собой структуру, которая создается в памяти как родительского, так и дочернего процесса. Разработчику решения на базе KasperskyOS не требуется выполнять операции с полями этой структуры, но указатель на нее нужно использовать в качестве идентификатора процесса при вызове функций API. Дочерний процесс может получить адрес описывающего его объекта вызовом функции KosTaskGetSelf()
.
Если для доступа к службам, предоставляемым серверным процессом, используются статически созданные IPC-каналы, то объект, описывающий этот серверный процесс, должен быть связан со структурами, содержащими сведения о службах из формальной спецификации компонента решения. Это необходимо, чтобы при создании статического IPC-канала клиентские процессы получили сведения о службах, предоставляемых серверным процессом. Чтобы связать объект, описывающий дочерний серверный процесс, со структурами, содержащими сведения о службах из формальной спецификации компонента решения, нужно передать эти сведения через поле componentTree
параметра params
при вызове функций KosTaskInit*()
или функции KosTaskLaunch()
. Серверный процесс, который уже запущен, может связать описывающий его объект со структурами, содержащими сведения о службах из формальной спецификации компонента решения, вызовом функции KosTaskSetComponentTree()
. Это требуется, если у запущенного серверного процесса нет родительского процесса.
При вызове функции KosTaskInitEx()
, KosTaskInit()
или KosTaskLaunch()
ELF-образ из заданного исполняемого файла в ROMFS загружается в память создаваемого процесса. Если ELF-образ содержит таблицу символов .symtab
и таблицу строк .strtab
, то они загружаются в память процесса. Используя эти таблицы, ядро получает имена функций для формирования данных обратной трассировки стека (сведений о стеке вызовов).
Чтобы получить сведения об ELF-образе, загруженном в память процесса, нужно вызвать функцию KosTaskGetElfSegs()
.
При вызове функции KosTaskInit()
или KosTaskLaunch()
в качестве имени процесса и имени исполняемого файла используется одно из следующих значений:
- Значение поля
eiid
, если значение поляcomponentTree
равноRTL_NULL
. - Имя класса процессов из формальной спецификации компонента решения, если значение поля
componentTree
отлично отRTL_NULL
.
Таким же образом эти значения применяются в качестве имени процесса и/или имени исполняемого файла, если вызвать функцию KosTaskInitEx()
или KosTaskInitFromSegEx()
со значением RTL_NULL
в параметре name
и/или параметре path
. И аналогично эти значения применяются в качестве имени процесса, если вызвать функцию KosTaskInitFromSeg()
со значением RTL_NULL
в параметре name
.
Для использования функций KosTaskInitFromSegEx()
и KosTaskInitFromSeg()
необходимо, чтобы заранее были созданы буферы MDL, которые содержат сегменты ELF-образа. Сегменты ELF-образа для загрузки в память создаваемого процесса нужно задать через параметр segs
.
Через параметры entry
и relocBase
функции KosTaskInitFromSegEx()
необходимо задать точку входа в программу и смещение загрузки ELF-образа соответственно. Точка входа в программу представляет собой сумму адреса, указанного в поле e_entry
заголовка ELF-образа, и смещения загрузки ELF-образа. Генерацию случайного смещения загрузки ELF-образа и расчет адреса точки входа в программу с учетом этого смещения выполняет функция KnElfCreateVmSegEx()
, объявленная в заголовочном файле sysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK. (Смещение загрузки ELF-образа должно быть случайным значением с целью поддержки ASLR. Об ASLR см. "Управление процессами (низкоуровневый API task_api.h)".)
С помощью функции KosTaskInitFromSegEx()
в память создаваемого процесса можно загрузить таблицу символов .symtab
и таблицу строк .strtab
, а также заголовок ELF-образа. Загрузку заголовка ELF-образа нужно выполнить, если требуется, чтобы данные из него были доступны в создаваемом процессе.
Данные, передаваемые функции KosTaskInitFromSegEx()
через параметры segs
, entry
, relocBase
и параметры, связанные с загрузкой таблицы символов .symtab
и таблицы строк .strtab
, подготавливаются функцией KnElfCreateVmSegEx()
, объявленной в заголовочном файле sysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK.
Функция KosTaskInitFromSeg()
является упрощенной версией функции KosTaskInitFromSegEx()
и не позволяет загружать в память процесса таблицу символов .symtab
, таблицу строк .strtab
и заголовок ELF-образа, а также не позволяет задавать смещение загрузки ELF-образа (устанавливает нулевое смещение).
Функция KosTaskLaunch()
создает и сразу запускает процесс без возможности статического создания IPC-каналов.
Статическое создание IPC-каналов
Перед запуском процессов можно создать IPC-каналы между ними. Между одним клиентским и одним серверным процессом можно создать несколько IPC-каналов с разными именами. Между одним серверным и несколькими клиентскими процессами можно создать IPC-каналы с одним именем.
Чтобы создать IPC-канал с именем, соответствующим имени класса серверного процесса, нужно вызвать функцию KosTaskConnect()
.
Чтобы создать IPC-канал с заданным именем, нужно вызывать функцию KosTaskConnectToService()
.
Чтобы использовать созданный IPC-канал, на стороне клиентского процесса нужно получить клиентский IPC-дескриптор вызовом функции ServiceLocatorConnect()
, а на стороне серверного процесса нужно получить серверный IPC-дескриптор вызовом функции ServiceLocatorRegister()
. Через параметр channelName
эти функции принимают имя IPC-канала. (Функции ServiceLocatorConnect()
и ServiceLocatorRegister()
объявлены в заголовочном файле sysroot-*-kos/include/coresrv/sl/sl_api.h
из состава KasperskyOS SDK.)
Передача дескрипторов
Родительский процесс может передать один или несколько дескрипторов дочернему процессу, который еще не запущен. (Общие сведения о передаче дескрипторов приведены в разделе "Передача дескрипторов".)
Чтобы передать дескриптор дочернему процессу, нужно вызвать функцию KosTaskTransferResource()
, указав среди прочего дескриптор объекта контекста передачи ресурса, а также маску прав и условное имя потомка передаваемого дескриптора.
Чтобы найти потомка дескриптора, переданного родительским процессом, нужно вызвать функцию KosTaskLookupResource()
, указав условное имя потомка дескриптора, которое было задано родительским процессом при вызове функции KosTaskTransferResource()
.
Запуск процессов
Чтобы создать и сразу запустить процесс без статического создания IPC-каналов, нужно вызвать функцию KosTaskLaunch()
.
Чтобы запустить уже созданный процесс, перед запуском которого могут быть созданы требуемые этому процессу IPC-каналы, нужно вызвать функцию KosTaskRunEx()
или KosTaskRun()
.
Через параметр fsBackend
функции KosTaskRunEx()
нужно задать, как осуществляется поддержка файловой системы ROMFS для запускаемого процесса: ядром или системной программой fsusr
. Использование программы fsusr
обеспечивает размещение образа ROMFS в пользовательском пространстве. В пользовательском пространстве можно разместить образ ROMFS существенно большего размера, чем в пространстве ядра.
Чтобы можно было использовать файловую систему ROMFS, размещенную в пользовательском пространстве, нужно включить программу fsusr
в решение на базе KasperskyOS и создать IPC-канал с именем kl.core.FSUsr
от процесса, которому требуется использовать эту файловую систему, к процессу с именем kl.core.FSUsr
. (Клиентская часть программы fsusr
входит в библиотеку libkos
.) Чтобы проверить, поставляется ли программа fsusr
в составе KasperskyOS SDK, нужно убедиться в наличии исполняемого файла sysroot-*-kos/bin/fsusr
.
Чтобы задать, как осуществляется поддержка файловой системы в уже запущенном процессе, нужно вызывать функцию KosTaskSetSelfFSBackend()
. Эта функция может быть использована следующим образом. Родительский процесс задает, что для него файловую систему ROMFS поддерживает программа fsusr
, и вызовом функции KnFsChange()
загружает требуемый образ ROMFS. (Функция KnFsChange()
объявлена в заголовочном файле sysroot-*-kos/include/coresrv/fs/fs_api.h
из состава KasperskyOS SDK.) Затем родительский процесс выполняет запуск дочернего процесса вызовом функции KosTaskRunEx()
, указав, что для дочернего процесса файловую систему ROMFS поддерживает программа fsusr
. В результате дочерний процесс по умолчанию будет использовать образ ROMFS, размещенный в пользовательском пространстве родительским процессом.
Если родительскому процессу не требуется завершать дочерний процесс или ожидать его завершения, то после запуска дочернего процесса описывающий его объект нужно удалить, обнулив число ссылок на него с использованием функции KosTaskPut()
. Функция KosTaskLaunch()
вызывает функцию KosTaskPut()
после запуска дочернего процесса.
Завершение процессов
API позволяет завершать и ожидать завершения дочерних процессов.
Чтобы завершить дочерний процесс, нужно вызвать функцию KosTaskStop()
или KosTaskStopAndWait()
.
Чтобы ожидать, пока дочерний процесс завершится по собственной инициативе, нужно вызвать функцию KosTaskWait()
.
Чтобы объект ядра, который описывает дочерний процесс, был удален после завершения этого процесса, нужно до или после завершения дочернего процесса закрыть его дескриптор в родительском процессе. Дескриптор дочернего процесса закрывается при удалении в памяти родительского процесса объекта, описывающего дочерний процесс. Чтобы удалить объект, описывающий дочерний процесс, нужно обнулить число ссылок на этот объект, используя функцию KosTaskPut()
. Функция KosTaskLaunch()
вызывает функцию KosTaskPut()
после запуска дочернего процесса.
Подробнее о завершении процессов см. "Управление процессами (низкоуровневый API task_api.h)".
Сведения о функциях API
Функции task.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения об ELF-образе, загруженном в память процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает IPC-канал. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает IPC-канал с заданным именем. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает параметры запуска программы. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функция используется библиотекой |
|
Назначение Позволяет получить параметры запуска программы. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Чтобы удалить массив параметров запуска программы, нужно вызвать функцию |
|
Назначение Удаляет массив параметров запуска программы, полученный вызовом Параметры
Возвращаемые значения Нет. |
|
Назначение Задает переменные окружения программы. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функция используется библиотекой |
|
Назначение Позволяет получить переменные окружения программы. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Чтобы удалить массив переменных окружения программы, нужно вызвать функцию |
|
Назначение Удаляет массив переменных окружения программы, полученный вызовом функции Параметры
Возвращаемые значения Нет. |
|
Назначение Запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает процесс и ожидает окончания завершения этого процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Ожидает завершения процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить дескриптор процесса. Параметры
Возвращаемые значения Дескриптор процесса. |
|
Назначение Создает и запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить адрес объекта, описывающего вызывающий процесс. Параметры Нет. Возвращаемые значения Указатель на объект, описывающий процесс, или Дополнительные сведения Функция увеличивает на единицу число ссылок на объект, описывающий процесс, поэтому после вызова этой функции нужно вызвать функцию |
|
Назначение Уменьшает на единицу число ссылок на объект, описывающий процесс. Параметры
Возвращаемые значения Нет. |
|
Назначение Регистрирует службы. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функция используется библиотекой |
|
Назначение Задает, как осуществляется поддержка файловой системы ROMFS для вызывающего процесса: ядром или системной программой. Параметры
Возвращаемые значения Нет. |
|
Назначение Позволяет получить сведения о том, как осуществляется поддержка файловой системы ROMFS для вызывающего процесса: ядром или системной программой. Параметры Нет. Возвращаемые значения Значение, которое отражает, как осуществляется поддержка файловой системы ROMFS: ядром или системной программой. |
|
Назначение Создает структуры со сведениями о службах из формальной спецификации компонента решения и связывает эти структуры с объектом, описывающим процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Передает дескриптор процессу, который еще не запущен. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет поиск дескриптора по имени, заданному функцией Параметры
Возвращаемые значения В случае успеха возвращает дескриптор, иначе возвращает |
Управление процессами (низкоуровневый API task_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/task/task_api.h
из состава KasperskyOS SDK.
Основные возможности API:
- создавать, запускать и завершать процессы;
- обрабатывать исключения;
- получать сведения о процессах, включая информацию о причинах их завершения;
- задавать приоритеты и классы планирования начальных потоков процессов.
Сведения о функциях API приведены в таблице ниже.
Библиотека libkos
также предоставляет высокоуровневый API для управления процессами, который определен в заголовочном файле sysroot-*-kos/include/kos/task.h
из состава KasperskyOS SDK. Рекомендуется использовать именно этот API. Низкоуровневый API следует использовать, если недостаточно возможностей высокоуровневого API.
Создание и запуск процессов
Чтобы создать процесс, нужно вызвать функцию KnTaskCreate()
или KnTaskCreateEx()
. Эти функции создают "пустой" процесс, то есть процесс, в память которого не загружен ELF-образ программы. Перед запуском такого процесса нужно выполнить следующие шаги:
- Создать начальное значение генератора случайных чисел вызовом функции
KosRandomGenerate()
, которая объявлена в заголовочном файлеsysroot-*-kos/include/kos/random/random_api.h
из состава KasperskyOS SDK.Этот шаг необходим для выполнения следующего шага.
- Задать начальное значение генератора случайных чисел вызовом функции
KnTaskReseedAslr()
.Этот шаг необходим для рандомизации размещения адресного пространства процесса. Рандомизация размещения адресного пространства (англ. Address Space Layout Randomization, ASLR) – это размещение структур данных (ELF-образа, динамических библиотек, стека и кучи) в памяти процесса по случайным адресам с целью усложнения эксплуатации уязвимостей, которые связаны с заранее известной злоумышленнику структурой адресного пространства процесса.
Функция
KnTaskReseedAslr()
задает начальное значение генератора случайных чисел, который используется для автоматического выбора базового адреса выделяемого региона виртуальной памяти в таких функциях, какKnVmAllocate()
,KnPmmMdlMap()
,KnIoDmaMap()
,KnTaskVmReserve()
. Создание стека и кучи в процессе, а также загрузка динамических библиотек в его память выполняются операционной системой с использованием функцииKnVmAllocate()
. При этом в параметреaddr
указывается ноль, чтобы адрес выделенного региона виртуальной памяти был выбран автоматически, то есть был случайным значением. - Стереть из памяти начальное значение генератора случайных чисел, созданное на шаге 1.
Этот шаг необходим для целей безопасности. Чтобы выполнить этот шаг, нужно вызвать функцию
RtlRandomMemSanitize()
, которая объявлена в заголовочном файлеsysroot-*-kos/include/rtl/random.h
из состава KasperskyOS SDK. - Загрузить сегменты ELF-образа в память процесса с использованием функции
KnTaskLoadSeg()
.В поле
loadAddr
параметраseg
нужно указать адрес загрузки сегмента ELF-образа. С целью поддержки ASLR (дополнительно к шагу 2) адрес загрузки сегмента ELF-образа, указанный в ELF-файле, должен быть увеличен на смещение загрузки ELF-образа. Смещение загрузки ELF-образа должно быть случайным значением. Генерацию случайного смещения загрузки ELF-образа и расчет адресов загрузки сегментов ELF-образа с учетом этого смещения выполняет функцияKnElfCreateVmSegEx()
, объявленная в заголовочном файлеsysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK.В результате этого шага буферы MDL, которые содержат сегменты ELF-образа, будут отображены на виртуальную память процесса.
- [Опционально] Загрузить таблицу символов
.symtab
и таблицу строк.strtab
в память процесса вызовом функцииKnTaskLoadElfSyms()
.Адреса загрузки сегментов ELF-образа с таблицей символов
.symtab
и таблицей строк.strtab
должны быть рассчитаны так же, как и адреса загрузки других сегментов ELF-образа. Этот расчет выполняет функцияKnElfCreateVmSegEx()
, объявленная в заголовочном файлеsysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK.Используя таблицу символов
.symtab
и таблицу строк.strtab
, ядро получает имена функций для формирования данных обратной трассировки стека (сведений о стеке вызовов). - Задать точку входа в программу и смещение загрузки ELF-образа вызовом функции
KnTaskSetInitialState()
.Точка входа в программу представляет собой сумму адреса, указанного в поле
e_entry
заголовка ELF-образа, и смещения загрузки ELF-образа. Генерацию случайного смещения загрузки ELF-образа и расчет адреса точки входа в программу с учетом этого смещения выполняет функцияKnElfCreateVmSegEx()
, объявленная в заголовочном файлеsysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK. - [Опционально] Загрузить в память процесса заголовок ELF-образа вызовом функции
KnTaskSetElfHdr()
.Этот шаг нужно выполнить, если требуется, чтобы данные из заголовка ELF-образа были доступны в созданном процессе.
Дескриптор процесса можно передать другому процессу через IPC.
По умолчанию начальный поток процесса является стандартным потоком исполнения, приоритет которого может принимать значения от 0 до 15. (О классах планирования потоков исполнения см. "Управление потоками исполнения (низкоуровневый API thread_api.h)".) Чтобы изменить класс планирования и/или приоритет начального потока процесса, нужно вызвать функцию KnTaskSetInitialPolicy()
. Чтобы изменить приоритет начального потока процесса, нужно вызвать функцию KnTaskSetInitialThreadPriority()
. Функции KnTaskSetInitialPolicy()
и KnTaskSetInitialThreadPriority()
можно использовать после задания точки входа в программу. Также эти функции можно использовать после запуска процесса.
Чтобы запустить процесс, нужно вызвать функцию KnTaskResume()
. Запущенный процесс нельзя приостановить.
Перед запуском процесс получает данные от своего родительского процесса через страницу статических соединений. Страница статических соединений (англ. Static Connection Page, SCP) – набор структур, содержащих данные для статического создания IPC-каналов, параметры запуска и переменные окружения программы. Родительский процесс записывать данные в SCP дочернего процесса вызовом функции KnTaskSetEnv()
. Дочерний процесс при запуске считывает данные из SCP вызовом функции KnTaskGetEnv()
, а затем удаляет SCP вызовом функции KnTaskFreeEnv()
. Все три функции не требуется явно вызывать, так как их вызовы выполняет библиотека libkos
.
Завершение процессов
Завершение процесса включает в себя:
- Завершение всех потоков процесса.
- Освобождение памяти процесса.
- Освобождение системных и пользовательских ресурсов, которыми процесс владеет эксклюзивно.
При завершении процесса все дескрипторы, которыми он владеет, закрываются. Если закрытый дескриптор был единственным дескриптором ресурса, то этот ресурс освобождается.
Процесс завершается по следующим причинам:
- По собственной инициативе.
Вызвана функция
KnTaskExit()
, или завершены все потоки процесса. - По внешнему запросу.
Вызвана функция
KnTaskTerminate()
. - В результате необработанного исключения (аварийно).
Вызовом функции
KnTaskPanic()
процесс может специально инициировать возникновение исключения, которое не может быть обработано и приводит к завершению этого процесса. Это требуется, чтобы процесс мог гарантированно завершить себя. (Например, если в процессе есть потоки исполнения, привязанные к прерываниям, то функцияKnTaskExit()
не может завершить этот процесс, а функцияKnTaskPanic()
позволяет сделать это.)
Коды завершения процессов определяются разработчиком решения на базе KasperskyOS. Эти коды нужно указывать в параметре status
функции KnTaskExit()
. Если процесс завершился в результате завершения всех его потоков, то кодом завершения этого процесса будет код завершения его начального потока. Чтобы получить код завершения процесса, который завершился по собственной инициативе, нужно вызвать функцию KnTaskGetExitCode()
.
Чтобы получить сведения о причине завершения процесса, нужно вызвать функцию KnTaskGetExitStatus()
. Эта функция позволяет определить, был ли процесс завершен по собственной инициативе, по внешнему запросу или аварийно.
Чтобы получить сведения о необработанном исключении, которое привело к аварийному завершению процесса, нужно вызвать функцию KnTaskGetExceptionInfo()
. Эти сведения включают код исключения и контекст потока исполнения, в котором это исключение возникло.
Если процесс создан вызовом функции KnTaskCreateEx()
с флагом TaskExceptionFreezesTask
в параметре flags
, то в результате необработанного исключения этот процесс не завершится, а перейдет в "замороженное" состояние. "Замороженное" состояние процесса – это такое состояние процесса, при котором исполнение его потоков завершилось в результате необработанного исключения, но ресурсы не освободились, чтобы можно было получить сведения об этом процессе. Чтобы получить контекст потока исполнения, входящего в процесс, который находится в "замороженном" состоянии, нужно вызвать функцию KnTaskGetThreadContext()
. Чтобы получить сведения о регионе виртуальной памяти, принадлежащем процессу, который находится в "замороженном" состоянии, нужно вызвать функцию KnTaskGetNextVmRegion()
. Эти сведения включают такую информацию, как базовый адрес и размер региона виртуальной памяти, права доступа к нему. Перед переходом процесса в "замороженное" состояние выполняется вывод данных обратной трассировки стека (сведений о стеке вызовов) для потока исполнения, в котором возникло необработанное исключение. Чтобы завершить процесс, который находится в "замороженном" состоянии, нужно вызвать функцию KnTaskTerminateAfterFreezing()
.
Чтобы объект ядра, который описывает процесс, был удален после завершения этого процесса, нужно до или после завершения этого процесса закрыть или отозвать каждый его дескриптор во всех процессах, которые владеют этими дескрипторами. Чтобы выполнить это, нужно использовать функцию KnHandleClose()
и/или KnHandleRevoke()
, которые объявлены в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Обработка исключений
Чтобы зарегистрировать функцию обработки исключений, нужно вызвать функцию KnTaskSetExceptionHandler()
. Эта функция дерегистрирует предыдущую функцию обработки исключений и возвращает ее идентификатор. Сохранив этот идентификатор, в дальнейшем можно снова зарегистрировать предыдущую функцию обработки исключений.
Функция обработки исключений вызывается при возникновении исключения в любом потоке процесса. В случае успешной обработки исключения эта функция возвращает значение, отличное от ноля, в противном случае она возвращает ноль. Входным параметром функции обработки исключений является структура, содержащая сведения об исключении. Тип этой структуры определен в заголовочном файле sysroot-*-kos/include/thread/tcbpage.h
из состава KasperskyOS SDK.
Если функции обработки исключений, зарегистрированной на уровне процесса, не удалось успешно обработать исключение, будет вызвана функция обработки исключений, зарегистрированная на уровне потока исполнения, в котором возникло это исключение. (Об обработке исключений на уровне потоков исполнения см. "Управление потоками исполнения (низкоуровневый API thread_api.h)".)
Резервирование памяти в дочернем процессе
API включает функции KnTaskVmReserve()
и KnTaskVmFree()
, которые позволяют соответственно резервировать и освобождать регионы виртуальной памяти в дочернем процессе, для которого еще не задана точка входа в программу. Эти функции являются только частью функциональности, нацеленной на повышение уровня контроля родительского процесса за виртуальным адресным пространством дочернего процесса. В настоящее время эта функциональность находится в разработке.
Получение адреса GSI
Общая системная информация (англ. Global System Information, GSI) – структура, содержащая системные сведения, такие как число отсчетов таймера с момента запуска ядра, число отсчетов таймера в секунду, число процессоров (вычислительных ядер) в активном состоянии, данные о процессорном кеше. Тип структуры определен в заголовочном файле sysroot-*-kos/include/task/pcbpage.h
из состава KasperskyOS SDK. Получить адрес GSI позволяет функция KnTaskGetGsi()
. Эта функция предназначена для использования библиотекой libc
.
Получение адреса PCB
Блок управления процессом (англ. Process Control Block, PCB) – структура, содержащая сведения о процессе, которые используются ядром для управления этим процессом. Тип структуры определен в заголовочном файле sysroot-*-kos/include/task/pcbpage.h
из состава KasperskyOS SDK. Получить адрес PCB позволяет функция KnTaskGetPcb()
. Эта функция предназначена для использования библиотекой libc
.
Сведения о функциях API
Функции task_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Позволяет получить адрес GSI для вызывающего процесса. Параметры Нет. Возвращаемые значения Указатель на GSI. Тип данных для хранения GSI определен в заголовочном файле |
|
Назначение Позволяет получить адрес блока управления процессом (PCB) для вызывающего процесса. Параметры Нет. Возвращаемые значения Указатель на PCB. Тип данных для хранения PCB определен в заголовочном файле |
|
Назначение Позволяет получить адрес SCP вызывающего процесса. Параметры
Возвращаемые значения Указатель на SCP или |
|
Назначение Записывает данные в SCP процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет SCP вызывающего процесса. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Записывает заголовок ELF-образа в PCB процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает вызывающий процесс. Параметры
Возвращаемые значения Код ошибки. Дополнительные сведения Не завершает процесс, если в нем есть потоки исполнения, привязанные к прерываниям. |
|
Назначение Завершает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о причине завершения процесса. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Через параметры
|
|
Назначение Позволяет получить сведения о необработанном исключении, которое привело к аварийному завершению процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить контекст потока исполнения, входящего в процесс, который находится в "замороженном" состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о регионе виртуальной памяти, принадлежащем процессу, который находится в "замороженном" состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает процесс, который находится в "замороженном" состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить код завершения процесса, который завершился по собственной инициативе. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить идентификатор процесса (PID) для вызывающего процесса. Параметры Нет. Возвращаемые значения Идентификатор процесса. Тип идентификатора определен в заголовочном файле |
|
Назначение Позволяет получить имя вызывающего процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить имя исполняемого файла (в ROMFS), из которого создан вызывающий процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить приоритет начального потока процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает приоритет начального потока процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Регистрирует функцию обработки исключений для вызывающего процесса. Параметры
Возвращаемые значения Идентификатор предыдущей зарегистрированной функции обработки исключений или |
|
Назначение Загружает сегмент ELF-образа в память процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Резервирует регион виртуальной памяти в процессе. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
Допустимые комбинации флагов, задающих права доступа к региону виртуальной памяти:
|
|
Назначение Освобождает регион виртуальной памяти, зарезервированный вызовом функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает точку входа в программу и смещение загрузки ELF-образа. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Загружает таблицу символов Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает класс планирования и приоритет начального потока процесса. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре В параметре |
|
Назначение Задает начальное значение генератора случайных чисел для поддержки ASLR в заданном процессе. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить адреса и размеры таблицы символов Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если таблица символов Функция предназначена для механизма, который выводит данные обратной трассировки стека и работает в процессе, а не в ядре. В настоящее время этот механизм находится в разработке. |
|
Назначение Позволяет получить идентификатор процесса (PID). Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Инициирует возникновение исключения, которое не может быть обработано и приводит к завершению вызывающего процесса. Параметры Нет. Возвращаемые значения Нет. |
|
Назначение Передает дескриптор процессу, который еще не запущен. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В отличие от функции |
Инициализация IPC-транспорта для межпроцессного взаимодействия и управление обработкой IPC-запросов (transport-kos.h, transport-kos-dispatch.h)
API определены в заголовочных файлах transport-kos.h
и transport-kos-dispatch.h
из состава KasperskyOS SDK, которые расположены по пути sysroot-*-kos/include/coresrv/nk
.
Возможности API:
- Инициализировать IPC-транспорт на стороне клиента и на стороне сервера.
IPC-транспорт – это надстройка над системными вызовами отправки и приема IPC-сообщений, которая позволяет отдельно работать с фиксированной частью и ареной IPC-сообщений. Поверх этой надстройки работает транспортный код.
- Запускать цикл обработки IPC-запросов на стороне сервера.
- Копировать данные в арену IPC-сообщений.
Сведения о функциях API приведены в таблицах ниже.
В этом разделе приведены примеры использования API. В этих примерах программы, которые являются серверами, имеют следующую формальную спецификацию:
FsDriver.edl
Operations.cdl
FileIface.idl
Инициализация IPC-транспорта для межпроцессного взаимодействия
Чтобы инициализировать IPC-транспорт для взаимодействия с другими процессами, нужно вызвать функцию NkKosTransport_Init()
или NkKosTransportSync_Init()
, объявленные в заголовочном файле transport-kos.h
.
Пример использования функции NkKosTransport_Init()
на стороне клиента:
Если клиенту требуется использовать несколько служб, то нужно инициализировать столько же прокси-объектов. При инициализации каждого прокси-объекта нужно указать IPC-транспорт, ассоциированный через клиентский IPC-дескриптор с нужным сервером. При инициализации нескольких прокси-объектов, относящихся к службам одного сервера, можно указать один и тот же IPC-транспорт, который ассоциирован с этим сервером.
Пример использования функции NkKosTransport_Init()
на стороне сервера:
Если сервер обрабатывает IPC-запросы, поступающие через несколько IPC-каналов, то нужно учитывать следующие особенности:
- Если слушающий дескриптор ассоциирован со всеми IPC-каналами, то для IPC-взаимодействия со всеми клиентами можно использовать один IPC-транспорт, ассоциированный с этим слушающим дескриптором.
- Если IPC-каналы ассоциированы с разными слушающими дескрипторами, то для IPC-взаимодействия с каждой группой клиентов, соответствующих одному слушающему дескриптору, нужно использовать отдельный IPC-транспорт, ассоциированный с этим слушающим дескриптором. При этом обработку IPC-запросов можно выполнять в параллельных потоках исполнения, если реализация методов служб потокобезопасна.
Функция NkKosTransportSync_Init()
позволяет инициализировать IPC-транспорт с поддержкой прерывания блокирующих системных вызовов Call()
и Recv()
. (Прерывание этих вызовов может потребоваться, например, чтобы корректно завершить процесс, который их выполняет.) Чтобы прерывать системные вызовы Call()
и Recv()
, нужно использовать API ipc_api.h.
Функция NkKosSetTransportTimeouts()
, объявленная в заголовочном файле transport-kos.h
, позволяет задать для IPC-транспорта максимальное время блокировки системных вызовов Call()
и Recv()
.
Запуск цикла обработки IPC-запросов
Цикл обработки IPC-запроса на сервере включает следующие стадии:
- Получение IPC-запроса.
- Обработка IPC-запроса.
- Отправка IPC-ответа.
Каждую стадию этого цикла можно выполнять отдельно, последовательно вызывая функции nk_transport_recv()
, диспетчер, nk_transport_reply()
. (Функции nk_transport_recv()
и nk_transport_reply()
объявлены в заголовочном файле sysroot-*-kos/include/nk/transport.h
из состава KasperskyOS SDK.) А можно вызвать функцию NkKosTransport_Dispatch()
, NkKosDoDispatch()
или NkKosDoDispatchEx()
, внутри которых этот цикл выполняется полностью. (Функция NkKosTransport_Dispatch()
объявлена в заголовочном файле transport-kos.h
, функции NkKosDoDispatch()
и NkKosDoDispatchEx()
объявлены в заголовочном файле transport-kos-dispatch.h
.) Использовать функцию NkKosDoDispatch()
или NkKosDoDispatchEx()
удобнее по сравнению с функцией NkKosTransport_Dispatch()
, поскольку нужно выполнять меньше подготовительных операций (в том числе не требуется инициализировать IPC-транспорт).
Для инициализации структуры, передаваемой функции NkKosDoDispatch()
или NkKosDoDispatchEx()
через параметр info
, можно использовать макросы, определенные в заголовочном файле transport-kos-dispatch.h
. Используя параметр syncHandle
функции NkKosDoDispatchEx()
, можно прерывать системный вызов Recv()
. Через параметр cb
функции NkKosDoDispatchEx()
можно задать callback-функции, вызываемые после выполнения системных вызовов Recv()
и Reply()
, а также после выхода из цикла обработки IPC-запросов (все функции задавать не требуется). Callback-функция, соответствующая указателю enterDispatchProcessing
, вызывается сразу после выполнения системного вызова Recv()
. Callback-функция, соответствующая указателю leaveDispatchProcessing
, вызывается сразу после выполнения системного вызова Reply()
. Callback-функция, соответствующая указателю stopDispatchLoop
, вызывается сразу после выхода из цикла обработки IPC-запросов. Каждой из этих callback-функций передается указатель callbackContext
. Эти callback-функции могут использоваться, например, в реализации пула потоков исполнения.
Функции NkKosTransport_Dispatch()
, NkKosDoDispatch()
и NkKosDoDispatchEx()
можно вызывать из параллельных потоков исполнения, если реализация методов служб потокобезопасна.
Пример использования функции NkKosDoDispatch()
:
Пример использования функции NkKosTransport_Dispatch()
:
Копирование данных в арену IPC-сообщений
Чтобы скопировать строку в арену IPC-сообщений, нужно вызвать функцию NkKosCopyStringToArena()
, объявленную в заголовочном файле transport-kos.h
. Эта функция резервирует участок арены и копирует строку в этот участок.
Пример использования функции NkKosCopyStringToArena()
:
Сведения о функциях API
Функции transport-kos.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует IPC-транспорт. Параметры
Возвращаемые значения Нет. |
|
Назначение Инициализирует IPC-транспорт с поддержкой прерывания системных вызовов Параметры
Возвращаемые значения Нет. |
|
Назначение Задает для IPC-транспорта максимальное время блокировки системных вызовов Параметры
Возвращаемые значения Нет. |
|
Назначение Запускает цикл обработки IPC-запросов. Параметры
Возвращаемые значения В случае неуспеха возвращает код ошибки. |
|
Назначение Резервирует участок арены и копирует строку в этот участок. Параметры
Возвращаемые значения В случае успеха возвращает |
Функции transport-kos-dispatch.h
Функция |
Сведения о функции |
---|---|
|
Назначение Запускает цикл обработки IPC-запросов. Параметры
Возвращаемые значения Нет. |
|
Назначение Запускает цикл обработки IPC-запросов. Параметры
Возвращаемые значения Нет. |
Инициализация IPC-транспорта для обращения к модулю безопасности (transport-kos-security.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/nk/transport-kos-security.h
из состава KasperskyOS SDK.
API позволяет инициализировать IPC-транспорт для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности. Поверх IPC-транспорта работает транспортный код.
Сведения о функциях API приведены в таблице ниже.
В этом разделе приведен пример использования API. В этом примере программа, которая обращается к модулю безопасности, имеет следующую формальную спецификацию:
Verifier.edl
Approve.idl
Фрагмент описания политики в примере:
security.psl
Использование API
Чтобы инициализировать IPC-транспорт для обращения к модулю безопасности, нужно вызвать функцию NkKosSecurityTransport_Init()
.
Пример использования функции NkKosSecurityTransport_Init()
:
Если процессу требуется использовать несколько интерфейсов безопасности, то нужно инициализировать столько же прокси-объектов, указав один и тот же IPC-транспорт и уникальные идентификаторы интерфейсов безопасности.
Сведения о функциях API
Функции transport-kos-security.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует IPC-транспорт для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности. Параметры
Возвращаемые значения В случае успеха возвращает |
Генерация случайных чисел (random_api.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/random/random_api.h
из состава KasperskyOS SDK.
API позволяет генерировать случайные числа, а также включает функции, которые можно использовать, чтобы обеспечить высокую энтропию (высокий уровень непредсказуемости) начального значения генератора случайных чисел. Начальное значение генератора случайных чисел (англ. seed) определяет последовательность генерируемых случайных чисел. То есть после установки одного и того же начального значения генератор создает одинаковые последовательности случайных чисел. (Энтропия таких чисел полностью определяется энтропией начального значения, поэтому точнее их называть не случайными, а псевдослучайными.)
Генератор случайных чисел одного процесса не зависит от генераторов случайных чисел других процессов.
Сведения о функциях API приведены в таблице ниже.
Использование API
Чтобы сгенерировать последовательность случайных байтовых значений, нужно вызвать функцию KosRandomGenerate()
или KosRandomGenerateEx()
.
Пример использования функции KosRandomGenerate()
:
Функция KosRandomGenerateEx()
позволяет получить уровень качества сгенерированных случайных значений через выходной параметр quality
. Уровень качества может быть высоким или низким. Высококачественными считаются случайные значения, которые сгенерированы при выполнении всех следующих условий:
- На момент изменения начального значения генератора случайных чисел зарегистрирован хотя бы один источник энтропии, и успешно получены данные из всех зарегистрированных источников энтропии.
Чтобы зарегистрировать источник энтропии, нужно вызвать функцию
KosRandomRegisterSrc()
. Через параметрcallback
эта функция принимает указатель на callback-функцию следующего типа:typedef Retcode (*KosRandomSeedMethod)(void *context, rtl_size_t size, void *output);Эта callback-функция должна, используя параметры
context
, получить данные размеромsize
байт из источника энтропии и записать их в буферoutput
. Если функция возвращаетrcOk
, то считается, что данные из источника энтропии были получены успешно. Источником энтропии может быть, например, оцифрованный сигнал какого-либо датчика или аппаратный генератор случайных чисел.Чтобы дерегистрировать источник энтропии, нужно вызвать функцию
KosRandomUnregisterSrc()
. - Выполнена инициализация генератора случайных чисел, если до изменения начального значения генератора случайных чисел с выполнением условия 1 уровень качества был низким.
Если уровень качества низкий, то сделать его высоким без инициализации генератора случайных чисел нельзя.
Чтобы инициализировать генератор случайных чисел, нужно вызвать функцию
KosRandomInitSeed()
. Энтропию данных, передаваемых через параметрseed
, должен гарантировать вызывающий процесс. - Счетчик случайных байтовых значений, которые сгенерированы после изменения начального значения генератора случайных чисел с выполнением условия 1, не превышает заданный в системе лимит.
- Счетчик времени, которое прошло после изменения начального значения генератора случайных чисел с выполнением условия 1, не превышает заданный в системе лимит.
Если хотя бы одно из этих условий не выполняется, сгенерированные случайные значения считаются низкокачественными.
При запуске процесса начальное значение генератора случайных чисел задается системой автоматически. Затем начальное значение генератора случайных чисел изменяется в следующих случаях:
- Генерация последовательности случайных значений.
Каждый успешный вызов функции
KosRandomGenerateEx()
с параметромsize
больше нуля и каждый успешный вызов функцииKosRandomGenerate()
изменяют начальное значение генератора случайных чисел, но не каждое такое изменение выполняется с получением данных из зарегистрированных источников энтропии. Зарегистрированные источники энтропии используются только при нарушении условия 3 или 4. При этом, если зарегистрирован хотя бы один источник энтропии, то сбрасывается счетчик времени изменения начального значения генератора случайных чисел. А если данные из хотя бы одного источника энтропии получены успешно, то также сбрасывается счетчик сгенерированных случайных байтовых значений.Уровень качества может измениться с высокого на низкий.
- Инициализация генератора случайных чисел.
Каждый успешный вызов функции
KosRandomInitSeed()
изменяет начальное значение генератора случайных чисел, используя данные, переданные через параметрseed
и полученные из зарегистрированных источников энтропии. При наличии хотя бы одного зарегистрированного источника энтропии сбрасываются счетчики сгенерированных случайных байтовых значений и времени изменения начального значения генератора случайных чисел. В противном случае сбрасывается только счетчик сгенерированных случайных байтовых значений.Уровень качества может измениться с высокого на низкий и наоборот.
- Регистрация источника энтропии.
Каждый успешный вызов функции
KosRandomRegisterSrc()
изменяет начальное значение генератора случайных чисел, используя данные только из регистрируемого источника энтропии. При этом сбрасывается счетчик сгенерированных случайных байтовых значений.Уровень качества не может измениться.
Возможный сценарий генерации случайных значений высокого качества включает следующие шаги:
- Зарегистрировать хотя бы один источник энтропии вызовом функции
KosRandomRegisterSrc()
. - Сгенерировать последовательность случайных значений вызовом функции
KosRandomGenerateEx()
. - Проверить уровень качества случайных значений.
Если уровень качества низкий, инициализировать генератор случайных чисел вызовом функции
KosRandomInitSeed()
и перейти к шагу 2.Если уровень качестве высокий, перейти к шагу 4.
- Использовать случайные значения.
Чтобы получить уровень качества без генерации случайных значений, нужно вызвать функцию KosRandomGenerateEx()
со значениями 0
и RTL_NULL
в параметрах size
и output
соответственно.
Сведения о функциях API
Функции random_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует генератор случайных чисел. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Генерирует последовательность случайных байтовых значений. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Генерирует последовательность случайных байтовых значений. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Регистрирует источник энтропии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Дерегистрирует источник энтропии. Параметры
Возвращаемые значения В случае успеха возвращает |
Получение и изменение значений времени (time_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/time/time_api.h
из состава KasperskyOS SDK.
Основные возможности API:
- получать и изменять системное время;
- получать монотонное время, отсчитанное с момента запуска ядра KasperskyOS;
- получать разрешение источников системного и монотонного времени.
Сведения о функциях API приведены в таблице ниже.
Функции time_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Позволяет получить разрешение источника системного времени. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает системное время. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить системное время. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить разрешение источника монотонного времени, отсчитываемого с момента запуска ядра KasperskyOS. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить монотонное время, отсчитанное с момента запуска ядра KasperskyOS. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить системное время. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить монотонное время, отсчитанное с момента запуска ядра KasperskyOS. Параметры Нет. Возвращаемые значения Монотонное время, отсчитанное с момента запуска ядра KasperskyOS, в миллисекундах. |
|
Назначение Запускает постепенную корректировку системного времени. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если запустить новую корректировку до завершения ранее запущенной, то ранее запущенная будет прервана. |
Использование уведомлений (notice_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/handle/notice_api.h
из состава KasperskyOS SDK.
API позволяет отслеживать события, которые связаны с ресурсами (как системными, так и пользовательскими), а также уведомлять о событиях, связанных с пользовательскими ресурсами, другие процессы и потоки исполнения.
Сведения о функциях API приведены в таблице ниже.
Использование API
Механизм уведомлений использует маску событий. Маска событий – значение, биты которого интерпретируются как события, которые должны отслеживаться или уже произошли. Маска событий имеет размер 32 бита и состоит из общей и специальной части. Общая часть описывает события, неспецифичные для любых ресурсов. Специальная часть описывает события, специфичные для ресурсов. Флаги специальной части для системных ресурсов и флаги общей части определены в заголовочном файле sysroot-*-kos/include/handle/event_descr.h
из состава KasperskyOS SDK. (Например, флаг общей части EVENT_OBJECT_DESTROYED
означает прекращение существования ресурса, а флаг специальной части EVENT_TASK_COMPLETED
означает завершение процесса.) Флаги специальной части для пользовательского ресурса определяются поставщиком этого ресурса с использованием макросов OBJECT_EVENT_SPEC()
и OBJECT_EVENT_USER()
, которые определены в заголовочном файле sysroot-*-kos/include/handle/event_descr.h
из состава KasperskyOS SDK. Поставщику ресурса необходимо экспортировать публичные заголовочные файлы с описанием флагов специальной части.
Типовой сценарий получения уведомлений о событиях, связанных с ресурсами, включает следующие шаги:
- Создание приемника уведомлений (объекта ядра KasperskyOS, в котором накапливаются уведомления) вызовом функции
KnNoticeCreate()
.Идентификатор приемника уведомлений является указателем на объектом
KosObject
, который содержит дескриптор приемника уведомлений (об объектахKosObject
см. "Использование объектов KosObject (objects.h)"). Уничтожение этого объекта приводит к уничтожению приемника уведомлений. Если требуется создать копию идентификатора приемника уведомлений (например, для использования в другом потоке исполнения), нужно инкрементировать счетчик ссылок на объектKosObject
вызовом функцииKosRefObject()
, чтобы обеспечить существование этого объекта на время существования созданной копии идентификатора. Если копия идентификатора приемника уведомлений больше требуется, нужно декрементировать счетчик ссылок на объектKosObject
вызовом функцииKosPutObject()
, чтобы обеспечить уничтожение этого объекта при отсутствии других ссылок. - Добавление в приемник уведомлений записей вида "ресурс – маска событий", чтобы настроить его на получение уведомлений о событиях, которые связаны с интересующими ресурсами.
Чтобы добавить запись вида "ресурс – маска событий" в приемник уведомлений, нужно вызвать функцию
KnNoticeSubscribeToObject()
. (В маске прав дескриптора ресурса, указанного в параметреobject
, должен быть флагOCAP_HANDLE_GET_EVENT
.) Для одного и того же ресурса можно добавить несколько записей вида "ресурс – маска событий", при этом не требуется, чтобы идентификаторы этих записей были уникальными. Отслеживаемые события для каждой записи вида "ресурс – маска событий" нужно задать маской событий, которая может соответствовать одному или нескольким событиям.Добавленные в приемник уведомлений записи вида "ресурс – маска событий" можно полностью или частично удалить, чтобы этот приемник не получал уведомления, соответствующие этим записям. Чтобы удалить из приемника уведомлений все записи вида "ресурс – маска событий", нужно вызвать функцию
KnNoticeDropAndWake()
. Чтобы удалить из приемника уведомлений записи вида "ресурс – маска событий", относящиеся к одному ресурсу, нужно вызвать функциюKnNoticeUnsubscribeFromObject()
. Чтобы удалить из приемника уведомлений записи вида "ресурс – маска событий" с конкретным идентификатором, нужно вызвать функциюKnNoticeUnsubscribeFromEvent()
.Записи вида "ресурс – маска событий" можно добавлять в приемник уведомлений и удалять из него на протяжении всего времени жизни этого приемника уведомлений.
- Извлечение уведомлений из приемника с использованием функции
KnNoticeGetEvent()
илиKnNoticeGetEventEx()
.При вызове функции
KnNoticeGetEvent()
илиKnNoticeGetEventEx()
можно задать время ожидания появления уведомлений в приемнике. Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновляют свое исполнение при появлении уведомлений, даже если эти уведомления соответствуют записям вида "ресурс – маска событий", добавленным в приемник во время ожидания.Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновляют свое исполнение и не будут заблокированы при последующих вызовах функции
KnNoticeGetEvent()
илиKnNoticeGetEventEx()
, если из этого приемника удалены все записи вида "ресурс – маска событий" вызовом функцииKnNoticeDropAndWake()
. Если после вызова функцииKnNoticeDropAndWake()
добавить в приемник уведомлений хотя бы одну запись вида "ресурс – маска событий", то потоки исполнения, получающие уведомления из этого приемника, будут снова заблокированы при вызове функцииKnNoticeGetEvent()
илиKnNoticeGetEventEx()
на заданное время ожидания при отсутствии уведомлений. Если все записи вида "ресурс – маска событий" удалены из приемника уведомлений с использованием функцииKnNoticeUnsubscribeFromObject()
и/или функцииKnNoticeUnsubscribeFromEvent()
, то исполнение потоков, ожидающих появления уведомлений в этом приемнике, не будет возобновлено до истечения времени ожидания, а также будет заблокировано на время ожидания при последующих вызовах функцииKnNoticeGetEvent()
илиKnNoticeGetEventEx()
. - Завершение работы с приемником уведомлений вызовом функции
KnNoticeRelease()
.Функция
KnNoticeRelease()
удаляет из приемника уведомлений все записи вида "ресурс – маска событий" и делает невозможным добавление новых. При этом потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновляют свое исполнение и не будут заблокированы при последующих вызовах функцииKnNoticeGetEvent()
илиKnNoticeGetEventEx()
. Кроме того, функцияKnNoticeRelease()
декрементирует счетчик ссылок на объектKosObject
, содержащий дескриптор приемника уведомлений. При отсутствии других ссылок на этот объект приемник уведомлений будет уничтожен. Иначе приемник уведомлений будет существовать до удаления остальных ссылок.
Чтобы уведомить другие процессы и/или потоки исполнения о событиях, которые связаны с пользовательским ресурсом, нужно вызвать функцию KnNoticeSetObjectEvent()
. В результате вызова этой функции появляются уведомления в приемниках, настроенных на получение уведомлений о событиях, заданных через параметр evMask
, которые связаны с пользовательским ресурсом, заданным через параметр object
. В параметре evMask
нельзя указывать флаги общей части маски событий, так как о событиях, соответствующих общей части маски событий, может сигнализировать только ядро. Если процесс, вызывающий функцию KnNoticeSetObjectEvent()
, создал дескриптор пользовательского ресурса, указанный в параметре object
, то в параметре evMask
можно указать флаги, которые определены макросами OBJECT_EVENT_SPEC()
и OBJECT_EVENT_USER()
. Если процесс, вызывающий функцию KnNoticeSetObjectEvent()
, получил от другого процесса дескриптор пользовательского ресурса, указанный в параметре object
, то в параметре evMask
можно указать только те флаги, которые определены макросом OBJECT_EVENT_USER()
, при этом в маске прав полученного дескриптора должен быть флаг OCAP_HANDLE_SET_EVENT
.
Сведения о функциях API
Функции notice_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает приемник уведомлений. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Добавляет запись вида "ресурс – маска событий" в приемник уведомлений, чтобы он получал уведомления о событиях, которые связаны с заданным ресурсом и соответствуют заданной маске событий. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Извлекает уведомления из приемника. Параметры
Возвращаемые значения В случае успеха возвращает Если время ожидания появления уведомлений в приемники истекло, возвращает Если все записи вида "ресурс – маска событий" удалены из приемника уведомлений вызовом функции |
|
Назначение Извлекает уведомления из приемника. Параметры
Возвращаемые значения В случае успеха возвращает Если время ожидания появления уведомлений в приемники истекло, возвращает Если все записи вида "ресурс – маска событий" удалены из приемника уведомлений вызовом функции |
|
Назначение Удаляет записи вида "ресурс – маска событий", соответствующие заданному ресурсу, из приемника уведомлений, чтобы он не получал уведомления о событиях, соответствующих этим записям. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Уведомления, соответствующие удаленным записям вида "ресурс – маска событий", будут удалены из приемника. |
|
Назначение Удаляет записи вида "ресурс – маска событий" с заданным идентификатором из приемника уведомлений, чтобы он не получал уведомления о событиях, соответствующих этим записям. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Уведомления, соответствующие удаленным записям вида "ресурс – маска событий", будут удалены из приемника. |
|
Назначение Удаляет все записи вида "ресурс – маска событий" из заданного приемника уведомлений и возобновляет исполнение всех потоков, ожидающих появления уведомлений в заданном приемнике. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет все записи вида "ресурс – маска событий" из заданного приемника уведомлений и делает невозможным добавление новых, возобновляет исполнение всех потоков, ожидающих появления уведомлений в заданном приемнике, декрементирует счетчик ссылок на объект Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Сигнализирует, что произошли события, которые связаны с заданным пользовательским ресурсом и соответствуют заданной маске событий. Параметры
Возвращаемые значения В случае успеха возвращает |
Динамическое создание IPC-каналов (cm_api.h, ns_api.h)
API определены в следующих заголовочных файлах из состава KasperskyOS SDK:
sysroot-*-kos/include/coresrv/cm/cm_api.h
;sysroot-*-kos/include/coresrv/ns/ns_api.h
.
API позволяют динамически создавать IPC-каналы.
Сведения о функциях API приведены в таблицах ниже.
Использование API
Чтобы серверы могли сообщать клиентам о предоставляемых службах, нужно включить в решение сервер имен, то есть системную программу NameServer
(исполняемый файл sysroot-*-kos/bin/ns
из состава KasperskyOS SDK). IPC-каналы от клиентов и серверов к серверу имен можно создать статически (эти IPC-каналы должны иметь имя kl.core.NameServer
). Если этого не сделать, то при вызове клиентами и серверами функции NsCreate()
будут выполнены попытки динамического создания этих IPC-каналов. Сервер имен не требуется включать в решение, если у клиентов изначально есть сведения об именах серверов и предоставляемых этими серверами служб.
Имена служб и интерфейсов нужно задавать в соответствии с формальными спецификациями компонентов решения. (О квалифицированном имени службы см. "Привязка методов моделей безопасности к событиям безопасности".) Вместо квалифицированного имени службы можно использовать какое-либо условное название этой службы. Имена клиентов и серверов задаются в init-описании. Также имя процесса можно получить вызовом функции KnTaskGetName()
из API task_api.h.
Динамическое создание IPC-канала на стороне сервера включает следующие шаги:
- Подключиться к серверу имен вызовом функции
NsCreate()
. - Опубликовать предоставляемые службы на сервере имен, используя функцию
NsPublishService()
.Чтобы отменить публикацию службы, нужно вызвать функцию
NsUnPublishService()
. - Получить запрос клиента на создание IPC-канала вызовом функции
KnCmListen()
.Функция
KnCmListen()
позволяет получить первый запрос в очереди, но при этом не удаляет этот запрос, а помещает в конец очереди. Если в очереди всего один запрос, то вызов функцииKnCmListen()
несколько раз подряд дает один и тот же результат. Запрос удаляется из очереди при вызове функцииKnCmAccept()
илиKnCmDrop()
. - Принять запрос клиента на создание IPC-канала вызовом функции
KnCmAccept()
.Чтобы отклонить запрос клиента, нужно вызвать функцию
KnCmDrop()
.Слушающий дескриптор создается при вызове функции
KnCmAccept()
со значениемINVALID_HANDLE
в параметреlistener
. Если указать слушающий дескриптор, то созданный серверный IPC-дескриптор обеспечит возможность получать IPC-запросы по всем IPC-каналам, ассоциированным с этим слушающим дескриптором. (Первый IPC-канал, ассоциированный со слушающим дескриптором, создается при вызове функцииKnCmAccept()
со значениемINVALID_HANDLE
в параметреlistener
. Второй и последующие IPC-каналы, ассоциированные со слушающим дескриптором, создаются при втором и последующих вызовах функцииKnCmAccept()
с указанием дескриптора, полученного при первом вызове.) В параметреlistener
функцииKnCmAccept()
можно указать слушающий дескриптор, полученный с использованием функцийKnHandleConnect()
,KnHandleConnectEx()
иKnHandleCreateListener()
из API handle_api.h, а также функцииServiceLocatorRegister()
, объявленной в заголовочном файлеsysroot-*-kos/include/coresrv/sl/sl_api.h
из состава KasperskyOS SDK. В параметреrsid
функцииKnCmAccept()
нужно указать идентификатор службы (RIID), который является константой в автоматически генерируемом транспортном коде (например,FsDriver_operationsComp_fileOperations_iid
).
Динамическое создание IPC-канала на стороне клиента включает следующие шаги:
- Подключиться к серверу имен вызовом функции
NsCreate()
. - Найти сервер, предоставляющий требуемую службу, используя функцию
NsEnumServices()
.Чтобы получить полный список служб с заданным интерфейсом, нужно вызвать функцию несколько раз, инкрементируя индекс, пока не будет получена ошибка
rcResourceNotFound
. - Выполнить запрос на создание IPC-канала с требуемым сервером вызовом функции
KnCmConnect()
.
К серверу имен можно подключить несколько клиентов и серверов. Каждый клиент и сервер может создать несколько подключений к серверу имен. Сервер может отменить публикацию службы, выполненную другим сервером.
Чтобы удалить подключение к серверу имен, нужно вызвать функцию NsDestroy()
.
Удаление динамически созданных IPC-каналов
Динамически созданный IPC-канал будет удален при закрытии его клиентского и серверного IPC-дескрипторов.
Сведения о функциях API
Функции ns_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает подключение к серверу имен. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет подключение к серверу имен. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Публикует службу на сервере имен. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отменяет публикацию службы на сервере имен. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Перечисляет службы, опубликованные на сервере имен. Параметры
Возвращаемые значения В случае успеха возвращает |
Функции cm_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Выполняет запрос на создание IPC-канала с сервером для использования заданной службы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить запрос клиента на создание IPC-канала для использования службы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отклоняет запрос клиента на создание IPC-канала для использования заданной службы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Принимает запрос клиента на создание IPC-канала для использования заданной службы. Параметры
Возвращаемые значения В случае успеха возвращает |
Использование примитивов синхронизации (event.h, mutex.h, rwlock.h, semaphore.h, condvar.h)
Библиотека libkos
предоставляет API, позволяющие использовать следующие примитивы синхронизации:
- события (
event.h
); - мьютексы (
mutex.h
); - блокировки чтения-записи (
rwlock.h
); - семафоры (
semaphore.h
); - условные переменные (
condvar.h
).
Заголовочные файлы находятся в KasperskyOS SDK по пути sysroot-*-kos/include/kos
.
API предназначены для синхронизации потоков исполнения, принадлежащих одному и тому же процессу.
События
Событие – примитив синхронизации, который используется для уведомления одного или нескольких потоков исполнения о выполнении требуемого этим потокам условия. Уведомляемый поток исполнения ожидает, когда событие перейдет из несигнального состояния в сигнальное, а уведомляющий поток исполнения изменяет состояние этого события.
Типовой сценарий использования API для работы с событиями включает следующие шаги:
- Инициализация события вызовом функции
KosEventInit()
. - Использование события потоками исполнения:
- Ожидание перехода события из несигнального состояния в сигнальное вызовом функции
KosEventWait()
илиKosEventWaitTimeout()
(на стороне уведомляемых потоков исполнения). - Изменение состояния события вызовами функций
KosEventSet()
иKosEventReset()
(на стороне уведомляющих потоков исполнения).
- Ожидание перехода события из несигнального состояния в сигнальное вызовом функции
Сведения о функциях API для работы с событиями приведены в таблице ниже.
Функции event.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует событие. После инициализации событие находится в несигнальном состоянии. Параметры
Возвращаемые значения Нет. |
|
Назначение Устанавливает событие в сигнальное состояние. Параметры
Возвращаемые значения Нет. |
|
Назначение Устанавливает событие в несигнальное состояние. Параметры
Возвращаемые значения Нет. |
|
Назначение Ожидает перехода события из несигнального состояния в сигнальное сколь угодно долго. Параметры
Возвращаемые значения Нет. |
|
Назначение Ожидает перехода события из несигнального состояния в сигнальное не дольше заданного времени. Параметры
Возвращаемые значения В случае успеха возвращает Если время ожидания истекло, возвращает |
Мьютексы
Мьютекс – примитив синхронизации, который обеспечивает взаимоисключающее исполнение критических секций (участков кода, в которых осуществляется обращение к разделяемым между потоками исполнения ресурсам). Один поток захватывает мьютекс и исполняет критическую секцию, а другие потоки, чтобы исполнить критические секции, пытаются захватить этот мьютекс, ожидая его освобождения. Мьютекс может быть освобожден только тем потоком исполнения, которым он захвачен. Можно использовать рекурсивный мьютекс, который может быть захвачен одним потоком исполнения несколько раз.
Типовой сценарий использования API для работы с мьютексами включает следующие шаги:
- Инициализация мьютекса вызовом функции
KosMutexInit()
илиKosMutexInitEx()
. - Использование мьютекса потоками исполнения:
- Захват мьютекса вызовом функции
KosMutexTryLock()
,KosMutexLock()
илиKosMutexLockTimeout()
. - Освобождение мьютекса вызовом функции
KosMutexUnlock()
.
- Захват мьютекса вызовом функции
Сведения о функциях API для работы с мьютексами приведены в таблице ниже.
Функции mutex.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует мьютекс, который не является рекурсивным. Параметры
Возвращаемые значения Нет. |
|
Назначение Инициализирует мьютекс. Параметры
Возвращаемые значения Нет. |
|
Назначение Захватывает мьютекс. Если мьютекс уже захвачен, не ожидает его освобождения, а возвращает управление. Параметры
Возвращаемые значения В случае успеха возвращает Если мьютекс уже захвачен, возвращает |
|
Назначение Захватывает мьютекс. Если мьютекс уже захвачен, ожидает его освобождения сколь угодно долго. Параметры
Возвращаемые значения Нет. |
|
Назначение Освобождает мьютекс. Параметры
Возвращаемые значения Нет. |
|
Назначение Захватывает мьютекс. Если мьютекс уже захвачен, ожидает его освобождения не дольше заданного времени. Параметры
Возвращаемые значения В случае успеха возвращает Если время ожидания истекло, возвращает |
Блокировки чтения-записи
Блокировка чтения-записи – примитив синхронизации, который используется, чтобы разрешить доступ к разделяемым между потоками исполнения ресурсам либо на запись для одного потока исполнения, либо на чтение для нескольких потоков исполнения одновременно.
Типовой сценарий использования API для работы с блокировками чтения-записи включает следующие шаги:
- Инициализация блокировки чтения-записи вызовом функции
KosRWLockInit()
. - Использование блокировки чтения-записи потоками исполнения:
- Захват блокировки чтения-записи для записи (вызовом функции
KosRWLockWrite()
илиKosRWLockTryWrite()
) или для чтения (вызовом функцииKosRWLockRead()
илиKosRWLockTryRead()
). - Освобождение блокировки-чтения вызовом функции
KosRWLockUnlock()
.
- Захват блокировки чтения-записи для записи (вызовом функции
Сведения о функциях API для работы с блокировками чтения-записи приведены в таблице ниже.
Функции rwlock.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует блокировку чтения-записи. Параметры
Возвращаемые значения Нет. |
|
Назначение Захватывает блокировку чтения-записи для чтения. Если блокировка чтения-записи уже захвачена для записи, или есть потоки исполнения, ожидающие захвата этой блокировки чтения-записи для записи, то ожидает освобождения этой блокировки чтения-записи от захвата для записи сколь угодно долго. Параметры
Возвращаемые значения Нет. |
|
Назначение Захватывает блокировку чтения-записи для чтения. Если блокировка чтения-записи уже захвачена для записи, или есть потоки исполнения, ожидающие захвата этой блокировки чтения-записи для записи, то не ожидает освобождения этой блокировки чтения-записи от захвата для записи, а возвращает управление. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Захватывает блокировку чтения-записи для записи. Если блокировка чтения-записи уже захвачена для записи или чтения, ожидает освобождения этой блокировки чтения-записи сколь угодно долго. Параметры
Возвращаемые значения Нет. |
|
Назначение Захватывает блокировку чтения-записи для записи. Если блокировка чтения-записи уже захвачена для записи или чтения, не ожидает освобождения этой блокировки чтения-записи, а возвращает управление. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Освобождает блокировку чтения-записи. Параметры
Возвращаемые значения Нет. Дополнительные сведения Если блокировка чтения-записи захвачена для чтения, то эта блокировка чтения-записи остается захваченной для чтения, пока все потоки исполнения, выполняющие чтение, не освободят ее. |
Семафоры
Семафор – примитив синхронизации, основанный на счетчике, значение которого может быть атомарно изменено. Значение счетчика обычно отражает число доступных разделяемых между потоками исполнения ресурсов. Для исполнения критической секции поток ожидает, пока значение счетчика не станет больше нуля. Если значение счетчика больше нуля, то оно уменьшается на единицу, и поток исполняет критическую секцию. После исполнения критической секции поток исполнения сигнализирует семафор, в результате чего значение счетчика увеличивается.
Типовой сценарий использования API для работы с семафорами включает следующие шаги:
- Инициализация семафора вызовом функции
KosSemaphoreInit()
. - Использование семафора потоками исполнения:
- Ожидание семафора вызовом функции
KosSemaphoreWait()
,KosSemaphoreWaitTimeout()
илиKosSemaphoreTryWait()
. - Сигнализация семафора вызовом функции
KosSemaphoreSignal()
илиKosSemaphoreSignalN()
.
- Ожидание семафора вызовом функции
- Освобождение ресурсов семафора вызовом функции
KosSemaphoreDeinit()
.
Сведения о функциях API для работы с семафорами приведены в таблице ниже.
Функции semaphore.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует семафор. Параметры
Возвращаемые значения В случае успеха возвращает Если значение в параметре |
|
Назначение Освобождает ресурсы семафора. Параметры
Возвращаемые значения В случае успеха возвращает Если есть потоки исполнения, ожидающие семафор, возвращает |
|
Назначение Сигнализирует семафор с увеличением счетчика на единицу. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Сигнализирует семафор с увеличением счетчика на заданное число. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Ожидает семафор не дольше заданного времени. Параметры
Возвращаемые значения В случае успеха возвращает Если время ожидания истекло, возвращает |
|
Назначение Ожидает семафор сколь угодно долго. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Ожидает семафор. Если счетчик семафора имеет нулевое значение, не ожидает увеличения счетчика этого семафора, а возвращает управление. Параметры
Возвращаемые значения В случае успеха возвращает Если счетчик семафора имеет нулевое значение, возвращает |
Условные переменные
Условная переменная – примитив синхронизации, который используется для уведомления одного или нескольких потоков исполнения о выполнении требуемого этим потокам условия. Условная переменная используется совместно с мьютексом. Уведомляющий и уведомляемый потоки захватывают мьютекс для исполнения критических секций. Уведомляемый поток при исполнении критической секции проверяет, выполняется ли требуемое ему условие (например, подготовлены ли данные уведомляющим потоком). Если условие выполняется, то уведомляемый поток исполняет критическую секцию и освобождает мьютекс. Если условие не выполняется, то уведомляемый поток блокируется на условной переменной, ожидая выполнения условия. При этом мьютекс автоматически освобождается. Уведомляющий поток при исполнении критической секции проверяет, выполняется ли условие, требуемое уведомляемому потоку. Если условие выполняется, то уведомляющий поток сигнализирует об этом через условную переменную и освобождает мьютекс. Уведомляемый поток, заблокированный в ожидании выполнения требуемого ему условия, возобновляет исполнение критической секции, автоматически захватывая мьютекс. После исполнения критической секции уведомляемый поток освобождает мьютекс.
Типовой сценарий использования API для работы с условными переменными включает следующие шаги:
- Инициализация условной переменной и мьютекса.
Чтобы инициализировать условную переменную, нужно вызвать функцию
KosCondvarInit()
. - Использование условной переменной и мьютекса потоками исполнения.
Использование условной переменной и мьютекса на стороне уведомляемых потоков исполнения включает следующие шаги:
- Захват мьютекса.
- Проверка выполнения условия.
- Ожидание выполнения условия вызовом функции
KosCondvarWait()
илиKosCondvarWaitTimeout()
.После возврата функции
KosCondvarWait()
илиKosCondvarWaitTimeout()
обычно нужно снова проверить, что условие выполняется, так как другой уведомляемый поток исполнения также получил сигнал и мог сделать условие снова недействительным. (Например, другой поток мог извлечь данные, подготовленные уведомляющим потоком). Для этого нужно использовать следующую конструкцию:while(<условие>) <вызов KosCondvarWait() или KosCondvarWaitTimeout()> - Освобождение мьютекса.
Использование условной переменной и мьютекса на стороне уведомляющих потоков исполнения включает следующие шаги:
- Захват мьютекса.
- Проверка выполнения условия.
- Сигнализация о выполнении условия вызовом функции
KosCondvarSignal()
илиKosCondvarBroadcast()
. - Освобождение мьютекса.
Сведения о функциях API для работы с условными переменными приведены в таблице ниже.
Функции condvar.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует условную переменную. Параметры
Возвращаемые значения Нет. |
|
Назначение Ожидает выполнения условия не дольше заданного времени. Параметры
Возвращаемые значения В случае успеха возвращает Если время ожидания истекло, возвращает |
|
Назначение Ожидает выполнения условия сколь угодно долго. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Сигнализирует о выполнении условия одному из потоков исполнения, ожидающих выполнения этого условия. Параметры
Возвращаемые значения Нет. |
|
Назначение Сигнализирует о выполнении условия всем потокам исполнения, ожидающим выполнения этого условия. Параметры
Возвращаемые значения Нет. |
Управление изоляцией памяти для ввода-вывода (iommu_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/iommu/iommu_api.h
из состава KasperskyOS SDK.
API предназначен для управления изоляцией регионов физической памяти, используемых устройствами на шине PCIe для DMA. (Изоляция обеспечивается IOMMU.)
Сведения о функциях API приведены в таблице ниже.
Использование API
Без прикрепления к домену IOMMU устройство на шине PCIe не может использовать DMA. После прикрепления к домену IOMMU устройство может получить доступ ко всем буферам DMA, которые ассоциированы с этим доменом IOMMU. В один момент времени устройство может быть прикреплено только к одному домену IOMMU, но к одному домену IOMMU может быть прикреплено несколько устройств. Буфер DMA может быть ассоциирован с несколькими доменами IOMMU одновременно. Каждый домен IOMMU ассоциирован только с одним процессом, но с одним процессом может быть ассоциировано несколько доменов IOMMU. Возможность создания нескольких доменов IOMMU, ассоциированных с одним процессом, позволяет разграничить доступ к буферам DMA для разных устройств, управляемых одним процессом.
API позволяет создавать домены IOMMU, прикреплять устройства на шине PCIe к доменам IOMMU и откреплять устройства на шине PCIe от доменов IOMMU. Как правило, прикрепление устройства к домену IOMMU выполняется при инициализации драйвера. Открепление устройства от домена IOMMU обычно выполняется при возникновении ошибок во время инициализации драйвера или при финализации драйвера.
Ассоциация буфер DMA с доменом IOMMU создается при вызове функций KnIoDmaBegin()
и KnIoDmaBeginEx()
, входящих в API dma.h. Функция KnIoDmaBegin()
ассоциирует буфер DMA с автоматически созданными доменом IOMMU. Каждый процесс может быть ассоциирован только с одним таким доменом IOMMU. Этот домен IOMMU создается при первом успешном вызове функции KnIommuAttachDevice()
и существует на протяжении всего времени жизни процесса. Функция KnIoDmaBeginEx()
ассоциирует буфер DMA с доменом IOMMU, созданным вызовом функции KnIommuCreateDomain()
. Каждый процесс может быть ассоциирован с несколькими доменами IOMMU, созданными вызовами функции KnIommuCreateDomain()
. Такие домены IOMMU могут быть удалены до завершения процесса закрытием их дескрипторов.
Чтобы прикрепить устройство к автоматически созданному домену IOMMU или выполнить обратную операцию, нужно вызвать функцию KnIommuAttachDevice()
или KnIommuDetachDevice()
соответственно.
Чтобы прикрепить устройство к домену IOMMU, созданному вызовом функции KnIommuCreateDomain()
, или выполнить обратную операцию, нужно вызвать функцию KnIommuAttachDeviceToDomain()
или KnIommuDetachDeviceFromDomain()
соответственно.
Сведения о функциях API
Функции iommu_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Прикрепляет устройство на шине PCIe к автоматически созданному домену IOMMU, ассоциированному с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если IOMMU не задействован, возвращает |
|
Назначение Открепляет устройство на шине PCIe от автоматически созданного домена IOMMU, ассоциированного с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если IOMMU не задействован, возвращает |
|
Назначение Создает домен IOMMU, ассоциированный с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Прикрепляет устройство на шине PCIe к заданному домену IOMMU, ассоциированному с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Открепляет устройство на шине PCIe от заданного домена IOMMU, ассоциированного с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает |
Использование очередей (queue.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/queue.h
из состава KasperskyOS SDK.
API позволяет организовать обмен данными между потоками исполнения, принадлежащими одному процессу, через механизм очередей без блокировок. То есть для добавления или извлечения элементов очереди не требуется блокирование других потоков исполнения, добавляющих или извлекающих элементы этой очереди.
Сведения о функциях API приведены в таблице ниже.
Использование API
Типовой сценарий использования API включает следующие шаги:
- Создание абстракции очереди.
Абстракция очереди состоит из структуры, содержащей метаданные об очереди, и буфера очереди, предназначенного для хранения элементов очереди. Буфер очереди логически разделен на равные участки, каждый из которых предназначен для отдельного элемента очереди. Число участков в буфере очереди соответствует максимальному числу элементов в очереди. Выравнивание адресов участков соответствует типам данных элементов очереди.
Чтобы выполнить этот шаг, нужно вызвать функцию
KosQueueCreate()
. Эта функция может выделить память для буфера очереди или использовать уже выделенную память. Размер уже выделенной памяти должен быть достаточным, чтобы вместить максимальное число элементов в очереди. При этом нужно учитывать, что размер участка в буфере очереди округляется до ближайшего большего кратного значению выравнивания, заданному через параметрobjAlign
. Также начальный адрес уже выделенной памяти должен быть выровнен так, чтобы соответствовать типам данных элементов очереди. Если выравнивание адреса памяти, указанного в параметреbuffer
, меньше заданного через параметрobjAlign
, то функция вернетRTL_NULL
. - Обмен данными между потоками исполнения через добавление и извлечение элементов очереди.
Чтобы добавить один элемент в конец очереди, нужно зарезервировать участок в буфере очереди вызовом функции
KosQueueAlloc()
, скопировать этот элемент в зарезервированный участок и вызвать функциюKosQueuePush()
.Чтобы добавить последовательность элементов в конец очереди, нужно зарезервировать требуемое количество участков в буфере очереди вызовами функции
KosQueueAlloc()
, скопировать элементы этой последовательности в зарезервированные участки и вызвать функциюKosQueuePushArray()
. Порядок элементов последовательности не изменяется после добавления этой последовательности в очередь. То есть элементы добавляются очередь в том же порядке, в каком указатели на зарезервированные участки в буфере очереди помещены в массив, передаваемый через параметрobjs
функцииKosQueuePushArray()
.Чтобы извлечь первый элемент очереди, нужно вызвать функцию
KosQueuePop()
. Эта функция возвращает указатель на зарезервированный участок в буфере очереди, который содержит первый элемент очереди. После использования извлеченного элемента (например, после проверки или сохранения значения элемента) нужно отменить резервирование занятого этим элементом участка в буфере очереди. Для этого нужно вызвать функциюKosQueueFree()
.Чтобы очистить очередь и отменить резервирование всех зарезервированных участков в буфере очереди, нужно вызвать функцию
KosQueueFlush()
. - Удаление абстракции очереди.
Чтобы выполнить этот шаг, нужно вызвать функцию
KosQueueDestroy()
. Эта функция удаляет буфер очереди, если только память для этого буфера была выделена функциейKosQueueCreate()
. В противном случае нужно отдельно выполнить удаление буфера очереди.
Сведения о функциях API
Функции queue.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает абстракцию очереди. Параметры
Возвращаемые значения В случае успеха возвращает идентификатор абстракции очереди, иначе возвращает |
|
Назначение Удаляет абстракцию очереди. Параметры
Возвращаемые значения Нет. |
|
Назначение Резервирует участок в буфере очереди. Параметры
Возвращаемые значения В случае успеха возвращает указатель на зарезервированный участок в буфере очереди, иначе возвращает |
|
Назначение Отменяет резервирование заданного участка в буфере очереди. Параметры
Возвращаемые значения Нет. |
|
Назначение Добавляет элемент в конец очереди. Параметры
Возвращаемые значения Нет. |
|
Назначение Добавляет последовательность элементов в конец очереди. Параметры
Возвращаемые значения Нет. |
|
Назначение Извлекает первый элемент очереди. Параметры
Возвращаемые значения В случае успеха возвращает указатель на зарезервированный участок в буфере очереди, который содержит первый элемент очереди. Иначе возвращает |
|
Назначение Очищает очередь и отменяет резервирование всех зарезервированных участков в буфере очереди. Параметры
Возвращаемые значения Нет. |
Использование барьеров памяти (barriers.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/barriers.h
из состава KasperskyOS SDK.
API позволяет устанавливать барьеры на чтение из памяти и/или на запись в память. Барьер памяти (англ. memory barrier) – это инструкция для компилятора и процессора, которая гарантирует, что операции доступа к памяти, указанные в исходном коде до установки барьера, будут выполнены до операций доступа к памяти, указанных в исходном коде после установки барьера. Использование барьеров памяти требуется, если важен порядок операций чтения из памяти и/или записи в память, поскольку действия компилятора и/или процессора, связанные с оптимизацией, могут привести к тому, что эти операции будут выполнены в порядке, отличном от указанного в исходном коде.
Сведения о функциях API приведены в таблице ниже.
Функции barriers.h
Функция |
Сведения о функции |
---|---|
|
Назначение Устанавливает барьер на чтение из памяти. Параметры Нет. Возвращаемые значения Нет. |
|
Назначение Устанавливает барьер на запись в память. Параметры Нет. Возвращаемые значения Нет. |
|
Назначение Устанавливает барьер на запись в память и чтение из памяти. Параметры Нет. Возвращаемые значения Нет. |
Выполнение системных вызовов (syscalls.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/syscalls.h
из состава KasperskyOS SDK.
API позволяет выполнять системные вызовы Call()
, Recv()
и Reply()
для отправки и получения IPC-сообщений.
Сведения о функциях API приведены в таблице ниже.
Использование API
Для передачи функциям API указателей на буферы с фиксированной частью и ареной IPC-сообщений используется заголовок IPC-сообщений, тип которого определен в заголовочном файле sysroot-*-kos/include/ipc/if_rend.h
из состава KasperskyOS SDK. Перед вызовами функций API заголовки IPC-сообщений нужно связать с буферами, содержащими фиксированную часть и арену IPC-сообщений. Для этого нужно использовать функции PackInMsg()
и PackOutMsg()
, объявленные в заголовочном файле sysroot-*-kos/include/services/rtl/nk_msg.h
из состава KasperskyOS SDK.
Функции Call()
, CallEx()
, Recv()
и RecvEx()
блокируют исполнение вызывающего потока, ожидая завершения системных вызовов. Функции CallEx()
и RecvEx()
позволяют задать время ожидания завершения системного вызова, по истечении которого незавершенный системный вызов прерывается, и поток, ожидающий его завершения, возобновляет исполнение. Также системный вызов прерывается, если при его выполнении возникла ошибка (например, из-за завершения серверного процесса). Завершение потока исполнения извне тоже прерывает системный вызов, завершения которого ожидает этот поток. Системный вызов, выполняемый функцией CallEx()
или RecvEx()
, можно прервать (например, для корректного завершения процесса) с использованием API ipc_api.h.
Если системный вызов был прерван с использованием API ipc_api.h, то функции CallEx()
и RecvEx()
возвращают код ошибки rcIpcInterrupt
. Если отправка IPC-сообщения запрещена механизмами безопасности (модулем безопасности Kaspersky Security Module или механизмом безопасности на основе мандатных ссылок, реализуемым ядром KasperskyOS), то функции Call()
, CallEx()
и Reply()
возвращают код ошибки rcSecurityDisallow
.
Сведения о функциях API
Функции syscalls.h
Функция |
Сведения о функции |
---|---|
|
Назначение Выполняет системный вызов Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет системный вызов Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет системный вызов Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет системный вызов Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет системный вызов Параметры
Возвращаемые значения В случае успеха возвращает |
Прерывание IPC (ipc_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/ipc/ipc_api.h
из состава KasperskyOS SDK.
API позволяет прерывать системные вызовы Call()
и Recv()
, в ожидании завершения которых заблокирован один или несколько потоков процесса. Прерывать системные вызовы требуется, например, чтобы корректно завершить процесс, поскольку потоки, ожидающие завершения этих системных вызовов, возобновляют исполнение.
Сведения о функциях API приведены в таблице ниже.
Использование API
API позволяет прерывать системные вызовы в потоках процесса, которые заблокированы после вызова функции CallEx()
или RecvEx()
из API syscalls.h, если эти функции вызваны с указанием дескриптора объекта синхронизации IPC в параметре syncHandle
. Чтобы создать объекта синхронизации IPC, нужно вызвать функцию KnIpcCreateSyncObject()
. (Дескриптор объекта синхронизации IPC не может быть передан другому процессу, так как в маске прав этого дескриптора не установлен необходимый для этого флаг.)
Функция KnIpcSetInterrupt()
переводит объект синхронизации IPC в состояние, при котором прерываются системные вызовы в тех потоках процесса, которые заблокированы после вызова функции CallEx()
или RecvEx()
с указанием дескриптора этого объекта синхронизации IPC в параметре syncHandle
. Прерывание системного вызова возможно только на некоторых стадиях его выполнения. Системный вызов, выполняемый функцией CallEx()
, может быть прерван только тогда, когда на сервере еще не вызвана функция Recv()
или RecvEx()
для того IPC-канала, клиентский IPC-дескриптор которого указан при вызове функции CallEx()
. Системный вызов, выполняемый функцией RecvEx()
, может быть прерван только во время ожидания IPC-запроса от клиента.
Функция KnIpcClearInterrupt()
отменяет действие функции KnIpcSetInterrupt()
.
Чтобы удалить объект синхронизации IPC, нужно закрыть его дескриптор вызовом функции KnHandleClose()
, объявленной в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Сведения о функциях API
Функции ipc_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает объект синхронизации IPC. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Переводит заданный объект синхронизации IPC в состояние, при котором системные вызовы Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Переводит заданный объект синхронизации IPC в состояние, при котором системные вызовы Параметры
Возвращаемые значения В случае успеха возвращает |
Использование сессий (session.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/session.h
из состава KasperskyOS SDK.
API предназначен для применения в коде поставщиков ресурсов, предоставляющих доступ к пользовательским ресурсам через IPC, и в коде программ, использующих пользовательские ресурсы локально (без IPC). API позволяет организовать управление доступом к пользовательским ресурсам на основе сессий. Сессия представляет собой последовательность действий: открытие доступа к ресурсу, использование ресурса, закрытие доступа к ресурсу. Открытие доступа к ресурсу создает сессию. Закрытие доступа к ресурсу завершает сессию. В одной сессии может выполняться несколько операций с ресурсом одновременно. Ресурс может быть использован в режиме эксклюзивного или множественного доступа. Во втором случае ресурс должен быть открыт несколько раз (возможно с разными правами доступа), то есть ресурс будет использован через множество одновременно существующих сессий (параллельных сессий).
"Объект" в описании API – это объект KosObject
, который представляет собой абстракцию ресурса (об объектах KosObject
см. "Использование объектов KosObject (objects.h)"). Также тип сессий и контекст сессии являются объектами KosObject
. (Контекст сессии содержит сведения об этой сессии, такие как права доступа к ресурсу, счетчик активных операций с ресурсом.)
Сведения о функциях API приведены в таблице ниже.
Создание типа сессий
Созданию сессий предшествует создание их типа. Чтобы создать тип сессий, нужно вызвать функцию KosSessionCreateType()
.
Через параметр objectType
нужно задать тип объектов, для которых предназначены сессии создаваемого типа. Тип объектов должен наследовать тип с идентификатором kosSessionBaseObjectType
.
Через параметр sessionType
нужно задать тип контекстов сессий. Можно указать базовый тип контекстов сессий с идентификатором kosSessionBaseSessionType
либо тип, который наследует его. Базовому типу контекстов сессий соответствует структура, содержащая такие данные, как указатель на объект, права доступа к ресурсу, маска прав дескриптора ресурса, передаваемая потребителям ресурсов, счетчик активных операций с ресурсом в сессии (тип этой структуры не экспортируется программам, а используется библиотекой libkos
). Можно добавить в контекст сессии дополнительные сведения, создав собственный тип контекстов сессий, наследующий базовый. Например, контекст сессии использования устройства может дополнительно содержать указатели на функции, вызываемые программами решения для работы с устройством.
Через параметр ops
нужно задать callback-функции, вызываемые при создании и завершении сессий. Callback-функции для идентификаторов open
и close
нужно задать обязательно. Callback-функцию для идентификатора closeComplete
можно не задавать, поэтому этот идентификатор может иметь значение RTL_NULL
.
Callback-функция, соответствующая идентификатору open
, вызывается при создании сессии и получает указатели на объект, контекст сессии, данные, переданные функции KosSessionOpenObject()
через параметр openCtx
, и буфер для сохранения маски прав дескриптора ресурса, передаваемой потребителям ресурсов. В этой callback-функции можно, например, проверить состояние ресурса, задать передаваемую потребителям ресурсов маску прав дескриптора ресурса, выполнить запись данных в объект или контекст сессии. Если код возврата будет отличным от rcOk
, сессия не будет создана.
Callback-функция, соответствующая идентификатору close
, вызывается при завершении сессии независимо от того, завершены операции с ресурсом или нет (счетчик активных операций в закрываемой сессии может быть больше нуля), и получает указатели на объект и контекст сессии. В этой callback-функции можно, например, прервать активные операции в завершаемой сессии, выполнить запись данных в объект или контекст сессии. Код возврата может быть произвольным.
Callback-функция, соответствующая идентификатору closeComplete
, вызывается при завершении сессии только после завершения всех операций с ресурсом (счетчик активных операций в завершаемой сессии равен нулю) и получает указатели на объект и контекст сессии. В этой callback-функции можно, например, выполнить запись данных в объект.
Регистрация объекта
После создания типа сессий нужно зарегистрировать требуемые объекты как объекты, с которыми могут быть связаны сессии этого типа. Чтобы зарегистрировать объект, нужно вызвать функцию KosSessionRegisterObject()
.
Нельзя зарегистрировать один объект для связывания с разными типами сессий одновременно.
После регистрации объект готов к открытию.
Открытие объекта
Открытие объекта создает сессию, связанную с этим объектом, и выполняется по запросу на открытие доступа к ресурсу. Это может быть запрос через IPC от потребителя ресурсов или локальный запрос от другого компонента программы.
Чтобы открыть объект, нужно вызвать функцию KosSessionOpenObject()
. Через параметр requiredRights
нужно задать права доступа к ресурсу в создаваемой сессии, а через параметр shareMode
нужно задать права множественного доступа к ресурсу, которые устанавливают ограничения доступа к этому ресурсу для параллельных сессий. Например, если через параметр requiredRights
заданы права на чтение и запись, а в параметре shareMode
указан 0
, то создаваемая сессия требует эксклюзивного доступа к ресурсу на чтение и запись. Если через параметр requiredRights
заданы права на чтение и запись, а через параметр shareMode
заданы права только на чтение, то создаваемая сессия требует доступа на чтение и запись и разрешает чтение в параллельных сессиях. Если через параметр requiredRights
заданы права на чтение, а через параметр shareMode
заданы права на чтение и запись, то создаваемая сессия требует доступа на чтение, а также разрешает чтение и запись в параллельных сессиях.
Если ресурс требуется использовать в режиме множественного доступа, то при втором и последующих открытиях объекта нужно учесть следующие условия:
- Права доступа, задаваемые через параметр
requiredRights
, не могут превышать минимальных прав доступа, заданных через параметрshareMode
для всех параллельных сессий, связанных с этим объектом. - Права доступа, задаваемые через параметр
shareMode
, должны включать все права доступа, заданные через параметрrequiredRights
для всех параллельных сессий, связанных с этим объектом.
В результате открытия объекта будет создан контекст сессии.
Если программа использует ресурсы локально, то после открытия объекта компонент программы, управляющий ресурсами, должен передать компоненту программы, использующему ресурсы, указатель на созданный контекст сессии. Запрашивая в дальнейшем операции с ресурсом, компонент программы, использующий ресурсы, должен передавать этот указатель компоненту программы, управляющему ресурсами, для идентификации сессии.
Поставщик ресурсов после открытия объекта должен передать потребителю дескриптор ресурса. В качестве контекста передачи ресурса должен использоваться контекст сессии, чтобы потребитель получил дескриптор ресурса, связанный с сессией. Запрашивая в дальнейшем операции с ресурсом, потребитель должен помещать полученный дескриптор ресурса в IPC-запросы, чтобы после разыменования этого дескриптора поставщик получал указатель на контекст сессии. Чтобы заполнить данными транспортный контейнер дескриптора ресурса для передачи потребителю ресурсов, нужно вызвать функцию KosSessionContextToIpcHandle()
. Через параметр sessionCtx
эта функция получает контекст сессии, а через параметр desc
передает транспортный контейнер дескриптора ресурса.
Функция KosSessionContextToIpcHandle()
помещает в транспортный контейнер дескриптора ресурса маску прав, заданную в callback-функции, которая вызывается при создании сессии. Права доступа, заданные в этой маске, не должны превышать права доступа в сессии, заданные через параметр requiredRights
функции KosSessionOpenObject()
. При этом одно и то же право доступа может соответствовать разным битам в маске прав и в значении, заданном через параметр requiredRights
функции KosSessionOpenObject()
.
В качестве контекста передачи ресурса функция KosSessionContextToIpcHandle()
задает контекст сессии. Контекст сессии будет автоматически удален (соответственно сессия будет завершена) после закрытия или отзыва дескрипторов ресурса, порожденных передачей дескриптора ресурса, который получен вызовом функции KosSessionContextToIpcHandle()
. Если требуется предотвратить автоматическое завершение сессии для последующего завершения вызовом функции KosSessionCloseObject()
, перед передачей дескриптора ресурса нужно инкрементировать счетчик ссылок на контекст этой сессии вызовом функции KosRefObject()
из API objects.h. В этом случае после вызова функции KosSessionCloseObject()
нужно декрементировать счетчик ссылок на контекст сессии вызовом функции KosPutObject()
из API objects.h.
Выполнение операций с ресурсом
Операция с ресурсом (например, чтение, запись, получение параметров) выполняется по запросу через IPC от потребителя ресурсов или по локальному запросу от другого компонента программы.
Сценарий выполнения операции с ресурсом включает следующие шаги:
- Проверить права доступа к ресурсу.
При обработке локального запроса нужно вызвать функцию
KosSessionGetOpenRights()
. Эта функция позволяет получить сведения о правах доступа к ресурсу в сессии, заданных через параметрrequiredRights
функцииKosSessionOpenObject()
, чтобы сравнить эти права с требуемыми для выполнения операции.При обработке IPC-запроса нужно вызвать функцию
KosSessionIpcHandleToSession()
, которая позволяет получить контекст сессии, а также проверяет, что маска прав дескриптора ресурса, который потребитель ресурсов поместил в IPC-запрос, соответствует запрашиваемой операции. Через параметрdesc
нужно передать функции полученный от потребителя ресурса транспортный контейнер дескриптора ресурса. В параметреoperation
нужно указать права доступа к ресурсу, требуемые для выполнения запрашиваемой операции. В параметреtype
можно указать идентификатор типа сессии, чтобы проверить, что тип контекста сессии соответствует типу сессии. Если в параметреtype
указать значениеRTL_NULL
, то перед приведением типа указателя, полученного через параметрsessionCtx
, нужно проверить тип контекста сессии. Проверку типа контекста сессии нужно сделать обязательно, поскольку поставщик ресурсов может создавать сессии с контекстами разных типов, а потребитель ресурсов может ошибочно поместить в IPC-запрос дескриптор ресурса, который соответствует сессии с контекстом другого типа. Чтобы проверить тип контекста, нужно использовать API objects.h. - Инкрементировать счетчик активных операций в сессии вызовом функции
KosSessionRef()
.Функция проверяет, что сессия не завершена. В параметре
type
можно указать идентификатор типа сессии, чтобы проверить, что тип контекста сессии соответствует типу сессии. Через параметрobject
можно получить указатель на объект. - Выполнить запрошенные действия с ресурсом.
- Декрементировать счетчик активных операций в сессии вызовом функции
KosSessionPut()
.
Получение дескриптора ресурса
Дескриптор ресурса может потребоваться, например, для использования уведомлений или для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности. Чтобы получить дескриптор ресурса по объекту или по контексту сессии, нужно вызвать функцию KosSessionGetObjectHandle()
или KosSessionGetObjectHandleBySession()
соответственно.
Перечисление сессий, связанных с объектом
Перечисление сессий, связанных с объектом, может потребоваться, например, чтобы сообщать о состоянии ресурса каждому из потребителей ресурсов, использующих этот ресурс. Чтобы перечислить сессии, связанные с объектом, нужно вызвать функцию KosSessionWalk()
. Через параметр handler
нужно задать callback-функцию, которая вызывается для каждой сессии при перечислении и получает указатели на объект, контекст сессии и данные, переданные функции KosSessionWalk()
через параметр walkCtx
. В этой callback-функции можно, например, отправить потребителям ресурсов уведомления о состоянии ресурса.
Закрытие объекта
Закрытие объекта завершает одну из сессий, связанных с этим объектом. Завершение сессии не будет выполнено, пока не будут завершены все операции в этой сессии, то есть счетчик активных операций не станет равным нулю. При завершении сессии автоматически отзываются дескрипторы ресурса, связанные с этой сессией.
Закрытие объекта выполняется по запросу на закрытие доступа к ресурсу. Это может быть запрос через IPC от потребителя ресурсов или локальный запрос от другого компонента программы. После выполнения запроса на закрытие доступа к ресурсу потребитель ресурсов должен закрыть дескриптор этого ресурса. (Если потребитель ресурсов завершится, не выполнив запрос на закрытие доступа к ресурсу, либо закроет дескриптор ресурса без выполнения этого запроса, то соответствующая сессия будет автоматически завершена при условии, что поставщик ресурсов дополнительно не инкременетировал счетчик ссылок на контекст этой сессии.)
Чтобы закрыть объект, нужно вызвать функцию KosSessionCloseObject()
или KosSessionCloseObjectByIpcHandle()
.
Функция KosSessionCloseObject()
завершает сессию, соответствующую контексту сессии, заданному через параметр sessionCtx
.
Функция KosSessionCloseObjectByIpcHandle()
завершает сессию, с которой связан дескриптор ресурса, помещенный потребителем ресурса в IPC-запрос на закрытие доступа к ресурсу. Через параметр desc
нужно передать функции полученный транспортный контейнер дескриптора ресурса. В параметре type
можно указать идентификатор типа сессии, чтобы проверить, что тип контекста сессии соответствует типу сессии.
Дерегистрация объекта
Дерегистрация объекта делает невозможным открытие этого объекта и завершает все связанные с ним сессии. Завершение сессии не будет выполнено, пока не будут завершены все операции в этой сессии, то есть счетчик активных операций не станет равным нулю. При завершении сессии автоматически отзываются дескрипторы ресурса, связанные с этой сессией. (Отзыв не закрывает дескрипторы ресурса, поэтому отозванные дескрипторы нужно закрыть.)
Чтобы дерегистрировать объект, нужно вызвать функцию KosSessionUnregisterObject()
.
Удаление типа сессий
Тип сессий нужно удалить, если отсутствуют зарегистрированные объекты, для которых можно использовать сессии этого типа, и больше регистраций не будет. Например, тип сессий требуется удалить при завершении работы поставщика ресурсов.
Чтобы удалить тип сессий, нужно вызвать функцию KosSessionDestroyType()
.
Сведения о функциях API
Функции session.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает тип сессий. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет тип сессий. Параметры
Возвращаемые значения Нет. |
|
Назначение Регистрирует объект как объект, с которым могут быть связаны сессии заданного типа. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Дерегистрирует объект, зарегистрированный вызовом функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Открывает объект. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Закрывает объект. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Инкрементирует счетчик активных операций в сессии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Декрементирует счетчик активных операций в сессии. Параметры
Возвращаемые значения Нет. |
|
Назначение Перечисляет сессии, связанные с заданными объектом. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если callback-функция, заданная через параметр Callback-функция, заданная через параметр |
|
Назначение Позволяет получить сведения о правах доступа к ресурсу в заданной сессии. Эти права были заданы через параметр Параметры
Возвращаемые значения В случае успеха возвращает значение, отражающее права доступа к ресурсу, иначе возвращает |
|
Назначение Заполняет данными транспортный контейнер дескриптора ресурса для передачи потребителю ресурса при обработке IPC-запроса на открытие доступа к ресурсу. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить контекст сессии при обработке IPC-запроса от потребителя ресурсов. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Закрывает объект при обработке IPC-запроса от потребителя ресурса на закрытие доступа к ресурсу. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить дескриптор ресурса по объекту. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить дескриптор ресурса по контексту сессии. Параметры
Возвращаемые значения В случае успеха возвращает |
Использование объектов KosObject (objects.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/objects.h
из состава KasperskyOS SDK.
API позволяет использовать типизированные объекты KosObject
. Объект KosObject
представляет собой регион памяти процесса, состоящий из сегментов со служебными и полезными данными. Служебные данные включают указатель на структуру, описывающую тип объекта, счетчик ссылок на объект и другие сведения об объекте. Состав полезных данных может быть любым в зависимости от назначения объекта. Например, сегменты полезных данных в объекте, который представляет собой абстракцию устройства, хранят структуры, которые содержат параметры функционирования устройства, указатели на низкоуровневые методы работы с ним, а также параметры программно-аппаратных интерфейсов для управления устройством.
Для объектов KosObject
поддерживается механизм наследования типов. Например, абстракция устройства NS16550 UART содержит в разных сегментах полезных данных следующие структуры: специфичную для типа устройств NS16550 UART, специфичную для класса устройств UART, общие для любых устройств. Тип абстракции устройства NS16550 UART соответствует только той структуре, которая специфична для устройств NS16550 UART. Все остальные структуры соответствуют типам, которые унаследовал тип абстракции устройства NS16550 UART.
В API указателем на объект является указатель на сегмент полезных данных в этом объекте.
Сведения о функциях API приведены в таблице ниже.
Создание типа объектов
Созданию объектов предшествует создание их типа. Тип объектов представляет собой регион памяти процесса, содержащий структуру, которая включает такие данные, как имя типа, указатели на функции, вызываемые при создании и уничтожении объектов этого типа, указатель на родительский тип, счетчик ссылок на тип. В каждом объекте хранится указатель на такую структуру, что делает объекты типизированными.
Чтобы создать тип объектов, нужно вызвать функцию KosCreateObjectType()
или KosCreateObjectTypeEx()
. В отличие от функции KosCreateObjectType()
функция KosCreateObjectTypeEx()
позволяет создать тип, наследующий другие типы. Такой тип содержит адрес родительского типа, заданного через параметр parentType
. При этом через параметр parentType
можно задать тип, который также содержит адрес своего родительского типа. В итоге, используя функцию KosCreateObjectTypeEx()
, можно создать дерево наследования типов. Каждый тип в этом дереве будет наследовать всю цепочку типов, образующих путь от корня дерева до этого типа.
В зависимости от того, используется наследование типов или нет, объекты могут быть простыми и составными. Объекты, которые соответствуют одному типу, являются простыми. Объекты, которые соответствуют цепочке наследования типов, являются составными. Составные объекты состоят из простых. Число простых объектов в составном равно числу типов в цепочке наследования. При этом эти простые объекты образуют цепочку наследования, соответствующую цепочке наследования их типов, то есть каждый объект, кроме первого в цепочке наследования, содержит адрес родительского объекта.
Через параметр defaultObjSize
функций KosCreateObjectType()
и KosCreateObjectTypeEx()
нужно задать размер объектов по умолчанию (при создании объекта можно задать другой размер). В случае создания типа, наследующего другие типы, этот параметр имеет отношение только к последнему типу в цепочке наследования. Фактически параметр defaultObjSize
задает минимальный размер сегмента полезных данных в простых объектах, поскольку действительный размер объектов будет больше заданного из-за выравнивания регионов памяти, наследования типов и наличия сегментов со служебными данными.
Через параметр ops
функций KosCreateObjectType()
и KosCreateObjectTypeEx()
можно задать callback-функции, вызываемые при создании и уничтожении объектов (можно задать обе функции или только одну). При создании составного объекта внутри него создается набор простых объектов, а при уничтожении составного объекта внутри него уничтожается набор простых объектов. При создании и уничтожении каждого простого объекта вызываются отдельные callback-функции, заданные при создании типа этого объекта. Первым создается первый объект в цепочке наследования, последним создается последний объект цепочке наследования. Первым уничтожается последний объект в цепочке наследования, последним уничтожается первый объект в цепочке наследования.
Callback-функция, вызываемая при создании объекта, получает указатели на объект и данные, переданные функции KosCreateObjectEx()
через параметр context
. В этой callback-функции можно, например, выделить ресурсы, инициализировать данные в объекте. Если код возврата будет отличным от rcOk
, объект не будет создан. Если при создании составного объекта не будет создан хотя бы один простой объект, то этот составной объект не будет создан. Также при создании составного объекта данные, переданные функции KosCreateObjectEx()
через параметр context
, получит только та callback-функция, которая вызывается при создании последнего простого объекта в цепочке наследования.
Callback-функция, вызываемая при уничтожении объекта, получает указатель на объект. В этой callback-функции можно, например, освободить ресурсы. Код возврата может быть произвольным.
Создание объекта
После создания типа объектов можно создавать объекты. Чтобы создать объект, нужно вызвать функцию KosCreateObject()
или KosCreateObjectEx()
.
Через параметр type
нужно задать тип объекта. Если задать тип, не наследующий другие типы, будет создан простой объект. Если задать тип, наследующий другие типы, будет создан составной объект, в котором последний простой объект в цепочке наследования будет иметь заданный тип.
Через параметр size
нужно задать размер объекта или указать 0
, чтобы был задан размер объекта по умолчанию, указанный в типе этого объекта. В случае создания составного объекта этот параметр имеет отношение только к последнему простому объекту в цепочке наследования. Фактически параметр size
задает минимальный размер сегмента полезных данных в простом объекте, поскольку действительный размер объекта будет больше заданного из-за выравнивания региона памяти, наследования типов и наличия сегментов со служебными данными.
В отличие от функции KosCreateObject()
у функции KosCreateObjectEx()
есть параметр context
, через который можно передать данные callback-функции, вызываемой при создании объекта. При создании составного объекта данные, переданные через параметр context
, получит только та callback-функция, которая вызывается при создании последнего простого объекта в цепочке наследования.
Через параметр outObject
функции KosCreateObject()
и KosCreateObjectEx()
передают указатель на созданный объект. Указатель на созданный составной объект представляет собой указатель на последний простой объект в цепочке наследования.
После создания объект можно использовать для записи данных в него и чтения данных из него.
Получение доступа к простым объектам в составном объекте
Чтобы получать доступ к простым объектам в составном объекте, нужно использовать функцию KosGetObjectParent()
и/или функцию KosGetObjectAncestor()
. Функция KosGetObjectParent()
позволяет получить указатель на объект, который является непосредственным предком заданного объекта. Функция KosGetObjectAncestor()
позволяет получить указатель на объект, который является предком заданного объекта и имеет заданный тип.
Управление временем жизни объектов и их типов
Объект существует, пока счетчик ссылок на него имеет значение больше нуля. Также тип объектов существует, пока счетчик ссылок на него имеет значение больше нуля. При создании объекта или типа объектов значение счетчика ссылок равно 1. В дальнейшем этот счетчик можно инкрементировать и декрементировать для управления временем жизни объекта или типа объектов. Например, после создания объекта можно декрементировать счетчик ссылок на его тип, поскольку при создании объекта библиотека libkos
инкрементирует счетчик ссылок на тип этого объекта. В этом случае тип объекта будет уничтожен автоматически после уничтожения объекта, так как библиотека libkos
декрементирует счетчик ссылок на тип объекта при уничтожении объекта. Также, к примеру, при сохранении адреса объекта в другом объекте нужно инкрементировать счетчик ссылок на первый объект, чтобы обеспечить его существование на время существования второго объекта. При уничтожении объекта, который содержит адрес другого объекта, нужно декрементировать счетчик ссылок на второй объект, чтобы обеспечить его уничтожение при отсутствии других ссылок.
Время жизни простого объекта в составном соответствует времени жизни этого составного объекта. Отдельно управлять временем жизни простого объекта в составном нельзя.
Чтобы инкрементировать счетчик ссылок на объект или тип объектов, нужно вызвать функцию KosRefObject()
или KosRefObjectType()
соответственно.
Чтобы декрементировать счетчик ссылок на объект или тип объектов, нужно вызвать функцию KosPutObject()
или KosPutObjectType()
соответственно.
Проверка типа объектов
Функции KosCheckParentType()
и KosObjectTypeInheritsType()
позволяют проверить, является ли один тип объектов родительским для другого.
Функция KosObjectOfType()
проверяет, имеет ли объект заданный тип.
Функция KosObjectInheritsType()
проверяет, имеет ли объект заданный тип или тип, наследующий заданный тип.
Получение типа и имени объекта
Чтобы получить тип объекта, нужно вызвать функцию KosObjectGetType()
.
Чтобы получить имя объекта, нужно вызвать функцию KosGetObjectName()
. (Каждый простой объект в составном имеет имя этого составного объекта.)
Получение имени типа объектов
Чтобы получить имя типа объектов, нужно вызвать функцию KosObjectGetTypeName()
.
Сведения о функциях API
Функции objects.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает тип объектов. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает тип объектов. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает объект. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения При создании объекта для него выделяется память, которая заполняется нулями. |
|
Назначение Инкрементирует счетчик ссылок на тип объектов. Параметры
Возвращаемые значения Нет. |
|
Назначение Декрементирует счетчик ссылок на тип объектов. Параметры
Возвращаемые значения Нет. |
|
Назначение Проверяет, является ли тип объектов Параметры
Возвращаемые значения В случае успешной проверки возвращает |
|
Назначение Проверяет, является ли тип объектов Параметры
Возвращаемые значения В случае успешной проверки возвращает |
|
Назначение Создает объект. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения При создании объекта для него выделяется память, которая заполняется нулями. |
|
Назначение Инкрементирует счетчик ссылок на объект. Параметры
Возвращаемые значения Нет. |
|
Назначение Декрементирует счетчик ссылок на объект. Параметры
Возвращаемые значения Нет. |
|
Назначение Позволяет получить имя объекта. Параметры
Возвращаемые значения Возвращает идентификатор строки Дополнительные сведения Функция |
|
Назначение Позволяет получить указатель на объект, который является непосредственным предком заданного объекта. Параметры
Возвращаемые значения В случае успеха возвращает указатель на объект, который является непосредственным предком заданного объекта, иначе возвращает |
|
Назначение Позволяет получить указатель на объект, который является предком заданного объекта и имеет заданный тип. Параметры
Возвращаемые значения В случае успеха возвращает указатель на объект, который является предком заданного объекта и имеет заданный тип, иначе возвращает Дополнительные сведения Если через параметр |
|
Назначение Проверяет, имеет ли объект заданный тип. Параметры
Возвращаемые значения В случае успешной проверки возвращает |
|
Назначение Проверяет, имеет ли объект заданный тип либо тип, который наследует заданный тип. Параметры
Возвращаемые значения В случае успешной проверки возвращает |
|
Назначение Позволяет получить идентификатор типа объекта. Параметры
Возвращаемые значения Идентификатор типа объекта. Дополнительные сведения Инкрементирует счетчик ссылок на тип объекта. Если полученный идентификатор типа объекта больше не требуется, нужно декрементировать число ссылок на тип объекта вызовом функции |
|
Назначение Позволяет получить имя типа объектов. Параметры
Возвращаемые значения Возвращает идентификатор строки Дополнительные сведения Функция |
Использование контейнеров объектов KosObject (objcontainer.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/objcontainer.h
из состава KasperskyOS SDK.
API позволяет объединять объекты KosObject
в контейнеры для удобства использования наборов этих объектов (об объектах KosObject
см. "Использование объектов KosObject (objects.h)"). Контейнеры также являются объектами KosObject
и могу быть элементами других контейнеров. Один и тот же объект KosObject
может быть элементом нескольких контейнеров одновременно.
Сведения о функциях API приведены в таблице ниже.
Создание контейнера
Чтобы создать контейнер, нужно вызвать функцию KosCreateObjContainer()
. В параметре parent
можно указать идентификатор родительского контейнера, то есть контейнера, в который будет добавлен создаваемый контейнер.
Добавление объекта в контейнер
Чтобы добавить объект в контейнер, нужно вызвать функцию KosInsertObjContainerObject()
. Объектом может быть другой контейнер. Через параметр name
нужно задать имя объекта, которое этот объект будет иметь внутри контейнера. Это имя не связано с именем, которое было задано при создании объекта. Имя объекта внутри контейнера должно быть уникальным, чтобы однозначно идентифицировать этот объект среди других объектов в этом контейнере. Добавление объекта в контейнер инкрементирует счетчик ссылок на этот объект.
Удаление объекта из контейнера
Чтобы удалить объект из контейнера, нужно вызвать функцию KosRemoveObjContainerObjectByName()
или KosRemoveObjContainerObject()
. Удаление объекта из контейнера декрементирует счетчик ссылок на этот объект.
Поиск объекта в контейнере
Чтобы выполнить поиск объекта с заданным именем в контейнере, нужно вызвать функцию KosGetObjContainerObjectByName()
. Поиск объекта в дочерних контейнерах не выполняется. Функция инкрементирует счетчик ссылок на найденный объект.
Перечисление объектов в контейнере
Перечисление может потребоваться, чтобы выполнить какие-либо действия с несколькими объектами в контейнере. Чтобы перечислить объекты в контейнере, нужно вызвать функцию KosWalkObjContainerObjects()
. Через параметр walk
нужно задать callback-функцию, которая вызывается для каждого объекта при перечислении и получает указатели на объект и данные, переданные функции KosWalkObjContainerObjects()
через параметр context
. Перечисление объектов в дочерних контейнерах не выполняется.
Перечисление имен объектов в контейнере
Чтобы перечислить имена объектов в контейнере, нужно использовать функцию KosEnumObjContainerNames()
. Порядок перечисления имен объектов соответствует порядку добавления этих объектов в контейнер. Перечисление имен объектов в дочерних контейнерах не выполняется.
Получение числа объектов в контейнере
Чтобы получить число объектов в контейнере, нужно вызвать функцию KosCountObjContainerObjects()
. Объекты в дочерних контейнерах не учитываются.
Очистка контейнера
Чтобы удалить все объекты из контейнера, нужно вызвать функцию KosClearObjContainer()
. Функция декрементирует счетчики ссылок на удаленные из контейнера объекты.
Проверка, является ли объект контейнером
Чтобы проверить, является ли объект контейнером, нужно вызвать функцию KosIsContainer()
.
Удаление контейнера
Чтобы удалить контейнер, нужно вызвать функцию KosDestroyObjContainer()
. Удаление контейнера декрементирует счетчики ссылок на объекты, которые в нем содержались.
Сведения о функциях API
Функции objcontainer.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает контейнер. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет контейнер. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Добавляет объект в контейнер. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет из контейнера объект с заданным именем. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет объект из контейнера. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет поиск объекта с заданным именем в контейнере. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если объект с заданным именем не найден, функция передает через параметр |
|
Назначение Перечисляет объекты в контейнере и вызывает заданную функцию для каждого объекта при перечислении. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Callback-функция, заданная через параметр Если callback-функция, заданная через параметр Если callback-функция, заданная через параметр Флаги |
|
Назначение Перечисляет имена объектов в контейнере. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функция |
|
Назначение Позволяет получить число объектов в контейнере. Параметры
Возвращаемые значения Число объектов в контейнере. |
|
Назначение Очищает контейнер. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Проверяет, является ли объект контейнером. Параметры
Возвращаемые значения В случае успешной проверки возвращает |
Использование строк KosString (strings.h)
API определен в заголовочном файле sysroot-*-kos/include/kos/strings.h
из состава KasperskyOS SDK.
API позволяет использовать строки KosString
, которые имеют следующие особенности:
- Строка
KosString
представляет собой C-строку (с терминирующим нулем), следующую за заголовком со служебными данными. - Строки
KosString
хранятся в хеш-таблицах, представляющих собой массивы, элементами которых являются списки строк. (Указатели для создания связных списков строк хранятся в заголовках строк.) Каждый список состоит из одной или нескольких строк. В одном списке находятся строки, для которых остаток от деления хеш-значения строки на число списков в хеш-таблице имеет одинаковое значение. Основное свойство хеш-таблицы заключается в том, что вычислительная сложность поиска строки не зависит от степени заполнения этой таблицы, если все списки включают только одну строку.На практике при добавлении строк
KosString
в хеш-таблицу могут создаваться списки с несколькими строками, что приводит к варьированию вычислительной сложности поиска строк в хеш-таблице по следующей причине. При выполнении поиска для ключа вычисляется хеш-значение, которое преобразуется в индекс списка строк (вычислением остатка от деления хеш-значения на число списков), и, если в списке с рассчитанным индексом только одна строка, то после сравнения этой строки с ключом поиск будет завершен. Но если в списке с рассчитанным индексом несколько строк, то для завершения поиска может потребоваться сравнить ключ со всеми строками в этом списке. В таком случае вычислительная сложность поиска строки может быть больше, чем в случае с одной строкой в списке. - Строки
KosString
из одной хеш-таблицы уникальны, то есть в одной хеш-таблице нет одинаковых строк. Если строки из одной хеш-таблицы имеют разные идентификаторы, то это разные строки. (В API идентификатор строкиKosString
представляет собой указатель на эту строку.) Это позволяет сравнивать строки не по содержимому, а по идентификаторам, что обеспечивает независимость вычислительной сложности сравнения от размеров строк. - Размер строки
KosString
хранится в заголовке, а не рассчитывается на основе поиска терминирующего нуля, что обеспечивает независимость вычислительной сложности получения размера от фактического размера строки. - Строки
KosString
нельзя изменять. Эта особенность является следствием особенностей 2-4. Изменение строки может привести к появлению одинаковых строк в одной хеш-таблице, несоответствию фактического размера строки и сохраненного в заголовке, а также несоответствию содержимого строки индексу списка строк, в котором эта строка находится в хеш-таблице. - Строка
KosString
существует, пока счетчик ссылок на нее больше нуля. (Счетчик ссылок на строку хранится в заголовке.)
Сведения о функциях API приведены в таблице ниже.
Создание хеш-таблицы
Можно использовать хеш-таблицу по умолчанию, которая создается автоматически при инициализации библиотеки libkos
. Эта таблица может включать не более 2039 списков строк с размером строк не более 65524 байт без учета терминирующего нуля.
Можно создать хеш-таблицу с требуемым максимальным числом списков строк и требуемым максимальным размером строк вызовом функции KosCreateStringRoot()
.
Хеш-таблица создается пустой, то есть не содержит строк.
Добавление строки KosString в хеш-таблицу
Чтобы добавить строку в хеш-таблицу по умолчанию, нужно вызывать функцию KosCreateString()
.
Чтобы добавить строку в заданную хеш-таблицу, нужно вызвать функцию KosCreateStringEx()
.
Если добавляемая строка уже есть в хеш-таблице, эти функции не добавляют новую строку, а передают через параметр outStr
идентификатор уже существующей строки.
Поиск строки KosString в хеш-таблице
Чтобы выполнить поиск строки в хеш-таблице по умолчанию, нужно вызывать функцию KosGetString()
.
Чтобы выполнить поиск строки в заданной хеш-таблице, нужно вызывать функцию KosGetStringEx()
.
Поиск завершается успешно, если ключ и строка полностью совпадают.
Управление временем жизни строк KosString
Строка существует, пока счетчик ссылок на нее больше нуля. Функции KosCreateString()
и KosCreateStringEx()
добавляют в хеш-таблицу строку, счетчик ссылок на которую имеет значение 1. Если строка уже добавлена в хеш-таблицу, эти функции инкрементируют счетчик ссылок на эту строку. Функции KosGetString()
и KosGetStringEx()
инкрементируют счетчик ссылок на найденную строку. В дальнейшем этот счетчик можно инкрементировать и декрементировать для управления временем жизни строки. Передавая идентификатор строки другому компоненту программы, нужно инкрементировать счетчик ссылок на соответствующую строку, чтобы обеспечить существование этой строки на время, требуемое этому компоненту. Если строка больше не требуется, нужно декрементировать счетчик ссылок на эту строку, чтобы обеспечить ее уничтожение при отсутствии других ссылок.
Чтобы инкрементировать счетчик ссылок на строку, нужно вызвать функцию KosRefString()
или KosRefStringEx()
.
Чтобы декрементировать счетчик ссылок на строку в хеш-таблице по умолчанию, нужно вызывать функцию KosPutString()
.
Чтобы декрементировать счетчик ссылок на строку в заданной хеш-таблице, нужно вызывать функцию KosPutStringEx()
.
Получение размера строки KosString
Чтобы получить размер строки без учета терминирующего нуля, нужно вызвать функцию KosGetStringLen()
.
Чтобы получить размер строки с учетом терминирующего нуля, нужно вызвать функцию KosGetStringSize()
.
Удаление хеш-таблицы
Чтобы удалить хеш-таблицу, нужно вызвать функцию KosDestroyStringRoot()
. Таблица будет удалена только в том случае, если она пустая.
Сведения о функциях API
Функции strings.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает пустую хеш-таблицу. Параметры
Возвращаемые значения Идентификатор хеш-таблицы. |
|
Назначение Удаляет пустую хеш-таблицу. Параметры
Возвращаемые значения Нет. |
|
Назначение Выполняет поиск строки Параметры
Возвращаемые значения В случае успеха возвращает идентификатор строки |
|
Назначение Выполняет поиск строки Параметры
Возвращаемые значения В случае успеха возвращает идентификатор строки |
|
Назначение Добавляет строку Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Добавляет строку Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Инкрементирует счетчик ссылок на строку Параметры
Возвращаемые значения Нет. |
|
Назначение Инкрементирует счетчик ссылок на строку Параметры
Возвращаемые значения Нет. |
|
Назначение Декрементирует счетчик ссылок на строку Параметры
Возвращаемые значения Нет. |
|
Назначение Декрементирует счетчик ссылок на строку Параметры
Возвращаемые значения Нет. |
|
Назначение Позволяет получить размер строки Параметры
Возвращаемые значения Размер строки Дополнительные сведения Если параметр имеет значение |
|
Назначение Позволяет получить размер строки Параметры
Возвращаемые значения Размер строки Дополнительные сведения Если параметр имеет значение |
Управление драйвером XHCI DbC ядра KasperskyOS (xhcidbg_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/xhcidbg/xhcidbg_api.h
из состава KasperskyOS SDK.
API предназначен для использования в коде драйверов, реализующих стек USB (драйверов класса kusb), и позволяет останавливать и запускать драйвер XHCI DbC (Debug Capability) ядра KasperskyOS. (Ядро KasperskyOS включает драйвер XHCI DbC, который представляет собой упрощенный драйвер контроллера XHCI и используется ядром для диагностического вывода либо GDB-сервером ядра для взаимодействия с отладчиком GDB.) Если драйверу класс kusb нужно перезагрузить контроллер XHCI, то драйвер XHCI DbC ядра необходимо остановить вызовом функции KnXhcidbgStop()
перед перезагрузкой и запустить вызовом функции KnXhcidbgStart()
после перезагрузки. Если этого не сделать, перезагрузка контроллера XHCI приведет к невозможности выполнять диагностический вывод (или отладку) через порт USB.
Для аппаратных платформ Raspberry Pi 4 B и Radxa ROCK 3A API не реализован (функции возвращают rcUnimplemented
).
Сведения о функциях API приведены в таблице ниже.
Функции xhcidbg_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Запускает драйвер XHCI DbC ядра KasperskyOS. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Останавливает драйвер XHCI DbC ядра KasperskyOS. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
Получение данных аудита безопасности (vlog_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/vlog/vlog_api.h
из состава KasperskyOS SDK.
API позволяет выполнять чтение из журнала ядра KasperskyOS с данными аудита безопасности и используется в коде статической библиотеки sysroot-*-kos/lib/libklog_system_audit.a
, компонуемой с системной программой Klog
.
Сведения о функциях API приведены в таблице ниже.
Использование API
Сценарий использования API включает следующие шаги:
- Открытие журнала ядра с данными аудита безопасности вызовом функции
KnAuOpen()
. - Получение сообщений из журнала ядра с данными аудита безопасности вызовами функции
KnAuRead()
.Журнал представляет собой циклический буфер, поэтому нужно не допускать перезаписи в нем, поскольку это приведет к потере еще не считанных данных аудита безопасности. Для контроля перезаписи в журнале через параметр
outDropMsgs
функцииKnAuRead()
передается число потерянных сообщений. (Счетчик этих сообщений обнуляется после считывания его значения при каждом вызове функции.) При наличии потерянных сообщений нужно либо увеличить скорость считывания сообщений из журнала, например, выполняя считывание из параллельных потоков исполнения, либо снизить скорость генерации сообщений, изменив профиль аудита безопасности. - Закрытие журнала ядра с данными аудита безопасности вызовом функции
KnAuClose()
.
Сведения о функциях API
Функции vlog_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Открывает журнал ядра с данными аудита безопасности. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Закрывает журнал ядра с данными аудита безопасности. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сообщение из журнала ядра с данными аудита безопасности. Параметры
Возвращаемые значения В случае успеха возвращает |
Использование фьютексов (sync.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/sync/sync.h
из состава KasperskyOS SDK.
API предназначен для работы с фьютексами и используется в коде функций API event.h, mutex.h, rwlock.h, semaphore.h, condvar.h. Фьютекс – низкоуровневый примитив синхронизации, для которого поддерживается две операции: блокировка потока исполнения с его добавлением в связанную с фьютексом очередь заблокированных потоков исполнения и возобновление исполнения потоков из связанной с фьютексом очереди заблокированных потоков исполнения. Фьютекс представляет собой объект ядра связанный с целочисленной переменной в пользовательском пространстве. Объект ядра обеспечивает возможность хранить очередь заблокированных потоков исполнения, связанную с фьютексом. Значение целочисленной переменной в пользовательском пространстве (значение фьютекса) атомарно изменяется синхронизируемыми потоками исполнения, чтобы сигнализировать об изменении состояния разделяемых ресурсов. Например, значение фьютекса может отражать, в каком состоянии находится событие (сигнальном или несигнальном), захвачен или освобожден мьютекс, какое значение имеет счетчик семафора. От значения фьютекса зависит, будет ли заблокирован поток исполнения, который пытается получить доступ к разделяемым ресурсам.
Сведения о функциях API приведены в таблице ниже.
Использование API
Чтобы использовать фьютекс, нужно создать только целочисленную переменную для хранения его значения. Функции API принимают указатель на эту переменную через параметр ftx
. Создание и удаление объекта ядра, связанного с этой переменной, выполняется автоматически при использовании функций API.
Функция KnFutexWait()
блокирует вызывающий поток исполнения, если значение фьютекса совпадает со значением параметра val
. (Значение фьютекса может быть изменено другим потоком исполнения во время выполнения функции.) Поток исполнения блокируется на время mdelay
, но исполнение этого потока может быть возобновлено до истечения времени mdelay
вызовом функции KnFutexWake()
из другого потока исполнения. Функция KnFutexWake()
возобновляет исполнение потоков из связанной с фьютексом очереди заблокированных потоков исполнения. Число потоков, исполнение которых возобновляется, ограничено значением параметра nThreads
. Возобновление исполнения потоков начинается с начала очереди.
Сведения о функциях API
Функции sync.h
Функция |
Сведения о функции |
---|---|
|
Назначение Блокирует вызывающий поток исполнения, если значение фьютекса равно ожидаемому. Параметры
Возвращаемые значения В случае успеха возвращает Если время блокировки потока исполнения истекло, возвращает Если значение фьютекса не равно ожидаемому, возвращает |
|
Назначение Возобновляет исполнение потоков, заблокированных вызовами функции Параметры
Возвращаемые значения В случае успеха возвращает |
Получение IPC-дескрипторов и идентификаторов служб для использования статически созданных IPC-каналов (sl_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/sl/sl_api.h
из состава KasperskyOS SDK.
API позволяет серверам получать слушающие дескрипторы, а клиентам получать клиентские IPC-дескрипторы и идентификаторы служб (RIIDs) для использования статически созданных IPC-каналов.
Закрытие полученного IPC-дескриптора приведет к недоступности IPC-канала. Если IPC-дескриптор был закрыт, то получить его повторно и восстановить доступ к IPC-каналу невозможно.
Сведения о функциях API приведены в таблице ниже.
Функции sl_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Позволяет получить слушающий дескриптор по имени IPC-канала. Параметры
Возвращаемые значения В случае успеха возвращает слушающий дескриптор, иначе возвращает |
|
Назначение Позволяет получить клиентский IPC-дескриптор по имени IPC-канала. Параметры
Возвращаемые значения В случае успеха возвращает клиентский IPC-дескриптор, иначе возвращает |
|
Назначение Позволяет получить идентификатор службы (RIID). Параметры
Возвращаемые значения В случае успеха возвращает идентификатор службы (RIID), иначе возвращает |
Управление электропитанием (pm_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/pm/pm_api.h
из состава KasperskyOS SDK.
API позволяет изменять режим электропитания аппаратной платформы (например, выключать, перезагружать), а также включать и выключать процессоры (вычислительные ядра).
Сведения о функциях API приведены в таблице ниже.
Использование API
Чтобы выполнить запрос на изменение режима электропитания аппаратной платформы, нужно вызвать функцию KnPmRequest()
.
Функции KnPmSetCpusOnline()
и KnPmGetCpusOnline()
имеют параметр mask
, через который передается маска процессов. Маска процессоров – битовая маска, отражающая набор процессоров (вычислительных ядер). Флаг, установленный в i-ом бите, отражает, что процессор с индексом i входит в набор (нумерация начинается с нуля). Для работы с маской процессоров нужно использовать функции, определенные в заголовочном файле sysroot-*-kos/include/rtl/cpuset.h
.
Чтобы включить и/или выключить процессоры, нужно вызвать функцию KnPmSetCpusOnline()
, указав маску процессоров, отражающую требуемый набор активных процессоров. В этой маске должен быть установлен флаг, соответствующий процессору загрузки (англ. bootstrap processor), иначе функция завершится с ошибкой. Чтобы получить индекс процессора загрузки, нужно вызвать функцию KnPmGetBootstrapCpuNum()
.
Чтобы получить сведения о том, какие процессоры находятся в активном состоянии, нужно вызвать функцию KnPmGetCpusOnline()
. Выходным параметром этой функции является маска процессоров, отражающая фактический набор активных процессоров.
Если функция KnPmSetCpusOnline()
завершилась с ошибкой, это может привести к неопределенному изменению набора активных процессоров. Чтобы предпринять повторную попытку настроить набор активных процессоров, нужно получить сведения о том, какие процессоры находятся в активном состоянии, вызовом функции KnPmGetCpusOnline()
и скорректировать на основе этих сведений требуемый набор активных процессоров при последующем вызове функции KnPmSetCpusOnline()
.
Сведения о функциях API
Функции pm_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Выполняет запрос на изменение режима электропитания аппаратной платформы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет запрос на включение и/или выключение процессоров. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о том, какие процессоры находятся в активном состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить индекс процессора загрузки. Параметры
Возвращаемые значения В случае успеха возвращает |
Ограничения поддержки POSIX
В KasperskyOS ограниченно реализован POSIX с ориентацией на стандарт POSIX.1-2008. Прежде всего ограничения связаны с обеспечением безопасности.
Отсутствует поддержка XSI и опциональной функциональности.
Ограничения затрагивают:
- взаимодействие между процессами;
- взаимодействие между потоками исполнения посредством сигналов;
- асинхронный ввод-вывод;
- использование робастных мьютексов;
- работу с терминалом;
- работу с оболочкой;
- управление дескрипторами файлов;
- использование таймеров;
- получение системных параметров.
Ограничения представлены:
- нереализованными интерфейсами;
- интерфейсами, которые реализованы с отклонениями от стандарта POSIX.1-2008;
- интерфейсами-заглушками, которые не выполняют никаких действий, кроме присвоения переменной
errno
значенияENOSYS
и возвращения значения-1
.
В KasperskyOS сигналы не могут прервать системные вызовы Call()
, Recv()
, Reply()
, которые обеспечивают работу библиотек, реализующих интерфейс POSIX.
Ядро KasperskyOS не посылает сигналы.
На аппаратных платформах с процессорной архитектурой Arm входные и выходные параметры интерфейсов POSIX нельзя сохранять в памяти типа "Device memory", поскольку это может привести к неопределенному поведению. Параметры интерфейсов POSIX нужно сохранять в памяти типа "Normal memory". Чтобы копировать данные из памяти типа "Device memory" в память типа "Normal memory" и обратно, нужно использовать функцию RtlPedanticMemcpy()
, объявленную в заголовочном файле sysroot-*-kos/include/rtl/string_pedantic.h
из состава KasperskyOS SDK.
Ограничения взаимодействия между процессами
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Создать новый (дочерний) процесс. |
Не реализован. |
|
|
Зарегистрировать обработчики, которые вызываются перед и после создания дочернего процесса. |
Не реализован. |
|
|
Ожидать остановки или завершения дочернего процесса. |
Заглушка. |
|
|
Ожидать изменения состояния дочернего процесса. |
Не реализован. |
|
|
Ожидать остановки или завершения дочернего процесса. |
Заглушка. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Запустить исполняемый файл. |
Не реализован. |
|
|
Перевести процесс в другую группу или создать группу. |
Заглушка. |
|
|
Создать сессию. |
Заглушка. |
|
|
Получить идентификатор группы вызывающего процесса. |
Заглушка. |
|
|
Получить идентификатор группы. |
Заглушка. |
|
|
Получить идентификатор родительского процесса. |
Заглушка. |
|
|
Получить идентификатор сессии. |
Заглушка. |
|
|
Получить значения времени для процесса и его потомков. |
Заглушка. |
|
|
Послать сигнал процессу или группе процессов. |
Можно посылать только сигнал |
|
|
Ожидать сигнала. |
Заглушка. |
|
|
Проверить наличие полученных заблокированных сигналов. |
Не реализован. |
|
|
Послать сигнал процессу. |
Не реализован. |
|
|
Ожидать сигнала из заданного набора сигналов. |
Не реализован. |
|
|
Ожидать сигнала из заданного набора сигналов. |
Не реализован. |
|
|
Создать неименованный семафор. |
Нельзя создать неименованный семафор для синхронизации между процессами. Если передать ненулевое значение через параметр |
|
|
Создать/открыть именованный семафор. |
Нельзя открыть именованный семафор, который был создан другим процессом. Именованные семафоры (как и неименованные) являются локальными, то есть они доступны только тому процессу, который их создал. |
|
|
Создать спин-блокировку. |
Нельзя создать спин-блокировку для синхронизации между процессами. Если передать значение |
|
|
Отобразить в память. |
Нельзя выполнить отображение в память для взаимодействия между процессами. Если передать значения |
|
|
Задать права доступа к памяти. |
Для целей безопасности некоторые конфигурации ядра KasperskyOS запрещают предоставлять доступ к регионам виртуальной памяти на запись и исполнение одновременно. Если при использовании такой конфигурации ядра через параметр |
|
|
Создать неименованный канал. |
Нельзя использовать неименованный канал для передачи данных между процессами. Неименованные каналы являются локальными, то есть они доступны только тому процессу, который их создал. |
|
|
Создать специальный файл FIFO (именованный канал). |
Заглушка. |
|
|
Создать специальный файл FIFO (именованный канал). |
Не реализован. |
|
Ограничения взаимодействия между потоками исполнения посредством сигналов
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Послать сигнал потоку исполнения. |
Нельзя послать сигнал потоку исполнения. Если передать номер сигнала через параметр |
|
|
Восстановить состояние потока управления и маску сигналов. |
Не реализован. |
|
|
Сохранить состояние потока управления и маску сигналов. |
Не реализован. |
|
Ограничения асинхронного ввода-вывода
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Отменить запросы ввода-вывода, которые ожидают обработки. |
Не реализован. |
|
|
Получить ошибку операции асинхронного ввода-вывода. |
Не реализован. |
|
|
Запросить выполнение операций ввода-вывода. |
Не реализован. |
|
|
Запросить чтение из файла. |
Не реализован. |
|
|
Получить статус операции асинхронного ввода-вывода. |
Не реализован. |
|
|
Ожидать завершения операций асинхронного ввода-вывода. |
Не реализован. |
|
|
Запросить запись в файл. |
Не реализован. |
|
|
Запросить выполнение набора операций ввода-вывода. |
Не реализован. |
|
Ограничения использования робастных мьютексов
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Вернуть робастный мьютекс в консистентное состояние. |
Не реализован. |
|
|
Получить атрибут робастности мьютекса. |
Не реализован. |
|
|
Задать атрибут робастности мьютекса. |
Не реализован. |
|
Ограничения работы с терминалом
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Получить путь к файлу управляющего терминала. |
Только возвращает или передает через параметр |
|
|
Задать параметры терминала. |
Скорость ввода, скорость вывода и другие параметры, специфичные для аппаратных терминалов, игнорируются. |
|
|
Ожидать завершения вывода. |
Только возвращает значение |
|
|
Приостановить или возобновить прием или передачу данных. |
Приостановка вывода и запуск приостановленного вывода не поддерживаются. |
|
|
Очистить очередь ввода или очередь вывода, или обе эти очереди. |
Только возвращает значение |
|
|
Разорвать соединение с терминалом на заданное время. |
Только возвращает значение |
|
|
Получить путь к файлу терминала. |
Только возвращает нулевой указатель. |
|
|
Получить путь к файлу терминала. |
Только возвращает значение ошибки. |
|
|
Получить идентификатор группы процессов, использующих терминал. |
Только возвращает значение |
|
|
Задать идентификатор группы процессов, использующих терминал. |
Только возвращает значение |
|
|
Получить идентификатор группы процессов для лидера сессии, связанной с терминалом. |
Только возвращает значение |
|
Ограничения работы с оболочкой
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Создать дочерний процесс для выполнения команды и неименованный канал с этим процессом. |
Не реализован. |
|
|
Закрыть неименованный канал с дочерним процессом, созданным |
Не реализован. |
|
|
Создать дочерний процесс для выполнения команды. |
Заглушка. |
|
|
Раскрыть строку как в оболочке. |
Не реализован. |
|
|
Освободить память, выделенную для результатов вызова |
Не реализован. |
|
Ограничения управления дескрипторами файлов
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Сделать копию дескриптора открытого файла. |
Поддерживаются дескрипторы обычных файлов, стандартных потоков ввода-вывода, сокетов и каналов. Не гарантируется, что будет получен наименьший свободный дескриптор. |
|
|
Сделать копию дескриптора открытого файла. |
Поддерживаются дескрипторы обычных файлов, стандартных потоков ввода-вывода, сокетов и каналов. Через параметр |
|
Ограничения использования таймеров
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Получить значение времени. |
Если передать значение |
|
|
Получить процессорное время, затраченное на исполнение вызывающего процесса. |
Возвращает время с момента запуска ядра KasperskyOS в миллисекундах. |
|
Получение системных параметров
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Получить системный параметр. |
Заглушка. |
|
Особенности реализации POSIX
В KasperskyOS реализация некоторых интерфейсов POSIX в части, которая не определяется стандартом POSIX.1-2008, отличается от реализации этих интерфейсов в Linux и других UNIX-подобных операционных системах. Сведения об этих интерфейсах приведены в таблице ниже.
Интерфейсы POSIX с особенностями реализации
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту POSIX.1-2008 |
---|---|---|---|
|
Назначить имя сокету. |
При использовании версии VFS, которая поддерживает только сетевые операции, файлы сокетов семейства |
|
|
Отобразить в память. |
Флаг На аппаратных платформах с процессорной архитектурой AArch64 (Arm64) нельзя выполнить отображение более 4 ГБ. |
|
|
Выполнить чтение из файла. |
Если размер буфера |
|
Совместное использование POSIX и API libkos
В потоке исполнения, созданном с помощью Pthreads, нельзя использовать следующие API libkos
:
- event.h, mutex.h, rwlock.h, semaphore.h, condvar.h;
- thread.h, thread_api.h;
- dma.h;
- ports.h;
- mmio.h;
- irq.h.
Следующие API libkos
можно использовать совместно с Pthreads (и другими API POSIX):
Интерфейсы POSIX нельзя использовать в потоках исполнения, созданных с помощью API thread.h и thread_api.h.
API syscalls.h можно использовать в любых потоках исполнения, созданных с использованием Pthreads или API thread.h и thread_api.h.
В началоПолучение статистических сведений о системе через API библиотеки libc
Библиотека libc
предоставляет API, которые позволяют получить статистические сведения о файловых системах и сетевых интерфейсах, управляемых VFS. Функции этих API приведены в таблице ниже.
Сведения о файловых системах и сетевых интерфейсах
Функция |
Заголовочный файл из состава KasperskyOS SDK |
Получаемые сведения |
---|---|---|
|
|
Сведения о файловой системе, такие как размер блока, число блоков, число свободных блоков |
|
|
Сведения обо всех смонтированных файловых системах, идентичные предоставляемым функцией |
|
|
Сведения о сетевых интерфейсах, такие как имя, IP-адрес, маска подсети |
Динамическое создание IPC-каналов с использованием системной программы DCM
В составе KasperskyOS SDK поставляется системная программа DCM
(Dynamic Connection Manager), которая позволяет динамически создавать IPC-каналы. Благодаря этой программе серверы могут сообщать клиентам о предоставляемых службах, а также передавать callable-дескрипторы для использования этих служб.
Для использования программы DCM
в составе KasperskyOS SDK поставляются следующие файлы:
sysroot-*-kos/include/dcm/dcm_api.h
– заголовочный файл, в котором определен базовый API.sysroot-*-kos/include/dcm/groups/pub.h
– заголовочный файл, в котором определен дополнительный API для серверов.sysroot-*-kos/include/dcm/groups/subscr.h
– заголовочный файл, в котором определен дополнительный API для клиентов.sysroot-*-kos/include/dcm/dcm.h
– заголовочный файл для включения в исходный код клиентов и серверов.sysroot-*-kos/bin/dcm
– исполняемый файл.sysroot-*-kos/lib/libdcm.a
– клиентская библиотека.sysroot-*-kos/lib/libdcm_s.a
– клиентская библиотека, собранная с флагом-fPIC
для обеспечения возможности компоновки с динамической библиотекой.sysroot-*-kos/include/kl/core/DCM.*dl
– файлы формальной спецификации.
IPC-каналы от клиентов и серверов к DCM
нужно создать статически.
Можно запустить несколько процессов программы DCM
. При этом каждый клиент и сервер может быть соединен только с одним процессом программы DCM
.
В API программы DCM
используются идентификаторы, которые называются DCM-дескрипторами (англ. DCM handles). DCM-дескрипторы идентифицируют объекты, которые дают клиентам и серверам, использующим DCM
, следующие возможности:
- Клиенты могут получать уведомления о публикации и отмене публикации служб, а также выполнять запросы на создание IPC-каналов с серверами.
- Серверы могут получать запросы клиентов на создание IPC-каналов, а также принимать или отклонять эти запросы.
Имена служб и интерфейсов служб нужно задавать в соответствии с формальными спецификациями компонентов решения. (О квалифицированном имени службы см. "Привязка методов моделей безопасности к событиям безопасности".) Вместо квалифицированного имени службы можно использовать какое-либо условное название этой службы. Имена клиентов и серверов задаются в init-описании.
Использование базового API (dcm_api.h)
Сведения о функциях API приведены в таблице ниже.
Динамическое создание IPC-канала на стороне сервера
Динамическое создание IPC-канала на стороне сервера включает следующие шаги:
- Создать подключение к
DCM
вызовом функцииDcmInit()
. - Опубликовать предоставляемые службы в
DCM
, используя функциюDcmPublishEndpoint()
.В параметре
serverHandle
функцииDcmPublishEndpoint()
нужно указать дескриптор, идентифицирующий сервер. В качестве дескриптора, идентифицирующего сервер, можно использовать дескриптор этого серверного процесса, полученный последовательностью вызовов функцийKosTaskGetSelf()
иKosTaskGetHandle()
из API task.h, или дескриптор, созданный вызовом функцииKnHandleCreateUserObject()
из API handle_api.h. (При вызове функцииKnHandleCreateUserObject()
в параметреrights
должны быть указаны флагиOCAP_HANDLE_TRANSFER
иOCAP_HANDLE_GET_SID
.) Можно опубликовать несколько служб, указывая один и тот же или разные дескрипторы, идентифицирующие сервер. (Клиенты могут получить потомков этих дескрипторов через опциональный параметрoutServerHandle
функцииDcmReadPubQueue()
.) После публикации служб дескриптор, идентифицирующий сервер, можно закрыть.В результате вызова функции
DcmPublishEndpoint()
создается DCM-дескриптор, позволяющий получать запросы клиентов на создание IPC-каналов для использования заданной службы с заданным интерфейсом.Чтобы отменить публикацию службы, нужно вызовом функции
DcmCloseHandle()
закрыть DCM-дескриптор, созданный при ее публикации. Также публикация всех опубликованных служб сервера будет отменена, если сервер завершится. - Получить запрос клиента на создание IPC-канала вызовом функции
DcmListen()
.Вызовы функции
DcmListen()
с одним и тем же DCM-дескриптором в параметреpubHandle
позволяют получить только те запросы клиентов, которые направлены на создание IPC-каналов для использования той службы с тем интерфейсом, которые были заданы при создании этого DCM-дескриптора на шаге 2.Через опциональные параметры
outClientHandle
иoutClientName
функцииDcmListen()
можно получить дескриптор, идентифицирующий клиента, и имя клиента соответственно. (Дескриптор, идентифицирующий клиента, является потомком дескриптора, указанного в параметреclientHandle
функцииDcmCreateConnection()
, вызванной на стороне клиента.) Эти данные можно использовать, чтобы принять решение о принятии или отклонении запроса клиента. При этом дескриптор, идентифицирующий клиента, может быть использован, например, для получения сведений о клиенте от других процессов или для получения SID по этому дескриптору для сравнения с другими имеющимся у сервера дескрипторами, идентифицирующими клиентов. После принятия решения можно закрыть дескриптор, идентифицирующий клиента.В результате вызова функции
DcmListen()
создается DCM-дескриптор, позволяющий принять или отклонить запрос клиента на создание IPC-канала. - Принять запрос клиента на создание IPC-канала вызовом функции
DcmAccept()
.В параметре
connectionId
функцииDcmAccept()
нужно указать DCM-дескриптор, полученный на шаге 3.В параметре
sessionHandle
функцииDcmAccept()
нужно указать callable-дескриптор для передачи клиенту. Чтобы создать callable-дескриптор, нужно вызвать функциюKnHandleCreateUserObjectEx()
из API handle_api.h. (При вызове функцииKnHandleCreateUserObjectEx()
в параметреrights
должны быть указаны флагиOCAP_IPC_CALL
иOCAP_HANDLE_TRANSFER
, а в параметрахipcChannel
иriid
требуется указать серверный IPC-дескриптор создаваемого IPC-канала и идентификатор службы (RIID) соответственно. Серверный IPC-дескриптор используется для инициализации IPC-транспорта и управления обработкой IPC-запросов на стороне сервера. Для создания серверного дескриптора можно использовать функциюKnHandleCreateListener()
из API handle_api.h. Идентификатор службы является константой в автоматически генерируемом транспортном коде, например,FsDriver_operationsComp_fileOperations_iid
.) После принятия запроса клиента callable-дескриптор можно закрыть.Передачу callable-дескриптора клиенту можно ассоциировать с объектом контекста передачи ресурса, указав дескриптор этого объекта в параметре
badgeHandle
функцииDcmAccept()
. Это позволит, используя API notice_api.h, отследить, когда будут закрыты или отозваны потомки callable-дескриптора, которые образуют поддерево наследования дескрипторов, корневой узел которого порожден передачей клиенту этого callable-дескриптора. (Переданный callable-дескриптор может быть закрыт клиентом, но также закрытие этого дескриптора выполняется в результате завершения клиента.) Чтобы создать объект контекста передачи ресурса, нужно вызвать функциюKnHandleCreateBadge()
из API handle_api.h.Через параметр
context
функцийKnHandleCreateUserObjectEx()
иKnHandleCreateBadge()
можно задать данные для ассоциации с callable-дескриптором и передачей callable-дескриптора соответственно (аналогично контексту пользовательского ресурса и контексту передачи ресурса). Сервер сможет получить указатель на эти данные при разыменовании callable-дескриптора. (Несмотря на то что callable-дескриптор является IPC-дескриптором, он помещается ядром в полеbase_.self
фиксированной части IPC-запроса.)Один и тот же callable-дескриптор можно использовать, чтобы принять несколько запросов одного или нескольких клиентов.
Чтобы отклонить запрос клиента на создание IPC-канала, нужно вызовом функции
DcmCloseHandle()
закрыть DCM-дескриптор, полученный на шаге 3. (При этом вызов функцииDcmConnect()
на стороне клиента завершится с ошибкойrcNotConnected
.) В случае принятия запроса клиента DCM-дескриптор, полученный на шаге 3, нужно также закрыть, но после вызова функцииDcmAccept()
.
Динамическое создание IPC-канала на стороне клиента
Динамическое создание IPC-канала на стороне клиента включает следующие шаги:
- Создать подключение к
DCM
вызовом функцииDcmInit()
. - Создать DCM-дескриптор, позволяющий получать уведомления о публикации и отмене публикации служб с заданным интерфейсом.
Чтобы выполнить этот шаг, нужно вызвать функцию
DcmSetSubscription()
.Опциональные параметры
endpointName
,serverName
иserverHandle
функцииDcmSetSubscription()
нужно использовать, чтобы включить фильтрацию уведомлений по квалифицированному имени службы, имени сервера и дескриптору, идентифицирующему сервер, соответственно. (Дескриптор, идентифицирующий сервер, является потомком дескриптора, указанного в параметреserverHandle
функцииDcmPublishEndpoint()
, вызванной на стороне сервера. Клиент может получить этот дескриптор, например, от другого процесса.)В результате вызова функции
DcmSetSubscription()
создается DCM-дескриптор, позволяющий получать уведомления о публикации и отмене публикации служб с заданным интерфейсом. При этом формируется очередь уведомлений о публикации служб, которые были опубликованы до вызоваDcmSetSubscription()
и соответствуют критериям фильтрации. Если больше не требуется получать уведомления о публикации и отмене публикации служб с заданным интерфейсом, то этот DCM-дескриптор нужно закрыть вызовом функцииDcmCloseHandle()
. - Извлечь уведомление о публикации службы из очереди этих уведомлений вызовом функции
DcmReadPubQueue()
.В параметре
subscrHandle
функцииDcmReadPubQueue()
нужно указать DCM-дескриптор, полученный на шаге 2.Через опциональные параметры
outServerHandle
,outServerName
иoutEndpointName
функцииDcmReadPubQueue()
можно получить дескриптор, идентифицирующий сервер, имя сервера и квалифицированное имя службы соответственно. (Дескриптор, идентифицирующий сервер, является потомком дескриптора, указанного в параметреserverHandle
функцииDcmPublishEndpoint()
, вызванной на стороне сервера.) Эти данные можно использовать, чтобы принять решение о выполнении запроса на создание IPC-канала с сервером. При этом дескриптор, идентифицирующий сервер, может быть использован, например, для получения сведений о сервере от других процессов или для получения SID по этому дескриптору для сравнения с другими имеющимися у клиента дескрипторами, идентифицирующими серверы.Значение, полученное через параметр
outPubStatus
функцииDcmReadPubQueue()
, отражает, что служба опубликована, или публикация службы отменена. Уведомление об отмене публикации службы появляется, если сервер отменил публикацию этой службы, а также при завершении сервера. - Создать DCM-дескриптор, позволяющий выполнить запрос на создание IPC-канала с сервером.
Чтобы выполнить этот шаг, нужно вызвать функцию
DcmCreateConnection()
.В параметре
serverHandle
функцииDcmCreateConnection()
нужно указать дескриптор, идентифицирующий сервер. Этот дескриптор может быть получен на шаге 3 через параметрoutServerHandle
функцииDcmReadPubQueue()
или другим способом (например, от другого процесса).В параметре
clientHandle
функцииDcmCreateConnection()
нужно указать дескриптор, идентифицирующий клиента. В качестве дескриптора, идентифицирующего клиента, можно использовать дескриптор этого клиентского процесса, полученный последовательностью вызовов функцийKosTaskGetSelf()
иKosTaskGetHandle()
из API task.h, или дескриптор, созданный вызовом функцииKnHandleCreateUserObject()
из API handle_api.h. (При вызове функцииKnHandleCreateUserObject()
в параметреrights
должны быть указаны флагиOCAP_HANDLE_TRANSFER
иOCAP_HANDLE_GET_SID
.) Можно создать несколько DCM-дескрипторов, позволяющих выполнить запрос на создание IPC-канала, указывая в параметреclientHandle
функцииDcmCreateConnection()
один и тот же или разные дескрипторы, идентифицирующие клиента. (Серверы могут получить потомков этих дескрипторов через опциональный параметрoutClientHandle
функцииDcmListen()
.) После создания DCM-дескриптора, позволяющего выполнить запрос на создание IPC-канала, дескриптор, идентифицирующий клиента, можно закрыть.В результате вызова функции
DcmCreateConnection()
создается DCM-дескриптор, позволяющий выполнить запрос на создание IPC-канала с сервером для использования заданной службы с заданным интерфейсом. - Выполнить запрос на создание IPC-канала с сервером вызовом функции
DcmConnect()
.В параметре
connectionId
нужно указать DCM-дескриптор, полученный на шаге 4.В результате вызова функции
DcmConnect()
клиент получает через параметрoutSessionHandle
callable-дескриптор. Клиент использует этот дескриптор для инициализации IPC-транспорта. При этом в функции инициализации прокси-объекта клиент указывает значениеINVALID_RIID
в качестве идентификатор службы (RIID).После получения callable-дескриптора DCM-дескриптор, полученный на шаге 4, нужно закрыть вызовом функции
DcmCloseHandle()
.
Прерывание блокирующих вызовов функций
Чтобы прервать блокирующий вызов функции DcmConnect()
, DcmReadPubQueue()
или DcmListen()
из другого потока исполнения, нужно вызвать функцию DcmInterruptBlockingCall()
.
Использование уведомлений
Используя функции DcmSubscribeToEvents()
и DcmUnsubscribeFromEvents()
совместно с функциями из API notice_api.h, можно получать уведомления о том, что произошли следующие события: публикация или отмена публикации сервером службы в DCM
(флаг DCM_PUBLICATION_CHANGED
), получение сервером запроса от клиента на создание IPC-канала (флаг DCM_CLIENT_CONNECTED
), прерывание блокирующего вызова функции DcmConnect()
, DcmReadPubQueue()
или DcmListen()
(флаг DCM_BLOCKING_CALL_INTERRUPTED
), прием или отклонение сервером запроса клиента на создание IPC-канала (флаг DCM_CLIENT_RELEASED_BY_SERVER
). (Флаги маски событий и идентификатор записи вида "ресурс – маска событий" DCM_EVENT_ID
определены в заголовочном файле sysroot-*-kos/include/dcm/dcm_api.h
из состава KasperskyOS SDK.) Функции DcmSubscribeToEvents()
и DcmUnsubscribeFromEvents()
позволяют настроить приемник уведомлений, соответственно добавляя и удаляя отслеживаемые объекты, идентифицируемые DCM-дескрипторами.
Удаление динамически созданных IPC-каналов
Динамически созданный IPC-канал будет удален при закрытии callable-дескриптора и серверного IPC-дескриптора этого IPC-канала.
Удаление подключения к DCM
Если использовать DCM
больше не требуется, нужно вызвать функцию DcmFini()
, чтобы удалить подключение к DCM
и тем самым освободить связанные с этим подключением ресурсы.
Сведения о функциях API
Функции dcm_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает подключение к Параметры Нет. Возвращаемые значения В случае успеха возвращает Если IPC-канал до Дополнительные сведения Потокобезопасная функция. Неблокирующий вызов. |
|
Назначение Удаляет подключение к Параметры Нет. Возвращаемые значения Нет. Дополнительные сведения Потокобезопасная функция. Неблокирующий вызов. |
|
Назначение Настраивает приемник уведомлений, чтобы он получал уведомления о событиях, связанных с объектом, идентифицируемым заданным DCM-дескриптором. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Настраивает приемник уведомлений, чтобы он не получал уведомления о событиях, связанных с объектом, идентифицируемым заданным DCM-дескриптором. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Закрывает DCM-дескриптор, полученный вызовом функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Прерывает блокирующий вызов функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает DCM-дескриптор, позволяющий получать уведомления о публикации и отмене публикации служб с заданным интерфейсом. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Извлекает уведомление о публикации или отмене публикации службы из очереди этих уведомлений. Параметры
Возвращаемые значения В случае успеха возвращает Если блокирующий вызов был прерван вызовом функции Дополнительные сведения Неблокирующий вызов, если в параметре |
|
Назначение Создает DCM-дескриптор, позволяющий выполнить запрос на создание IPC-канала с сервером для использования заданной службы с заданным интерфейсом. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Выполняет запрос на создание IPC-канала с сервером. Параметры
Возвращаемые значения В случае успеха возвращает Если в параметре Если блокирующий вызов был прерван вызовом функции Дополнительные сведения Неблокирующий вызов, если в параметре |
|
Назначение Публикует службу в Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить запрос клиента на создание IPC-канала. Параметры
Возвращаемые значения В случае успеха возвращает Если блокирующий вызов был прерван вызовом функции Дополнительные сведения Неблокирующий вызов, если в параметре |
|
Назначение Принимает запрос клиента на создание IPC-канала. Параметры
Возвращаемые значения В случае успеха возвращает |
Использование дополнительного API для серверов (pub.h)
API позволяет серверам публиковать группы служб. С позиции сервера группа служб представляет собой набор предоставляемых этим сервером служб, для которых можно получать клиентские запросы на создание IPC-каналов, используя один DCM-дескриптор. Сервер может опубликовать несколько групп служб. Множества служб из разных групп, опубликованных сервером, не должны пересекаться.
Сведения о функциях API приведены в таблице ниже.
Чтобы опубликовать группу предоставляемых сервером служб в DCM
, нужно вызвать функцию DcmPublishGroupEndpoints()
. Через параметр endpoints
функции DcmPublishGroupEndpoints()
нужно задать квалифицированные имена и контексты группируемых служб, а также имена интерфейсов служб. (Массив структур, указатель на который задан через параметр endpoints
, можно удалить после публикации.) Контекст службы представляет собой данные, которые используются сервером, чтобы при вызове функции DcmListenGroupPub()
определить, какая именно служба из опубликованной группы требуется клиенту. В качестве контекста службы можно использовать числовой идентификатор либо указатель на какие-либо данные. В результате вызова функции DcmPublishGroupEndpoints()
создается DCM-дескриптор, позволяющий получать запросы клиентов на создание IPC-каналов для использования служб из заданной группы с заданными интерфейсами.
Чтобы получить запрос клиента на создание IPC-канала для использования службы из опубликованной группы, нужно вызвать функцию DcmListenGroupPub()
. В параметре pubHandle
функции DcmListenGroupPub()
нужно указать DCM-дескриптор, полученный вызовом функции DcmPublishGroupEndpoints()
. Выходной параметр outContext
функции DcmListenGroupPub()
содержит указатель на контекст службы. В результате вызова функции DcmListenGroupPub()
создается DCM-дескриптор, позволяющий принять или отклонить запрос клиента на создание IPC-канала для использования той службы группы, которой соответствует полученный контекст службы.
Чтобы отменить публикацию группы служб, нужно вызовом функции DcmCloseGroupPubHandle()
закрыть DCM-дескриптор, созданный при ее публикации. Также публикация всех опубликованных групп служб сервера будет отменена, если сервер завершится.
Чтобы прервать блокирующий вызов функции DcmListenGroupPub()
из другого потока исполнения, нужно вызвать функцию DcmInterruptGroupPubBlockingCall()
.
Используя функции DcmSubscribeToGroupPubEvent()
и DcmUnsubscribeFromGroupPubEvent()
совместно с функциями из API notice_api.h, можно получать уведомления о том, что произошли следующие события: получение сервером запроса от клиента на создание IPC-канала (флаг DCM_CLIENT_CONNECTED
), прерывание блокирующего вызова функции DcmListenGroupPub()
(флаг DCM_BLOCKING_CALL_INTERRUPTED
). (Флаги маски событий и идентификатор записи вида "ресурс – маска событий" DCM_EVENT_ID
определены в заголовочном файле sysroot-*-kos/include/dcm/dcm_api.h
из состава KasperskyOS SDK.) Функции DcmSubscribeToGroupPubEvent()
и DcmUnsubscribeFromGroupPubEvent()
позволяют настроить приемник уведомлений, соответственно добавляя и удаляя отслеживаемые объекты, идентифицируемые DCM-дескрипторами.
Функции pub.h
Функция |
Сведения о функции |
---|---|
|
Назначение Публикует группу служб в Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить запрос клиента на создание IPC-канала. Параметры
Возвращаемые значения В случае успеха возвращает Если блокирующий вызов был прерван вызовом функции Дополнительные сведения Неблокирующий вызов, если в параметре |
|
Назначение Прерывает блокирующий вызов функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Закрывает DCM-дескриптор, полученный вызовом функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Настраивает приемник уведомлений, чтобы он получал уведомления о событиях, связанных с объектом, идентифицируемым заданным DCM-дескриптором. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Настраивает приемник уведомлений, чтобы он не получал уведомления о событиях, связанных с объектом, идентифицируемым заданным DCM-дескриптором. Параметры
Возвращаемые значения В случае успеха возвращает |
Использование дополнительного API для клиентов (subscr.h)
API позволяет клиентам получать уведомления о публикации и отмене публикации групп служб. С позиции клиента группа служб представляет собой набор служб одного сервера, уведомления о публикации и отмене публикации которых можно получать, используя один DCM-дескриптор. При этом действует ограничение о том, что сервер не может предоставлять несколько служб с одинаковым интерфейсом. Несколько серверов могут предоставлять одинаковые группы служб, требуемые клиенту. Сервер может предоставлять несколько групп служб, требуемых клиенту. Множества служб из разных групп, требуемых клиенту, могут пересекаться.
Сведения о функциях API приведены в таблице ниже.
Чтобы создать DCM-дескриптор, позволяющий получать уведомления о публикации и отмене публикации групп служб с заданными интерфейсами, нужно вызвать функцию DcmSetGroupSubscription()
. Через параметр endpointTypes
нужно задать имена интерфейсов группируемых служб. В параметре endpointsCount
нужно указать число группируемых служб, равное числу интерфейсов, заданных через параметр endpointTypes
. (Уведомления будут содержать сведения о том числе служб, которое равно числу интерфейсов, так как действует ограничение, что каждому интерфейсу соответствует отдельная и единственная служба.)
Чтобы извлечь уведомление о публикации или отмене публикации группы служб из очереди этих уведомлений, нужно вызвать функцию DcmReadGroupPubQueue()
. В параметре subscrHandle
функции DcmReadGroupPubQueue()
нужно указать DCM-дескриптор, полученный вызовом функции DcmSetGroupSubscription()
. В параметре maxCount
функции DcmReadGroupPubQueue()
нужно указать число элементов в массиве, заданном через параметр outEndpoints
. Значение этого параметра должно быть не меньше числа служб в группе. Значение, полученное через параметр outPubStatus
функции DcmReadGroupPubQueue()
, отражает, что группа служб опубликована, или публикация группы служб отменена. Уведомление о публикации группы служб появляется в очереди только в том случае, если сервер публикует все службы группы (сразу или по отдельности). Если сервер публикует только часть требуемых клиенту служб, то уведомление о публикации группы служб не появляется. Если сервер завершается или отменяет публикацию хотя бы одной службы из опубликованной группы служб, то клиент получает уведомление об отмене публикации этой группы служб.
Если больше не требуется получать уведомления о публикации и отмене публикации группы служб с заданными интерфейсами, то DCM-дескриптор, созданный вызовом функции DcmSetGroupSubscription()
, нужно закрыть вызовом функции DcmCloseGroupSubscrHandle()
.
Чтобы прервать блокирующий вызов функции DcmReadGroupPubQueue()
из другого потока исполнения, нужно вызвать функцию DcmInterruptGroupSubscrBlockingCall()
.
Используя функции DcmSubscribeToGroupSubscrEvent()
и DcmUnsubscribeFromGroupSubscrEvent()
совместно с функциями из API notice_api.h, можно получать уведомления о том, что произошли следующие события: публикация или отмена публикации сервером службы в DCM
(флаг DCM_PUBLICATION_CHANGED
), прерывание блокирующего вызова функции DcmReadGroupPubQueue()
(флаг DCM_BLOCKING_CALL_INTERRUPTED
). (Флаги маски событий и идентификатор записи вида "ресурс – маска событий" DCM_EVENT_ID
определены в заголовочном файле sysroot-*-kos/include/dcm/dcm_api.h
из состава KasperskyOS SDK.) Функции DcmSubscribeToGroupSubscrEvent()
и DcmUnsubscribeFromGroupSubscrEvent()
позволяют настроить приемник уведомлений, соответственно добавляя и удаляя отслеживаемые объекты, идентифицируемые DCM-дескрипторами.
Функции subscr.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает DCM-дескриптор, позволяющий получать уведомления о публикации и отмене публикации групп служб с заданными интерфейсами. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Извлекает уведомление о публикации или отмене публикации группы служб из очереди этих уведомлений. Параметры
Возвращаемые значения В случае успеха возвращает Если блокирующий вызов был прерван вызовом функции Дополнительные сведения Неблокирующий вызов, если в параметре |
|
Назначение Прерывает блокирующий вызов функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Закрывает DCM-дескриптор, полученный вызовом функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Настраивает приемник уведомлений, чтобы он получал уведомления о событиях, связанных с объектом, идентифицируемым заданным DCM-дескриптором. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Настраивает приемник уведомлений, чтобы он не получал уведомления о событиях, связанных с объектом, идентифицируемым заданным DCM-дескриптором. Параметры
Возвращаемые значения В случае успеха возвращает |
Компонент MessageBus
Компонент MessageBus
реализует шину сообщений, которая обеспечивает прием, распределение и доставку сообщений между программами, работающими под KasperskyOS. Шина построена по принципу "издатель-подписчик". Использование шины сообщений позволяет избежать создания большого количества IPC-каналов для связывания каждой программы-подписчика с каждой программой-издателем.
Сообщения, передаваемые через шину MessageBus
, не могут содержать данные. Эти сообщения могут использоваться только для уведомления подписчиков о событиях.
Компонент MessageBus
представляет собой дополнительный уровень абстракции над KasperskyOS IPC, который позволяет упростить процесс разработки и развития ваших программ. MessageBus
является отдельной программой, доступ к которой осуществляется через IPC, но при этом разработчикам предоставляется библиотека доступа к MessageBus
, которая позволяет избежать использования IPC-вызовов напрямую. Чтобы получить доступ к API этой библиотеки, скомпонуйте вашу программу с библиотекой, используя CMake-команду target_link_libraries()
.
CMakeLists.txt
API библиотеки доступа предоставляет следующие интерфейсы:
IProviderFactory
- Интерфейс. предоставляющий фабричные методы для получения доступа к экземплярам остальных интерфейсов.
IProviderControl
- Интерфейс для регистрации и дерегистрации издателя и подписчика в шине.
IProvider (компонент MessageBus)
- Интерфейс для передачи сообщения в шину.
ISubscriber
- Интерфейс обратного вызова для передачи сообщения подписчику.
IWaiter
- Интерфейс ожидания обратного вызова при появлении соответствующего сообщения.
Структура сообщения
Каждое сообщение содержит два параметра:
topic
- Идентификатор темы сообщения.
id
- Дополнительный параметр, специфицирующий сообщение.
Параметры topic
и id
уникальны для каждого сообщения. Интерпретация topic
+id
определяется контрактом между издателем и подписчиком. Например, если изменяются конфигурационные данные, с которыми работают издатель и подписчик, издатель высылает сообщение об изменении данных и id
конкретной записи с новыми данными. Подписчик, пользуясь отличными от MessageBus
механизмами, получает новые данные по ключу id
.
Пример использования компонента MessageBus
в решении на базе KasperskyOS см. в разделе "Пример messagebus".
Интерфейс IProviderFactory
Интерфейс IProviderFactory
предоставляет фабричные методы для получения интерфейсов, необходимых для работы с компонентом MessageBus
.
Описание интерфейса IProviderFactory
представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/messagebus/i_messagebus_control.h
.
Для получения экземпляра интерфейса IProviderFactory
используется свободная функция InitConnection()
, которая принимает имя IPC-канала вашей программы с программой MessageBus
. Имя соединения задается в файле init.yaml.in
при описании конфигурации решения. В случае успешного подключения выходной параметр содержит указатель на интерфейс IProviderFactory
.
- Для получения интерфейса регистрации и дерегистрации (см. "Интерфейс IProviderControl") издателей и подписчиков в шине сообщений используется метод
IProviderFactory::CreateBusControl()
. - Для получения интерфейса, содержащего методы для отправки издателем сообщений в шину (см. "Интерфейс IProvider (компонент MessageBus)"), используется метод
IProviderFactory::CreateBus()
. - Для получения интерфейсов, содержащих методы для получения подписчиком сообщений из шины (см. "Интерфейсы ISubscriber, IWaiter и ISubscriberRunner"), используются методы
IProviderFactory::CreateCallbackWaiter
иIProviderFactory::CreateSubscriberRunner()
.Мы не рекомендуем использовать интерфейс
IWaiter
, поскольку вызов метода этого интерфейса является блокирующим.
i_messagebus_control.h (фрагмент)
Интерфейс IProviderControl
Интерфейс IProviderControl
предоставляет методы для регистрации и дерегистрации издателей и подписчиков в шине сообщений.
Описание интерфейса IProviderControl
представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/messagebus/i_messagebus_control.h
.
Для получение экземпляра интерфейса используется интерфейс IProviderFactory
.
Регистрация и дерегистрация издателя
Для регистрации издателя в шине сообщений используется метод IProviderControl::RegisterPublisher()
. Метод принимает тему сообщения и помещает в выходной параметр уникальный идентификатор клиента шины. Если тема уже зарегистрирована в шине, то вызов будет отклонен, и идентификатор клиента не будет заполнен.
Для дерегистрации издателя в шине сообщений используется метод IProviderControl::UnregisterPublisher()
. Метод принимает идентификатор клиента шины, полученный при регистрации. Если указан идентификатор, не зарегистрированный как идентификатор издателя, то вызов будет отклонен.
i_messagebus_control.h (фрагмент)
Регистрация и дерегистрация подписчика
Для регистрации подписчика в шине сообщений используется метод IProviderControl::RegisterSubscriber()
. Метод принимает имя подписчика и список тем, на которые нужно подписаться, а в выходной параметр помещает уникальный идентификатор клиента шины.
Для дерегистрации подписчика в шине сообщений используется метод IProviderControl::UnregisterSubscriber()
. Метод принимает идентификатор клиента шины, полученный при регистрации. Если указан идентификатор, не зарегистрированный как идентификатор подписчика, то вызов будет отклонен.
i_messagebus_control.h (фрагмент)
Интерфейс IProvider (компонент MessageBus)
Интерфейс IProvider
предоставляет методы для отправки издателем сообщений в шину.
Описание интерфейса IProvider
представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/messagebus/i_messagebus.h
.
Для получение экземпляра интерфейса используется интерфейс IProviderFactory
.
Отправка сообщения в шину
Для оправки сообщения в шину используется метод IProvider::Push()
. Метод принимает идентификатор клиента шины, полученный при регистрации, и идентификатор сообщения. Если очередь сообщений в шине заполнена, то вызов будет отклонен.
i_messagebus.h (фрагмент)
Интерфейсы ISubscriber, IWaiter и ISubscriberRunner
Интерфейсы ISubscriber
, IWaiter
и ISubscriberRunner
предоставляют методы для получения и обработки подписчиком сообщений из шины.
Описания интерфейсов ISubscriber
, IWaiter
и ISubscriberRunner
представлены в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/messagebus/i_subscriber.h
.
Для получение экземпляров интерфейсов IWaiter
и ISubscriberRunner
используется интерфейс IProviderFactory
. Реализация callback-интерфейса ISubscriber
предоставляется приложением-подписчиком.
Получение сообщения из шины
Для перевода подписчика в режим ожидания сообщения от шины, вы можете использовать метод IWaiter::Wait()
или ISubscriberRunner::Run()
. Методы принимают идентификатор клиента шины и указатель на callback-интерфейс ISubscriber
. Если идентификатор клиента не зарегистрирован, то вызов будет отклонен.
Мы не рекомендуем использовать интерфейс IWaiter
, поскольку вызов метода IWaiter::Wait()
является блокирующим.
При получении сообщения из шины будет вызван метод ISubscriber::OnMessage()
. Метод принимает тему и идентификатор сообщения.
i_subscriber.h (фрагмент)
Компонент LogRR
Компонент LogRR
– система для журналирования информации о работе программ. Компонент включает в себя программу-сервер, которому другие программы передают сообщения о своем состоянии, и вспомогательные каналы вывода для журналирования. Для отправки сообщений серверу прикладные программы используют библиотеку logrr_clog
(для C++ доступна библиотека logrr_cpp
), которая фильтрует сообщения по уровню журналирования и отправляет их серверу. Сервер передаёт сообщения каналам вывода. Канал вывода сохраняет сообщения журнала в файлы.
В SDK API программы LogRR представлены статическими и динамическими библиотеками, компонуемыми с программами, информация о работе которых журналируется:
- в программах на языке C используется библиотека
logrr_clog
и заголовочный файлsysroot-*-kos/include/component/logrr/clog/clog.h
. - в программах на языке С++ используется библиотека
logrr_cpp
и заголовочный файлsysroot-*-kos/include/component/logrr/cpp/logger.h
.
Добавление сервера журналирования и каналов вывода в решение
Программа LogrrServer
отправляет сообщения одному или нескольким каналам вывода. Вы можете записывать сообщения журнала в файлы, используя канал вывода FsOutputChannel
.
Добавление и настройка сервера журналирования
Команда создания и настройки сервера журналирования create_logrr_server()
может содержать следующие параметры:
LOG_LEVEL
- Устанавливает указанный уровень журналирования. Доступные значения
LOG_LEVEL
:CRITICAL
,ERROR
,WARNING
,INFO
,DEBUG
иTRACE
. По умолчанию, сервер журналирования обрабатывает сообщения с уровнем Info. CONFIG_PATH
- Указывает путь до конфигурационного файла сервера журналирования.
RECV_CORE_LOGS
- Включает сбор журналов ядра.
WRITE_TO_CORE
- Включает передачу журналов в ядро. Не исключает передачу журналов серверу журналирование и далее в канал вывода. Требуется для вывода журналов в UART.
OUTPUT_CHANNELS
- Подключает один или несколько указанных каналов вывода к серверу.
DENY_DYNAMIC_CONN_TYPES
- Включает отклонение динамических подключений к серверу журналирования.
DENY_STATIC_CONN_TYPES
- Включает отклонение статических подключений к серверу журналирования.
Чтобы добавить программу LogrrServer
в решение,
отредактируйте корневой файл с CMake-командами сборки решения или файл с CMake-командами сборки инициализирующей программы Einit
:
CMakeLists.txt
Опцию PACK_DEPS
требуется включить при вызове команды build_kos_qemu_image()
или build_kos_hw_image()
для включения автоматической сборки библиотек в образ диска.
Добавление и настройка каналов вывода
Команда создания и настройки канала вывода журналов в файлы create_logrr_fs_output_channel()
может содержать следующие параметры:
CONFIG_PATH
- Указывает путь до конфигурационного файла канала вывода.
SERVER_TARGET
- Указывает сервер журналирования, к которому требуется подключить создаваемый канал вывода.
APP_LOG_DIR
- Указывает директорию хранения файлов журналов для программ. Обязательный параметр.
SYS_LOG_DIR
- Указывает директорию хранения файлов журналов системы. Если параметр не задан, файлы журналов системы не сохраняются.
Чтобы добавить канал вывода FsOutputChannel
в решение,
отредактируйте корневой файл с CMake-командами сборки решения или файл с CMake-командами сборки инициализирующей программы Einit
:
CMakeLists.txt
Создание IPC-каналов и разрешение взаимодействия программ
Система сборки обеспечивает автоматическое создание IPC-каналов, необходимых для работы системы журналирования, а также генерирует описание политики безопасности в части, которая разрешает взаимодействие между процессами.
Для создания статического подключения к серверу журналирования, вы можете использовать CMake-команду connect_to_logrr_server (ENTITIES <имена_программ_для_подключения>)
.
Получение записей журнала при работе в QEMU
Клиентские библиотеки logrr_clog
и logrr_cpp
отправляют сообщения в ядру, которое пересылает их в UART-порт. Вы можете перенаправить данные из эмулируемого UART-порта в стандартный поток ввода-вывода, указав флаг -serial stdio
при запуске QEMU. При этом сообщения журнала будут отображаться в терминале, в котором запущен QEMU.
Укажите флаги запуска QEMU в значении параметра QEMU_FLAGS, передаваемого команде build_kos_qemu_image():
CMakeLists.txt
Отправка сообщений в журнал с помощью макросов
Программа LogRR
предоставляет макросы для быстрого доступа к функциям журналирования с определенным уровнем.
Пример использования макросов в программе на языке C:
C
Для использования этих макросов требуется скомпоновать программу с библиотекой logrr_clog.
Пример использования макросов в программе на языке C++:
C++
Для использования этих макросов требуется скомпоновать программу с библиотекой logrr_cpp.
Дополнительные возможности при отправке сообщений в журнал
В большинстве случаев, для отправки сообщений в журнал достаточно использовать макросы быстрого доступа к функциям журналирования.
В этом разделе описаны дополнительные возможности API библиотеки logrr_cpp
: объединение сообщений, отправка сообщений по условию и отложенная отправка.
Объединение сообщений
Чтобы поэтапно получить текст записи журнала из частей и затем отправить запись в журнал одним вызовом:
- Скомпонуйте программу с библиотекой logrr_cpp.
- Подключите заголовочный файл
component/logrr/cpp/tools.h
.C++
- Создайте экземпляр класса
LogIface
.C++
auto logger = LogIface(logrr::LogLevel::Warning); - Заполните буфер сообщений одним или несколькими вызовами метода
LogIface::Push()
.C++
logger.Push("a={}", a); // ... logger.Push(", b={}", b); // ... logger.Push(", c={}", c); - Отправьте ранее полученные сообщения в журнал с помощью метода
LogIface::Flush()
.C++
logger.Flush();
Отправка сообщения в журнал по условию
Чтобы отправить сообщение в журнал только при выполнении указанного условия:
- Скомпонуйте программу с библиотекой logrr_cpp.
- Подключите заголовочный файл
component/logrr/cpp/tools.h
.C++
- Передайте логическое значение, один из перечислителей
LogLevel
и текст сообщения в макросLOG_IF()
.C++
LOG_IF(IsWorldBroken(), logrr::LogLevel::Critical, "World is broken!");
Отложенная отправка сообщений в журнал
Макрос LOG_DEFER()
, объявленный в заголовочном файле component/logrr/cpp/tools.h
, позволяет избежать дублирования кода для журналирования в блоках if
...else
.
Чтобы отправить предварительно отформатированное сообщение в журнал в момент выхода из функции:
- Скомпонуйте программу с библиотекой logrr_cpp.
- Подключите заголовочный файл
component/logrr/cpp/tools.h
.C++
- Добавьте вызов макроса
LOG_DEFER()
в начало кода функции, изменяющей значения, которые нужно отправить в журнал. В макрос передайте значениеLogLevel
, строку форматирования сообщения и аргументы для подстановки в строку форматирования.C++
int DeferredLoggingExample() { auto logger = LOG_DEFER(logrr::LogLevel::Info, "a={}, b={}", a, b); if (someCondition) { a = 1; b = 2; return -1; } else { a = 3; b = 4; return 0; } }
В этом примере, сообщение отправляется в журнал при вызове деструктора объекта logger
на выходе из функции DeferredLoggingExample()
. В строку форматирования сообщения подставляются значения a
и b
, актуальные на момент выхода из функции.
Уровни журналирования
Атрибутом каждого сообщения в системе журналирования является уровень журналирования. Уровень используется при фильтрации сообщений в клиенте и настраивается через сервер.
- Critical
- Критический сбой в работе программы, после которого продолжение работы программы невозможно.
- Error
- Ошибка в работе программы, после которой все еще возможно продолжение работы. Этот уровень применяется для журналирования неожиданного завершения текущей операции. Не рекомендуется применять для журналирования ошибочных действий пользователя.
- Warning
- Проблемная ситуация, возникновение которой предусмотрено, и обрабатывается программой в обычном режиме.
- Info (установлен по умолчанию)
- Информация о текущем функционировании программы, без дополнительных подробностей. Например, переход в новое окно в пользовательском интерфейсе или успешная запись данных в базу.
- Debug
- Более подробный уровень журналирования, чем Info. Предоставляет больше деталей о событиях программы и может быть полезен при отладке.
- Trace
- Самый подробный уровень журналирования, используемый для наиболее детального отслеживания событий программы. При включении может значительно влиять на производительность.
Каждый последующий уровень включает в себя все предыдущие. Например, если сервер настроен на уровень Warning, то в журнал передаются сообщения с уровнями Critical, Error и Warning, а сообщения с уровнями Info, Debug и Trace игнорируются.
Установка уровня журналирования при отправке сообщения программой может осуществляться:
- использованием макроса с параметром, соответствующем выбранному уровню;
- передачей значения перечислителя
LogrrLogLevel
илиLogLevel
при вызове функций журналирования.
API программы LogRR
Библиотеки программы LogRR
, предоставляют API для отправки сообщений в журнал через сервер журналирования, а также API для управления работой сервера журналирования.
Библиотека logrr_clog
Библиотека logrr_clog
предоставляет API для отправки сообщений в журнал.
Библиотека logrr_clog
предназначена для использования в программах на языке C. В программах на языке C++ используйте библиотеку logrr_cpp
.
Чтобы получить доступ к API этой библиотеки,
скомпонуйте вашу программу с библиотекой, используя CMake-команду target_link_libraries()
.
CMakeLists.txt
Функция ClogLog() и макрос CLOG
Функция ClogLog()
выполняет запись в журнал.
Функция ClogLog()
предназначена для использования в программах на языке C. В программах на языке C++ используйте функцию Logger::Log() или макросы LOG_*.
Описание функции ClogLog()
и макросов для быстрого доступа к ней представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/component/logrr/clog/clog.h
.
component/logrr/clog/clog.h (фрагмент)
Параметры функции ClogLog()
:
level
- Уровень журналирования
LogrrLogLevel
. file
- Имя файла.
line
- Номер строки в файле.
func
- Имя функции.
message
- Текст сообщения или строка форматирования текста сообщения.
...
- Параметры для подстановки в строку форматирования
message
.
Макрос быстрого доступа к функции ClogLog()
Вместо вызова функции ClogLog()
вы можете использовать макрос, описание которого представлено в файле component/logrr/clog/clog.h
. Этот макрос является вариационным (принимает переменное число параметров), что позволяет не указывать все параметры функции ClogLog()
. При вызове макроса достаточно указать уровень журналирования и текст сообщения или строку форматирования сообщения со значениями параметров. Используемый уровень журналирования level
определяется первым параметром макроса. Пример использования этого макроса представлен в разделе "Отправка сообщений в журнал с помощью макросов".
Перечисляемый тип LogrrLogLevel
Перечисляемый тип LogrrLogLevel
содержит поля, имена которых соответствуют уровням журналирования, доступным в программе LogRR
.
Перечисляемый тип LogrrLogLevel
предназначен для использования в программах на языке C. В программах на языке C++ используйте класс LogLevel
.
Перечислители LogrrLogLevel
могут передаваться в функцию ClogLog()
для отправки сообщения с указанным уровнем.
Описание перечисления LogrrLogLevel
представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/component/logrr/core/log_level_c.h
.
component/logrr/core/log_level_c.h (фрагмент)
Библиотека logrr_cpp
Библиотека logrr_cpp
предоставляет API для отправки сообщений в журнал.
Библиотека logrr_cpp
предназначена для использования в программах на языке C++. В программах на языке C используйте библиотеку logrr_clog
.
Чтобы получить доступ к API этой библиотеки,
скомпонуйте вашу программу с библиотекой, используя CMake-команду target_link_libraries()
.
CMakeLists.txt
Метод Log() и макрос LOG
Метод logrr::Log()
выполняет запись в журнал.
Параметры метода:
logLevel
- Уровень журналирования
LogLevel
. sourceLocation
- Объект, определяющий местоположение в исходном коде (имя файла, имя функции, номер строки и номер столбца). В C++20 используется класс
std::source_location
, в более ранних версиях используется классstd::experimental::source_location
. format
- Строка форматирования текста сообщения.
args
- Параметры для подстановки в строку форматирования
format
.
Метод logrr::Log()
предназначен для использования в программах на языке C++. В программах на языке C используйте статическую функцию ClogLog() или макрос CLOG.
Описание метода logrr::Log()
и макроса быстрого доступа к нему представлены в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/component/logrr/cpp/logger.h
.
component/logrr/cpp/logger.h (фрагмент)
Макрос быстрого доступа к методу Log()
Вместо вызова статического метода Logger::Log()
вы можете использовать макрос, описание которого представлено в файле component/logrr/cpp/logger.h
. Этот макрос является вариационным (принимает переменное число параметров), что позволяет не указывать все параметры метода Logger::Log()
. При вызове макроса достаточно указать только уровень журналирования и строку форматирования сообщения со значениями параметров. Используемый уровень журналирования logLevel
определяется первым параметром макроса: Пример использования этого макросов представлен в разделе "Отправка сообщений в журнал с помощью макросов".
Класс LogLevel
Класс LogLevel
является перечислением (enum class
) и содержит поля, имена которых соответствуют уровням журналирования, доступным в программе LogRR
.
Класс LogLevel
предназначен для использования в программах на языке C++. В программах на языке C используйте перечисляемый тип LogrrLogLevel
.
Значения перечисления LogLevel
могут передаваться в:
- статический метод
Log()
классаLogger
; - статические методы
ChangeLogLevel()
иChangeGlobalLogLevel()
структурыController
; - конструктор класса
LogIface
;
Описание класса LogLevel
представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/component/logrr/core/log_level.h
.
component/logrr/core/log_level.h (фрагмент)
Класс LogIface
Класс LogIface
содержит методы, позволяющие поэтапно получить текст записи журнала из частей, и затем отправить запись в журнал одним вызовом:
- Для установки уровня журналирования отправляемых сообщений используется метод
SetLogLevel()
. - Для добавления текста к сообщению используется метод
Push()
. - Для отправки составленного одним или несколькими вызовами метода
Push()
сообщения в журнал используется методFlush()
.При вызове деструктора
~LogIface()
в журнал также отправляется составленное вызовамиPush()
сообщение, если оно не было ранее отправлено с помощьюFlush()
. - Для немедленной отправки отдельного сообщения (без использования составленного вызовами
Push()
текста) используется методLog()
.
Чтобы создать экземпляр класса LogIface
, передайте один из перечислителей LogLevel
в конструктор класса. Пример использования функций класса LogIface
представлен в подразделе "Объединение сообщений" раздела "Дополнительные возможности при отправке сообщений в журнал".
Описание класса LogIface
представлено в файле /opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/component/logrr/cpp/tools.h
.
component/logrr/cpp/tools.h (фрагмент)
Компонент ExecutionManager
API определен в заголовочных файлах, расположенных в директории sysroot-*-kos/include/component/execution_manager/
из состава KasperskyOS SDK.
Сценарий использования компонента ExecutionManager описан в статье "Запуск процессов с помощью системной программы ExecutionManager".
Интерфейс execution_manager_proxy.h
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/kos_ipc/execution_manager_proxy.h
из состава KasperskyOS SDK.
Интерфейс содержит функцию CreateExecutionManager()
для получения указателя на экземпляр интерфейса IExecutionManager
, необходимого для работы с компонентом ExecutionManager. Через входной параметр cfg
эта функция принимает параметры конфигурации в виде структуры ExecutionManagerConfig
. Все поля этой структуры опциональны для заполнения.
Функции execution_manager_proxy.h
Функция |
Сведения о функции |
---|---|
|
Назначение Получение указателя на экземпляр интерфейса Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс IExecutionManager
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_execution_manager.h
из состава KasperskyOS SDK.
Интерфейс IExecutionManager
позволяет получить доступ к указателям на следующие интерфейсы:
IProcessControl
– интерфейс, который позволяет запускать процесс из исполняемого файла, установленного компонентом PackageManager из KPA-пакета в решение на базе KasperskyOS, а также получать сведения о процессе (включая информацию о его завершении) и останавливать его.IApplicationController
– интерфейс, который позволяет запускать процесс из любого исполняемого файла, чье расположение в файловой системе известно, а также останавливать этот процесс.IStateProvider
– интерфейс для получения сведений о процессе, запущенном с использованием интерфейсаIApplicationController
.ISystemController
– интерфейс для управления системой.
Пример использования:
client.cpp
Интерфейс IProcessControl
API определен в заголовочном файле sysroot-*-kos/include/alm/execution_manager/i_process_control.h
из состава KasperskyOS SDK.
API позволяет:
- запускать процесс из исполняемого файла, установленного компонентом PackageManager из KPA-пакета в решение на базе KasperskyOS;
- получать сведения о процессе (включая информацию о его завершении);
- останавливать процесс.
Сведения о функциях API приведены в таблице ниже.
Запуск процесса
Чтобы запустить процесс, нужно вызвать функцию StartProcess()
. Через входной параметр opts
эта функция принимает параметры для запуска процесса в виде структуры StartOptions
. Все поля этой структуры являются опциональными для инициализации.
При инициализации структуры StartOptions
транспортный контейнер дескриптора parent
заполняется значениями по умолчанию, которые означают отсутствие родительского процесса. Передавая в этом параметре запускаемому дочернему процессу дескриптор родительского процесса, можно создавать иерархию процессов.
Вектор userHandles
является компонентом структуры StartOptions
и содержит список пользовательских дескрипторов, которые будут переданы процессу при его запуске. Элементами списка являются пары, задаваемые в структуре UserHandleItem
и состоящие из дескриптора и его имени. После запуска процесса переданные ему дескрипторы могут быть найдены с помощью функции KosTaskLookupResource()
по их именам.
Входные параметры pkgId
и runConfigId
функции StartProcess()
определены в манифесте KPA-пакета. Их значения могут быть получены с использованием функций из интерфейса IPackageManifest компонента PackageManager.
Остановка процесса
Чтобы остановить процесс, нужно вызвать функцию StopProcess()
. Через входной параметр stopPolicy
эта функция принимает политику остановки процесса из перечисления StopPolicy
.
Получение сведений о процессе
Чтобы запросить сведения о процессе, нужно вызвать функцию GetProcessState()
. Через выходной параметр state
эта функция возвращает сведения о процессе в виде структуры ProcessContext
.
Перечисление state
является компонентом структуры ProcessContext
и описывает состояние процесса.
Перечисление exitStatus
является компонентом структуры ProcessContext
и описывает причину остановки процесса. Перечисление ExecutableExitStatus
определено в заголовочном файле sysroot-*-kos/include/alm/execution_manager/execution_manager_types.h
из состава KasperskyOS SDK.
Числовой параметр exitCode
является компонентом структуры ProcessContext
и содержит код возврата для процесса, который остановился самостоятельно, в том числе после получения сигнала на свою остановку. Значения для этого кода возврата определяются разработчиком решения на базе KasperskyOS.
Числовой параметр exitReason
является компонентом структуры ProcessContext
и содержит код возврата, который уточняет причину неудачной попытки запуска процесса, либо rcOk
в случае успешного запуска. Параметр определен в заголовочном файле sysroot-*-kos/include/rtl_cpp/retcode.h
из состава KasperskyOS SDK. В этом файле содержатся коды возврата, которые являются общими для API любых компонентов решения и их составных частей (см. "Коды возврата").
Функции i_process_control.h
Функция |
Сведения о функции |
---|---|
|
Назначение Запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Останавливает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Запрашивает сведения о процессе. Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс IApplicationController
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_application_control.h
из состава KasperskyOS SDK.
API позволяет запускать процесс из исполняемого файла, а также останавливать процесс.
Сведения о функциях API приведены в таблице ниже.
Чтобы запустить процесс, нужно вызвать функцию StartEntity()
. Через входной параметр info
эта функция принимает параметры для запуска процесса в виде структуры StartEntityInfo
. Все поля этой структуры являются опциональными для инициализации. Через выходной параметр resInfo
эта функция возвращает ссылку на структуру StartEntityResultInfo
с результатами запуска процесса.
Чтобы остановить процесс, нужно вызвать функцию ShutdownEntity()
или StopEntity()
. Через входной параметр entId
эти функции принимают дескриптор, идентифицирующий запущенный процесс.
Функции i_application_control.h
Функция |
Сведения о функции |
---|---|
|
Назначение Запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отправляет процессу сигнал на завершение. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Немедленно останавливает исполнение процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс IStateProvider
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_state_control.h
из состава KasperskyOS SDK.
API позволяет получать сведения о процессе, запущенном с использованием функции StartEntity()
из API IApplicationController (см. "Интерфейс IApplicationController"), включая информацию о причине его завершения.
Сведения о функциях API приведены в таблице ниже.
Чтобы получить сведения о процессе, нужно вызвать функцию GetApplicationState()
. Через входной параметр entityId
эта функция принимает значение типа EntityId
, которое идентифицирует запущенный процесс. Через выходной параметр appState
эта функция возвращает сведения о процессе в виде структуры AppContext
. Структура AppContext
определена в заголовочном файле sysroot-*-kos/include/component/execution_manager/types.h
из состава KasperskyOS SDK
Перечисление state
является компонентом структуры AppContext
и описывает состояние процесса. Перечисление state
определено в заголовочном файле sysroot-*-kos/include/component/execution_manager/types.h
из состава KasperskyOS SDK.
Перечисление exitStatus
является компонентом структуры AppContext
и описывает причину остановки процесса. Перечисление ExecutableExitStatus
определено в заголовочном файле sysroot-*-kos/include/alm/execution_manager/execution_manager_types.h
из состава KasperskyOS SDK.
Числовой параметр exitCode
является компонентом структуры AppContext
и содержит код возврата для процесса, который остановился самостоятельно, в том числе после получения сигнала на свою остановку. Значения для этого кода возврата определяются разработчиком решения на базе KasperskyOS.
Числовой параметр exitReason
является компонентом структуры AppContext
и содержит код возврата, который уточняет причину неудачной попытки запуска процесса, либо rcOk
в случае успешного запуска процесса. Параметр определен в заголовочном файле sysroot-*-kos/include/rtl_cpp/retcode.h
из состава KasperskyOS SDK. В этом файле содержатся коды возврата, которые являются общими для API любых компонентов решения и их составных частей (см. "Коды возврата").
Функции i_state_control
Функция |
Сведения о функции |
---|---|
|
Назначение Запрашивает сведения о процессе. Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс ISystemController
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_system_control.h
из состава KasperskyOS SDK.
API позволяет завершать работу системы.
Сведения о функциях API приведены в таблице ниже.
Функции i_system_control.h
Функция |
Сведения о функции |
---|---|
|
Назначение Останавливает все запущенные процессы; затем завершает процесс ExecutionManager; а затем отправляет в ядро запрос на выключение устройства. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Компонент PackageManager
API определен в заголовочных файлах, расположенных в директории sysroot-*-kos/include/component/package_manager/
из состава KasperskyOS SDK.
Сценарий использования компонента PackageManager описан в статье "Сценарий использования компонента PackageManager".
Интерфейс package_manager_proxy.h
API определен в заголовочном файле sysroot-*-kos/include/component/package_manager/kos_ipc/package_manager_proxy.h
из состава KasperskyOS SDK.
Интерфейс содержит функцию CreatePackageManager()
для получения указателя на экземпляр интерфейса IPackageManager
, необходимого для работы с компонентом PackageManager. Через входной параметр cfg
эта функция принимает параметры конфигурации в виде структуры PackageManagerConfig
. Все поля этой структуры опциональны для заполнения.
Функции package_manager_proxy.h
Функция |
Сведения о функции |
---|---|
|
Назначение Получение указателя на экземпляр интерфейса Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс IPackageManager
API определен в заголовочном файле sysroot-*-kos/include/component/package_manager/i_package_manager.h
из состава KasperskyOS SDK.
Интерфейс IPackageManager
позволяет получить указатель на интерфейс IPackageController
. Этот интерфейс предназначен для установки KPA-пакетов в решение на базе KasperskyOS, а также получения сведений о них.
Функции i_package_manager.h
Функция |
Сведения о функции |
---|---|
|
Назначение Получение указателя на экземпляр интерфейса Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс IPackageController
API определен в заголовочном файле sysroot-*-kos/include/component/package_manager/i_package_control.h
из состава KasperskyOS SDK.
API позволяет:
- устанавливать KPA-пакет в решение на базе KasperskyOS и удалять KPA-пакет;
- получать сведения об установленном KPA-пакете: уникальный идентификатор, данные из манифеста KPA-пакета, статус KPA-пакета (установлен или удален).
Сведения о функциях API приведены в таблице ниже.
Установка KPA-пакета
Чтобы установить KPA-пакет, нужно вызвать функцию InstallPackage()
. Через входной параметр pkgInfo
эта функция принимает данные для проверки сертификатов устанавливаемого KPA-пакета в виде структуры InstallPackageInfo
. Все поля этой структуры являются опциональными для заполнения.
Если параметр signatureVerify
установлен в значение true
(проверять сертификаты устанавливаемого KPA-пакета), а имена файлов не указаны, то при установке KPA-пакета будут использованы значения по умолчанию: <имя_пакета>.kcat
для файла внешней подписи KPA-пакета и <имя_пакета>.kidx
для индексного файла KPA-пакета.
Удаление KPA-пакета
Чтобы удалить KPA-пакет, нужно вызвать функцию UninstallPackage()
.
Получение сведений об установленных KPA-пакетах
Чтобы получить уникальные идентификаторы установленных KPA-пакетов, нужно вызвать функцию ListInstalledPackages()
. Через выходной параметр pkgUIDs
функция возвращает список уникальных идентификаторов установленных пакетов.
Чтобы получить данные о манифесте KPA-пакета, нужно вызвать функцию GetManifest()
. Через выходной параметр manifest
функция возвращает указатель на экземпляр интерфейса IPackageManifest
, используя который можно получить доступ к значениям ключей манифеста KPA-пакета. Подробнее см. "Интерфейс IPackageManifest".
Уведомления о статусах KPA-пакетов в решении на базе KasperskyOS
Компонент PackageManager реализует механизм уведомлений о статусах KPA-пакетов в решении на базе KasperskyOS, позволяя отслеживать изменения в их состоянии. Для получения уведомлений нужно создать очередь уведомлений используя функцию CreateEventQueue()
.
Чтобы извлекать уведомления из этой очереди, нужно использовать функцию GetEvents()
. Через выходной параметр pkgEvent
s функция возвращает статус KPA-пакетов (с момента создания очереди) в виде структуры PackageEvent
.
Чтобы удалить очередь уведомлений, нужно вызвать функцию DestroyEventQueue()
.
Функции i_package_control.h
Функция |
Сведения о функции |
---|---|
|
Назначение Устанавливает KPA-пакет. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет KPA-пакет. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает уникальные идентификаторы установленных KPA-пакетов. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает указатель на экземпляр интерфейса Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает хеш-сумму файла компонента KPA-пакета из базы данных компонента PackageManager. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает содержимое компонента KPA-пакета. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает очередь уведомлений о статусах KPA-пакетов. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет очередь уведомлений о статусах KPA-пакетов. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает из очереди уведомлений статусы KPA-пакетов. Параметры
Возвращаемые значения В случае успеха возвращает |
Пример использования:
client.cpp
Интерфейс IPackageManifest
API определен в заголовочном файле sysroot-*-kos/include/component/package_manager/i_package_manifest.h
из состава KasperskyOS SDK.
API позволяет получать значения ключей манифеста KPA-пакета. Подробнее о доступных ключах манифеста KPA-пакета см. "Манифест KPA-пакета"
Сведения о функциях API приведены в таблице ниже.
Получение идентификатора программы
Чтобы получить идентификатор программы, установленной из KPA-пакета, нужно вызвать функцию GetPackageID()
.
Получение сведений о компонентах KPA-пакета
Чтобы получить сведения о компонентах KPA-пакета, нужно вызвать функцию GetApplicationsInfo()
. Через выходной параметр applications
функция возвращает сведения о компонентах KPA-пакета в виде вектора структур ApplicationInfo
.
Элемент структуры extensions
описывает объект формата JSON. ManifestType
является псевдонимом типа nlohmann:json
.
Получение конфигураций запуска программы
Чтобы получить сведения о конфигурациях запуска программы, установленной из KPA-пакета, нужно вызвать функцию GetRunConfigurationsInfo()
. Через выходной параметр runConfigurations
функция возвращает сведения о конфигурациях запуска программы в виде вектора структур RunConfigurationInfo
.
Получение сведений о программе
Чтобы получить сведения о программе, установленной из KPA-пакета, нужно вызвать функцию GetPackageInfo()
. Через выходной параметр packageInfo
функция возвращает сведения о конфигурациях запуска в виде структуры PackageInfo
.
Получение сведений об изолированном хранилище программы
Чтобы получить сведения об изолированном хранилище программы, нужно вызвать функцию GetPrivateStorageInfo()
. Через выходной параметр packageInfo
функция возвращает сведения о конфигурациях запуска в виде структуры PrivateStorage
.
Получение сведений об объектах произвольного формата
Чтобы получить сведения об объектах произвольного формата, которые добавлены разработчиком KPA-пакета (ключ extensions
из манифеста KPA-пакета), нужно вызвать функцию Get()
.
Функции i_package_manifest.h
Функция |
Сведения о функции |
---|---|
|
Назначение Получает уникальный идентификатор программы, установленной из KPA-пакета. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает сведения о компонентах KPA-пакета. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает сведения о конфигурациях запуска программы, установленной из KPA-пакета. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает сведения о программе, установленной из KPA-пакета. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает сведения об изолированно хранилище программы. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Получает сведения об объектах произвольного формата, который добавлены в манифест разработчиком KPA-пакета. Параметры Нет. Возвращаемые значения Возвращает указатель на объект типа |
Пример использования:
client.cpp