Содержание
- KasperskyOS API
- Коды возврата
- Библиотека libkos
- Управление дескрипторами (handle_api.h)
- Выделение и освобождение памяти (alloc.h)
- Использование DMA (dma.h)
- Управление обработкой прерываний (irq.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)
- Поддержка POSIX
- Получение статистических сведений о системе
- Компонент MessageBus
- Компонент ExecutionManager
Коды возврата
Общие сведения
В решении на базе 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-каналов;
- управление электропитанием;
- получение статистических сведений о системе;
- другие возможности, поддерживаемые службами ядра.
Этот раздел содержит подробные описания работы с некоторыми интерфейсами библиотеки libkos
. Описания остальных интерфейсов вы можете найти в соответствующих им заголовочных файлах.
Заголовочные файлы, определяющие API библиотеки libkos
, расположены в следующих директориях:
sysroot-*-kos/include/coresrv/
sysroot-*-kos/include/kos/
Управление дескрипторами (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
).
При создании дескриптора пользовательского ресурса маска прав задается пользователем.
При передаче дескриптора маска прав задается пользователем, но передаваемые права доступа не могут быть повышены относительно прав доступа, которые имеет процесс.
В началоСоздание дескрипторов
Создание дескрипторов системных ресурсов
Дескрипторы системных ресурсов создаются при создании этих ресурсов, например, при регистрации прерывания или региона памяти 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-дескрипторами. Параметры
Возвращаемые значения В случае успеха возвращает |
Передача дескрипторов
Общие сведения
Передача дескрипторов между процессами осуществляется, чтобы потребители ресурсов получили доступ к требуемым ресурсам. По причине локальности дескрипторов передача дескриптора инициирует на стороне принимающего процесса создание дескриптора из его пространства дескрипторов. Этот дескриптор регистрируется как потомок отправленного дескриптора и идентифицирует тот же ресурс.
Один дескриптор может быть передан многократно одному или нескольким процессам. Каждая передача порождает нового потомка переданного дескриптора на стороне принимающего процесса. Процесс может передавать дескрипторы, которые он получил от других процессов или ядра 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
. Это нужно, чтобы сервер мог проверить, что клиент при использовании ресурса передал в интерфейсный метод дескриптор того ресурса, который соответствует этому методу. Такая проверка требуется, поскольку клиент может ошибочно передать в интерфейсный метод дескриптор ресурса, который не соответствует этому методу. Например, клиент получил дескриптор файла и передал его в интерфейсный метод для работы с томами.
Чтобы ассоциировать передачу дескриптора с контекстом передачи ресурса, сервер помещает в поле 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()
и освобождает память, которая была выделена для контекста пользовательского ресурса.
- Поставщик ресурсов вызовом функции
Выделение и освобождение памяти (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()
.Вызов функции
KnIoDmaBegin()
необходим, чтобы создать объект ядра, содержащий адреса и размеры блоков, из которых состоит буфер DMA. Эти сведения необходимы устройству, чтобы использовать буфер DMA. Устройство может работать как с физическими, так и с виртуальными адресами в зависимости от того, задействован ли IOMMU. Если IOMMU задействован, объект содержит виртуальные адреса блоков. В противном случае объект содержит физические адреса блоков.Дескриптор, полученный при вызове функции
KnIoDmaBegin()
, нельзя передать другому процессу через IPC. - Получение сведений о буфере DMA.
На этом шаге нужно получить адреса и размеры блоков из объекта ядра, созданного вызовом функции
KnIoDmaBegin()
. Полученные адреса и размеры в дальнейшем требуется передать устройству, используя, например, MMIO. После получения этих сведений устройство может записывать в буфер DMA и/или читать из него (при задействовании IOMMU устройство на шине PCIe должно быть прикреплено к домену IOMMU).Чтобы выполнить этот шаг, нужно вызвать функцию
KnIoDmaGetInfo()
илиKnIoDmaContinuousGetDmaAddr()
. ФункцияKnIoDmaGetInfo()
позволяет получить номер страницы памяти (frame
) и порядок (order
) для каждого блока. (Номер страницы памяти, умноженный на размер страницы памяти, дает адрес блока. Значение 2^order представляет собой размер блока в страницах памяти.) ФункциюKnIoDmaContinuousGetDmaAddr()
можно использовать, если буфер DMA состоит из одного блока. Эта функция позволяет получить адрес блока. (В качестве размера блока нужно принять размер буфера DMA, заданный при его создании.)
Закрытие доступа к буферу DMA для устройства
Если удалить объект ядра, созданный при вызове функции KnIoDmaBegin()
, то при задействовании IOMMU доступ устройства к буферу DMA будет запрещен. Чтобы удалить этот объект, нужно вызвать функцию KnHandleClose()
, указав дескриптор, который был получен при вызове функции KnIoDmaBegin()
. (Функция KnHandleClose()
объявлена в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.)
Удаление буфера DMA
Чтобы удалить буфер DMA, нужно выполнить следующие шаги:
- Освободить регионы виртуальной памяти, зарезервированные при вызовах функции
KnIoDmaMap()
.Чтобы выполнить этот шаг, нужно использовать функцию
KnHandleClose()
, указывая дескрипторы, которые были получены при вызовах функцииKnIoDmaMap()
. (ФункцияKnHandleClose()
объявлена в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.)Этот шаг нужно выполнить для всех процессов, на память которых отображен буфер DMA.
- Удалить объект ядра, созданный вызовом функции
KnIoDmaBegin()
.Чтобы выполнить этот шаг, нужно вызвать функцию
KnHandleClose()
, указав дескриптор, который был получен при вызове функцииKnIoDmaBegin()
. - Закрыть или отозвать каждый дескриптор буфера DMA во всех процессах, которые владеют этими дескрипторами.
Чтобы выполнить этот шаг, нужно использовать функцию
KnHandleClose()
и/илиKnHandleRevoke()
, которые объявлены в заголовочном файлеsysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Сведения о функциях API
Функции dma.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает буфер DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Создает буфер DMA, состоящий из одного блока. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Резервирует регион виртуальной памяти и отображает на него буфер DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Изменяет параметры кеширования буфера DMA. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Функцию можно использовать, если выполняются следующие условия:
В параметре
|
|
Назначение Позволяет получить сведения о буфере DMA. Сведения включают адреса и размеры блоков. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить адрес блока для буфера DMA, состоящего из одного блока. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Открывает доступ к буферу DMA для устройства. Параметры
Возвращаемые значения В случае успеха возвращает |
Управление обработкой прерываний (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
Функция |
Сведения о функции |
---|---|
|
Назначение Регистрирует прерывание. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Привязывает вызывающий поток исполнения к прерыванию. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Отправляет потоку исполнения запрос, в результате выполнения которого поток должен выполнить отвязывание от прерывания. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Разрешает (демаскирует) прерывание. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Запрещает (маскирует) прерывание. Параметры
Возвращаемые значения В случае успеха возвращает |
Инициализация 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()
, внутри которых этот цикл выполняется полностью. (Функции NkKosTransport_Dispatch()
и NkKosDoDispatch()
объявлены в заголовочных файлах transport-kos.h
и transport-kos-dispatch.h
соответственно.) Использовать функцию NkKosDoDispatch()
удобнее, поскольку нужно выполнять меньше подготовительных операций (в том числе не требуется инициализировать IPC-транспорт).
Для инициализации структуры, передаваемой функции NkKosDoDispatch()
через параметр info
, можно использовать макросы, определенные в заголовочном файле transport-kos-dispatch.h
.
Функции NkKosTransport_Dispatch()
и NkKosDoDispatch()
можно вызывать из параллельных потоков исполнения, если реализация методов служб потокобезопасна.
Пример использования функции NkKosDoDispatch()
:
Пример использования функции NkKosTransport_Dispatch()
:
Копирование данных в арену IPC-сообщений
Чтобы скопировать строку в арену IPC-сообщений, нужно вызвать функцию NkKosCopyStringToArena()
, объявленную в заголовочном файле transport-kos.h
. Эта функция резервирует участок арены и копирует строку в этот участок.
Пример использования функции NkKosCopyStringToArena()
:
Сведения о функциях API
Функции transport-kos.h
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует IPC-транспорт. Параметры
Возвращаемые значения Нет. |
|
Назначение Инициализирует IPC-транспорт с поддержкой прерывания системных вызовов Параметры
Возвращаемые значения Нет. |
|
Назначение Задает для IPC-транспорта максимальное время блокировки системных вызовов Параметры
Возвращаемые значения Нет. |
|
Назначение Запускает цикл обработки IPC-запросов. Параметры
Возвращаемые значения В случае неуспеха возвращает код ошибки. |
|
Назначение Резервирует участок арены и копирует строку в этот участок. Параметры
Возвращаемые значения В случае успеха возвращает |
Функции transport-kos-dispatch.h
Функция |
Сведения о функции |
---|---|
|
Назначение Запускает цикл обработки 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()
. - Добавление в приемник уведомлений записей вида "ресурс – маска событий", чтобы настроить его на получение уведомлений о событиях, которые происходят с интересующими ресурсами.
Чтобы добавить запись вида "ресурс – маска событий" в приемник уведомлений, нужно вызвать функцию
KnNoticeSubscribeToObject()
. (В маске прав дескриптора ресурса, указанного в параметреobject
, должен быть флагOCAP_HANDLE_GET_EVENT
.) Для одного и того же ресурса можно добавить несколько записей вида "ресурс – маска событий", при этом не требуется, чтобы идентификаторы этих записей были уникальными. Отслеживаемые события для каждой записи вида "ресурс – маска событий" нужно задать маской событий, которая может соответствовать одному или нескольким событиям.Добавленные в приемник уведомлений записи вида "ресурс – маска событий" можно полностью или частично удалить, чтобы этот приемник не получал уведомления, соответствующие этим записям. Чтобы удалить из приемника уведомлений все записи вида "ресурс – маска событий", нужно вызвать функцию
KnNoticeDropAndWake()
. Чтобы удалить из приемника уведомлений записи вида "ресурс – маска событий", относящиеся к одному ресурсу, нужно вызвать функциюKnNoticeUnsubscribeFromObject()
. Чтобы удалить из приемника уведомлений записи вида "ресурс – маска событий" с конкретным идентификатором, нужно вызвать функциюKnNoticeUnsubscribeFromEvent()
.Записи вида "ресурс – маска событий" можно добавлять в приемник уведомлений и удалять из него на протяжении всего жизненного цикла этого приемника уведомлений.
- Извлечение уведомлений из приемника с использованием функции
KnNoticeGetEvent()
.При вызове функции
KnNoticeGetEvent()
можно задать время ожидания появления уведомлений в приемнике. Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновят свое исполнение при появлении уведомлений, даже если эти уведомления соответствуют записям вида "ресурс – маска событий", добавленным после начала ожидания.Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновят свое исполнение, если из этого приемника будут удалены все записи вида "ресурс – маска событий" вызовом функции
KnNoticeDropAndWake()
. Если после вызова функцииKnNoticeDropAndWake()
добавить в приемник уведомлений хотя бы одну запись вида "ресурс – маска событий", то потоки исполнения, получающие уведомления из этого приемника, будут снова заблокированы при вызове функцииKnNoticeGetEvent()
на заданное время ожидания при отсутствии уведомлений. Если все записи вида "ресурс – маска событий" удалены из приемника уведомлений с использованием функцииKnNoticeUnsubscribeFromObject()
и/или функцииKnNoticeUnsubscribeFromEvent()
, то исполнение потоков, ожидающих появления уведомлений в этом приемнике, не возобновляется до истечения времени ожидания. - Удаление приемника уведомлений вызовом функции
KnNoticeRelease()
.Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновят свое исполнение при удалении этого приемника вызовом функции
KnNoticeRelease()
.
Чтобы уведомить другие процессы и/или потоки исполнения о событиях, которые произошли с пользовательским ресурсом, нужно вызвать функцию 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.
Динамическое создание IPC-канала на стороне клиента включает следующие шаги:
- Подключиться к серверу имен вызовом функции
NsCreate()
. - Найти сервер, предоставляющий требуемую службу, используя функцию
NsEnumServices()
.Чтобы получить полный список служб с заданным интерфейсом, нужно вызвать функцию несколько раз, инкрементируя индекс, пока не будет получена ошибка
rcResourceNotFound
. - Выполнить запрос на создание IPC-канала с требуемым сервером вызовом функции
KnCmConnect()
.
К серверу имен можно подключить несколько клиентов и серверов. Каждый клиент и сервер может создать несколько подключений к серверу имен. Сервер может отменить публикацию службы, выполненную другим сервером.
Удаление динамически созданных 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.
API позволяет прикреплять устройства на шине PCIe к домену IOMMU, ассоциированному с вызывающим процессом, и выполнять обратную операцию. Как правило, прикрепление устройства к домену IOMMU выполняется при инициализации драйвера. Открепление устройства от домена IOMMU обычно выполняется при возникновении ошибок во время инициализации драйвера или при финализации драйвера.
Ассоциация буфер DMA с доменом IOMMU создается при вызове функции KnIoDmaBegin()
, входящей в API dma.h.
Сведения о функциях API
Функции iommu_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Прикрепляет устройство на шине PCIe к домену IOMMU, ассоциированному с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если IOMMU не задействован, возвращает |
|
Назначение Открепляет устройство на шине PCIe от домена IOMMU, ассоциированного с вызывающим процессом. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если 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 в состояние, при котором системные вызовы Параметры
Возвращаемые значения В случае успеха возвращает |
Ограничения поддержки POSIX
В KasperskyOS ограниченно реализован POSIX с ориентацией на стандарт POSIX.1-2008. Прежде всего ограничения связаны с обеспечением безопасности.
Отсутствует поддержка XSI и опциональной функциональности.
Ограничения затрагивают:
- взаимодействие между процессами;
- взаимодействие между потоками исполнения посредством сигналов;
- асинхронный ввод-вывод;
- использование робастных мьютексов;
- работу с терминалом;
- работу с оболочкой;
- управление дескрипторами файлов;
- использование таймеров;
- получение системных параметров.
Ограничения представлены:
- нереализованными интерфейсами;
- интерфейсами, которые реализованы с отклонениями от стандарта POSIX.1-2008;
- интерфейсами-заглушками, которые не выполняют никаких действий, кроме присвоения переменной
errno
значенияENOSYS
и возвращения значения-1
.
В KasperskyOS сигналы не могут прервать системные вызовы Call()
, Recv()
, Reply()
, которые обеспечивают работу библиотек, реализующих интерфейс POSIX.
Ядро KasperskyOS не посылает сигналы.
Ограничения взаимодействия между процессами
Интерфейс |
Назначение |
Реализация |
Заголовочный файл по стандарту 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):
- handle_api.h;
- notice_api.h;
- task.h, task_api.h;
- cm_api.h, ns_api.h;
- queue.h.
Интерфейсы POSIX нельзя использовать в потоках исполнения, созданных с помощью API thread.h и thread_api.h.
API syscalls.h можно использовать в любых потоках исполнения, созданных с использованием Pthreads или API thread.h и thread_api.h.
В началоПолучение статистических сведений о системе
Библиотеки libkos
и libc
предоставляют API для получения статистических сведений о системе. Эти сведения включают следующие пункты:
- об использовании процессорного времени системой и отдельным процессом;
- об использовании памяти системой и отдельным процессом;
- о процессах и потоках исполнения;
- о файловых системах и сетевых интерфейсах.
Получение статистических сведений о системе через API библиотеки libkos
Библиотека libkos
предоставляет API, который позволяет получить статистические сведения об использовании процессорного времени и памяти, а также о процессах и потоках исполнения. Этот API определен в заголовочном файле sysroot-*-kos/include/coresrv/stat/stat_api.h
из состава KasperskyOS SDK.
API, определенный в заголовочном файле sysroot-*-kos/include/coresrv/stat/stat_api.h
из состава KasperskyOS SDK, включает функции, которые "оборачивают" функцию KnProfilerGetCounters()
, объявленную в заголовочном файле sysroot-*-kos/include/coresrv/profiler/profiler_api.h
из состава KasperskyOS SDK. Эта функция запрашивает значения счетчиков производительности. Поэтому, чтобы получить статистические сведения, нужно собрать решение с версией ядра KasperskyOS, которая поддерживает счетчики производительности (подробнее см. "Библиотека image").
Получение сведений об использовании процессорного времени
Время работы процессоров (вычислительных ядер) отсчитывается с момента запуска ядра KasperskyOS.
Чтобы получить сведения об использовании процессорного времени, нужно использовать функции KnGroupStatGetParam()
, KnTaskStatGetParam()
и KnCpuStatGetParam()
. При этом через параметр param
этих функций нужно передать значения, приведенные в таблице ниже.
Сведения об использовании процессорного времени
Функция |
Значение параметра |
Получаемое значение |
---|---|---|
|
|
Время работы всех процессоров в режиме ядра |
|
|
Время работы всех процессоров в пользовательском режиме |
|
|
Время работы всех процессоров в режиме бездействия |
|
|
Время работы всех процессоров, затраченное на исполнение заданного процесса |
|
|
Время работы всех процессоров, затраченное на исполнение заданного процесса в пользовательском режиме |
|
|
Время работы заданного процессора в режиме бездействия |
|
|
Время работы заданного процессора в пользовательском режиме |
|
|
Время работы заданного процессора в режиме ядра |
Процессорное время, полученное вызовом функции KnGroupStatGetParam()
, KnTaskStatGetParam()
или KnCpuStatGetParam()
, представлено в наносекундах.
Входным параметром функции KnCpuStatGetParam()
является индекс процессора (нумерация начинается с нуля). Чтобы получить общее число процессоров на аппаратной платформе, нужно использовать функцию KnHalGetCpuCount()
, объявленную в заголовочном файле sysroot-*-kos/include/coresrv/hal/hal_api.h
из состава KasperskyOS SDK.
Получение сведений об использовании памяти
Чтобы получить сведения об использовании памяти, нужно использовать функции KnGroupStatGetParam()
и KnTaskStatGetParam()
. При этом через параметр param
этих функций нужно передать значения, приведенные в таблице ниже.
Сведения об использовании памяти
Функция |
Значение параметра |
Получаемое значение |
---|---|---|
|
|
Размер всей установленной физической памяти |
|
|
Размер свободной физической памяти |
|
|
Размер физической памяти с атрибутом "доступ на исполнение" |
|
|
Размер физической памяти, используемой в качестве разделяемой |
|
|
Размер физической памяти, используемой заданным процессом |
|
|
Размер виртуальной памяти заданного процесса |
|
|
Размер виртуальной памяти заданного процесса, отображаемой на разделяемую физическую память |
|
|
Размер таблицы страниц заданного процесса |
Размер памяти, полученный вызовом функции KnGroupStatGetParam()
или KnTaskStatGetParam()
, представляет собой число страниц памяти. Размер страницы памяти составляет 4 КБ для всех аппаратных платформ, поддерживаемых KasperskyOS.
Размер физической памяти, используемой процессом, характеризует только ту память, которая выделена непосредственно для этого процесса. Например, если в память процесса отображен буфер MDL, созданный другим процессом, то размер этого буфера не включается в это значение.
Получение сведений о процессах и потоках исполнения
Помимо сведений об использовании процессорного времени и памяти функции KnGroupStatGetParam()
и KnTaskStatGetParam()
позволяют получить сведения о процессах и потоках исполнения. Для этого через параметр param
этих функций нужно передать значения, приведенные в таблице ниже.
Сведения о процессах и потоках исполнения
Функция |
Значение параметра |
Получаемое значение |
---|---|---|
|
|
Число пользовательских процессов (без учета процесса ядра) |
|
|
Общее число потоков исполнения (включая потоки ядра) |
|
|
Идентификатор родительского процесса заданного процесса (PPID) |
|
|
Приоритет начального потока заданного процесса |
|
|
Состояние заданного процесса (в соответствии с перечислением |
|
|
Размер загруженного в память образа программы, исполняемой в контексте заданного процесса, в байтах |
|
|
Время между запуском ядра и запуском заданного процесса в наносекундах |
|
|
Число дескрипторов, принадлежащих заданному процессу |
|
|
Число потоков исполнения в заданном процессе |
Кроме функций KnGroupStatGetParam()
и KnTaskStatGetParam()
для получения сведений о процессах и потоках исполнения можно использовать следующие функции:
KnTaskStatGetName()
позволяет получить имя заданного процесса.KnTaskStatGetPath()
позволяет получить имя исполняемого файла в ROMFS, из которого запущен заданный процесс.Функцию можно использовать, только если процесс запущен из исполняемого файла в ROMFS. В противном случае результатом вызова функции будет пустая строка.
KnTaskStatGetId()
позволяет получить идентификатор заданного процесса (PID).KnProfilerGetCounters()
позволяет получить значения счетчиков производительности.Например, чтобы получить число потоков ядра и общее число дескрипторов, нужно передать через параметр
names
значенияkl.core.Core.threads
иhandles.total
.
Получение сведений об использовании процессорного времени и памяти каждым процессом
Чтобы получить сведения об использовании процессорного времени и памяти каждым процессом, нужно выполнить следующие действия:
- Получить список процессов вызовом функции
KnGroupStatGetTaskList()
. - Получить число элементов списка процессов вызовом функции
KnTaskStatGetTasksCount()
. - Выполнить в цикле следующие действия:
- Получить элемент списка процессов вызовом функции
KnTaskStatEnumTaskList()
. - Получить имя процесса вызовом функции
KnTaskStatGetName()
.Это требуется, чтобы идентифицировать процесс, для которого будут получены сведения об использовании процессорного времени и памяти.
- Получить сведения об использовании процессорного времени и памяти процессом вызовами функции
KnTaskStatGetParam()
. - Проверить, что процесс не завершился. Если процесс завершился, то отбросить полученные сведения об использовании процессорного времени и памяти этим процессом.
Чтобы проверить, что процесс не завершился, нужно вызвать функцию
KnTaskStatGetParam()
с передачей через параметрparam
значенияTASK_PARAM_STATE
. Должно быть получено значение, отличное отTaskStateTerminated
. - Завершить работу с элементом списка процессов вызовом функции
KnTaskStatCloseTask()
.
- Получить элемент списка процессов вызовом функции
- Завершить работу со списком процессов вызовом функции
KnTaskStatCloseTaskList()
.
Расчет загрузки процессоров
Показателями загрузки процессоров (вычислительных ядер) могут быть следующие значения:
- процент загрузки всех процессоров;
- процент загрузки всех процессоров каждым процессом;
- проценты загрузки каждого процессора.
Расчет этих показателей выполняется для интервала времени, в начале и конце которого были получены сведения об использовании процессорного времени. (Например, может выполняться мониторинг загрузки процессоров с периодическим получением сведений об использовании процессорного времени.) Из значений, полученных в конце интервала, нужно вычесть значения, полученные в начале интервала. То есть для интервала нужно получить следующие приращения:
- TK – время работы всех процессоров в режиме ядра;
- TKi [i=1,2,...,n] – время работы i-го процессора в режиме ядра;
- TU – время работы всех процессоров в пользовательском режиме;
- TUi [i=1,2,...,n] – время работы i-го процессора в пользовательском режиме;
- TIDLE – время работы всех процессоров в режиме бездействия;
- TIDLEi [i=1,2,...,n] – время работы i-го процессора в режиме бездействия;
- Tj [j=1,2,...,m] – процессорное время, затраченное на исполнение j-го процесса.
Процент загрузки всех процессоров рассчитывается так:
(TK+TU)/(TK+TU+TIDLE).
Процент загрузки i-го процессора рассчитывается так:
(TKi+TUi)/(TKi+TUi+TIDLEi).
Процент загрузки всех процессоров j-м процессом рассчитывается так:
Tj/(TK+TU+TIDLE).
В началоПолучение статистических сведений о системе через API библиотеки libc
Библиотека libc
предоставляет API, которые позволяют получить статистические сведения о файловых системах и сетевых интерфейсах, управляемых VFS. Функции этих API приведены в таблице ниже.
Сведения о файловых системах и сетевых интерфейсах
Функция |
Заголовочный файл из состава KasperskyOS SDK |
Получаемые сведения |
---|---|---|
|
|
Сведения о файловой системе, такие как размер блока, число блоков, число свободных блоков |
|
|
Сведения обо всех смонтированных файловых системах, идентичные предоставляемым функцией |
|
|
Сведения о сетевых интерфейсах, такие как имя, IP-адрес, маска подсети |
Компонент MessageBus
Компонент MessageBus
реализует шину сообщений, которая обеспечивает прием, распределение и доставку сообщений между программами, работающими под KasperskyOS. Шина построена по принципу "издатель-подписчик". Использование шины сообщений позволяет избежать создания большого количества IPC-каналов для связывания каждой программы-подписчика с каждой программой-издателем.
Сообщения, передаваемые через шину MessageBus
, не могут содержать данные. Эти сообщения могут использоваться только для уведомления подписчиков о событиях.
Компонент MessageBus
представляет собой дополнительный уровень абстракции над KasperskyOS IPC, который позволяет упростить процесс разработки и развития ваших программ. MessageBus
является отдельной программой, доступ к которой осуществляется через IPC, но при этом разработчикам предоставляется библиотека доступа к MessageBus
, которая позволяет избежать использования IPC-вызовов напрямую.
API библиотеки доступа предоставляет следующие интерфейсы:
IProviderFactory
- Предоставляет фабричные методы для получения доступа к экземплярам остальных интерфейсов;
IProviderControl
- Интерфейс для регистрации и дерегистрации издателя и подписчика в шине;
IProvider (компонент MessageBus)
- Интерфейс для передачи сообщения в шину;
ISubscriber
- Интерфейс обратного вызова для передачи сообщения подписчику;
IWaiter
- Интерфейс ожидания обратного вызова при появлении соответствующего сообщения.
Структура сообщения
Каждое сообщение содержит два параметра:
topic
- Идентификатор темы сообщения;
id
- Дополнительный параметр, специфицирующий сообщение.
Параметры topic
и id
уникальны для каждого сообщения. Интерпретация topic
+id
определяется контрактом между издателем и подписчиком. Например, если изменяются конфигурационные данные, с которыми работают издатель и подписчик, издатель высылает сообщение об изменении данных и id
конкретной записи с новыми данными. Подписчик, пользуясь отличными от MessageBus
механизмами, получает новые данные по ключу id
.
Интерфейс IProviderFactory
Интерфейс IProviderFactory
предоставляет фабричные методы для получения интерфейсов, необходимых для работы с компонентом MessageBus
.
Описание интерфейса IProviderFactory
представлено в файле 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
представлено в файле 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
представлено в файле messagebus/i_messagebus.h
.
Для получение экземпляра интерфейса используется интерфейс IProviderFactory
.
Отправка сообщения в шину
Для оправки сообщения в шину используется метод IProvider::Push()
. Метод принимает идентификатор клиента шины, полученный при регистрации, и идентификатор сообщения. Если очередь сообщений в шине заполнена, то вызов будет отклонен.
i_messagebus.h (фрагмент)
Интерфейсы ISubscriber, IWaiter и ISubscriberRunner
Интерфейсы ISubscriber
, IWaiter
и ISubscriberRunner
предоставляют методы для получения и обработки подписчиком сообщений из шины.
Описания интерфейсов ISubscriber
, IWaiter
и ISubscriberRunner
представлено в файле messagebus/i_subscriber.h
.
Для получение экземпляров интерфейсов IWaiter
и ISubscriberRunner
используется интерфейс IProviderFactory
. Реализация callback-интерфейса ISubscriber
предоставляется приложением-подписчиком.
Получение сообщения из шины
Чтобы перевести подписчика в режим ожидания сообщения от шины, вы можете использовать метод IWaiter::Wait()
или ISubscriberRunner::Run()
. Методы принимают идентификатор клиента шины и указатель на callback-интерфейс ISubscriber
. Если идентификатор клиента не зарегистрирован, то вызов будет отклонен.
Мы не рекомендуем использовать интерфейс IWaiter
, поскольку вызов метода IWaiter::Wait()
является блокирующим.
При получении сообщения из шины будет вызван метод ISubscriber::OnMessage()
. Метод принимает тему и идентификатор сообщения.
i_subscriber.h (фрагмент)
Компонент ExecutionManager
API определен в заголовочных файлах, расположенных в директории sysroot-*-kos/include/component/execution_manager/
из состава SDK.
Сценарий использования компонента ExecutionManager описан в статье "Запуск процесса с помощью KasperskyOS API".
Интерфейс execution_manager_proxy.h
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/kos_ipc/execution_manager_proxy.h
Интерфейс содержит фабричный метод CreateExecutionManager()
для получения указателя на экземпляр интерфейса IExecutionManager
, необходимого для работы с компонентом ExecutionManager.
Пример использования:
client.cpp
Интерфейс IExecutionManager
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_execution_manager.h
Интерфейс IExecutionManager
позволяет получить доступ к указателям на следующие интерфейсы:
IApplicationController
- интерфейс для запуска\остановки процессов;ISystemController
- интерфейс для управления системой.
Пример использования:
client.cpp
Интерфейс IApplicationController
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_application_control.h
Интерфейс IApplicationController
предоставляет следующие методы, позволяющие изменять состояние процесса:
StartEntity(
const std::filesystem::path& runPath,
const StartEntityInfo& info,
StartEntityResultInfo& resInfo
) - метод для запуска процесса.RestartEntity(EntityId endId)
- метод для перезапуска ранее запущенного процесса.ShutdownEntity(EntityId entId)
- метод для отправки процессу сигнала на завершение.StopEntity(EntityId entId)
- метод для немедленной остановки исполнения процесса.
Метод StartEntity()
принимает путь к исполняемому файлу, который нужно запустить, а также структуру с параметрами запуска процесса StartEntityInfo
; а возвращает структуру с результатами запуска процесса StartEntityResultInfo
. Все поля структуры StartEntityInfo
являются опциональными для инициализации.
Остальные методы принимают структуру EntityId
, идентифицирующую запущенный процесс.
Пример использования:
client.cpp
Интерфейс ISystemController
API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_system_control.h
Интерфейс ISystemController
предоставляет следующий метод для управления системой:
StopAllEntities()
- метод останавливает все запущенные процессы; затем завершает процесс ExecutionManager; а затем отправляет в ядро запрос на выключение устройства.
Пример использования:
client.cpp