KasperskyOS Community Edition 1.2

Содержание

[Topic api]

Коды возврата

Общие сведения

В решении на базе KasperskyOS коды возврата функций различных API (например, API библиотек libkos и kdf, драйверов, транспортного кода, прикладного ПО) имеют тип 32-битного знакового целого числа. Этот тип определен в заголовочном файле sysroot-*-kos/include/rtl/retcode.h из состава KasperskyOS SDK так:

typedef __INT32_TYPE__ Retcode;

Множество кодов возврата состоит из кода успеха со значением 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. Описание общих кодов возврата приведено в таблице ниже.

Общие коды возврата

Код возврата

Описание

rcOk (соответствует значению 0)

Функция завершилась успешно.

rcInvalidArgument

Параметр функции некорректен.

rcNotConnected

Нет соединения между клиентской и серверной сторонами взаимодействия.

Например, отсутствует серверный IPC-дескриптор.

rcOutOfMemory

Недостаточно памяти для выполнения операции.

rcBufferTooSmall

Недостаточный размер буфера.

rcInternalError

Функция завершилась с внутренней ошибкой, которая связана с некорректной логикой.

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

rcTransferError

Ошибка отправки IPC-сообщения.

rcReceiveError

Ошибка приема IPC-сообщения.

rcSourceFault

IPC-сообщение не было передано из-за источника IPC-сообщения.

rcTargetFault

IPC-сообщение не было передано из-за приемника IPC-сообщения.

rcIpcInterrupt

IPC прервано другим потоком процесса.

rcRestart

Сигнализирует, что функцию нужно вызвать повторно.

rcFail

Функция завершилась с ошибкой.

rcNoCapability

Операция над ресурсом недоступна.

rcNotReady

Инициализация не выполнена.

rcUnimplemented

Функция не реализована.

rcBufferTooLarge

Большой размер буфера.

rcBusy

Ресурс временно недоступен.

rcResourceNotFound

Ресурс не найден.

rcTimeout

Время ожидания истекло.

rcSecurityDisallow

Операция запрещена механизмами безопасности.

rcFutexWouldBlock

Операция приведет к блокировке.

rcAbort

Операция прервана.

rcInvalidThreadState

В обработчике прерывания вызвана недопустимая функция.

rcAlreadyExists

Множество элементов уже содержит добавляемый элемент.

rcInvalidOperation

Операция не может быть выполнена.

rcHandleRevoked

Права доступа к ресурсу отозваны.

rcQuotaExceeded

Квота на ресурс превышена.

rcDeviceNotFound

Устройство не найдено.

rcOverflow

Произошло переполнение.

rcAlreadyDone

Операция уже выполнена.

Определение кодов ошибок

Чтобы определить код ошибки, разработчику решения на базе KasperskyOS нужно использовать макрос MAKE_RETCODE(), определенный в заголовочном файле sysroot-*-kos/include/rtl/retcode.h из состава KasperskyOS SDK. При этом через параметр customer нужно передать символьную константу RC_CUSTOMER_TRUE.

Пример:

#define LV_EBADREQUEST MAKE_RETCODE(RC_CUSTOMER_TRUE, RC_SPACE_APPS, RC_FACILITY_LogViewer, 5, "Bad request")

Описание ошибки, которое передается через параметр 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, используются для форматированного вывода сведений об ошибке.

В начало
[Topic return_codes]

Библиотека libkos

Библиотека libkos является базовой библиотекой KasperskyOS, предоставляющей набор API, через которые программы и другие библиотеки (например, libc, kdf) используют службы ядра. API, предоставляемые библиотекой libkos, обеспечивают для разработчиков решения следующие возможности:

  • управление процессами, потоками исполнения, виртуальной памятью;
  • управление доступом к ресурсам;
  • осуществление ввода-вывода;
  • создание IPC-каналов;
  • управление электропитанием;
  • получение статистических сведений о системе;
  • другие возможности, поддерживаемые службами ядра.

Этот раздел содержит подробные описания работы с некоторыми интерфейсами библиотеки libkos. Описания остальных интерфейсов вы можете найти в соответствующих им заголовочных файлах.

Заголовочные файлы, определяющие API библиотеки libkos, расположены в следующих директориях:

  • sysroot-*-kos/include/coresrv/
  • sysroot-*-kos/include/kos/

В этом разделе

Управление дескрипторами (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)

В начало
[Topic libkos]

Управление дескрипторами (handle_api.h)

API определен в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.

API предназначен для выполнения операций с дескрипторами. Дескрипторы имеют тип Handle, который определен в заголовочном файле sysroot-*-kos/include/handle/handletype.h из состава KasperskyOS SDK.

Локальность дескрипторов

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

В этом разделе

Маска прав дескриптора

Создание дескрипторов

Передача дескрипторов

Копирование дескрипторов

Разыменование дескрипторов

Отзыв дескрипторов

Закрытие дескрипторов

Получение идентификатора безопасности (SID)

Пример использования OCap

В начало
[Topic handles_manage]

Маска прав дескриптора

Маска прав дескриптора имеет размер 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).

При создании дескриптора пользовательского ресурса маска прав задается пользователем.

При передаче дескриптора маска прав задается пользователем, но передаваемые права доступа не могут быть повышены относительно прав доступа, которые имеет процесс.

В начало
[Topic libkos_handles_rights]

Создание дескрипторов

Создание дескрипторов системных ресурсов

Дескрипторы системных ресурсов создаются при создании этих ресурсов, например, при регистрации прерывания или региона памяти 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

Функция

Сведения о функции

KnHandleCreateUserObject()

Назначение

Создает дескриптор.

Параметры

  • [in] type – тип дескриптора. Фиктивный параметр, который должен принимать значение от константы HANDLE_TYPE_USER_FIRST до константы HANDLE_TYPE_USER_LAST, определенных в заголовочном файле sysroot-*-kos/include/handle/handletype.h из состава KasperskyOS SDK.
  • [in] rights – маска прав дескриптора.
  • [in,optional] context – указатель на данные, которые нужно ассоциировать с дескриптором, или RTL_NULL, если эта ассоциация не требуется.
  • [out] handle – указатель на дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnHandleCreateUserObjectEx()

Назначение

Создает дескриптор.

Параметры

  • [in] type – тип дескриптора. Фиктивный параметр, который должен принимать значение от константы HANDLE_TYPE_USER_FIRST до константы HANDLE_TYPE_USER_LAST, определенных в заголовочном файле sysroot-*-kos/include/handle/handletype.h из состава KasperskyOS SDK.
  • [in] rights – маска прав дескриптора.
  • [in,optional] context – указатель на данные, которые нужно ассоциировать с дескриптором, или RTL_NULL, если эта ассоциация не требуется.
  • [in,optional] ipcChannel – серверный IPC-дескриптор или INVALID_HANDLE, если не требуется создавать callable-дескриптор.
  • [in,optional] riid – идентификатор службы (RIID) или INVALID_RIID, если не требуется создавать callable-дескриптор.
  • [out] handle – указатель на дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnHandleConnect()

Назначение

Создает и связывает между собой клиентский, серверный и слушающий IPC-дескрипторы.

Параметры

  • [in,optional] ls – слушающий дескриптор или INVALID_HANDLE, чтобы создать его.
  • [out,optional] outLs – указатель на слушающий дескриптор. Можно указать RTL_NULL, если через параметр ls задан слушающий дескриптор.
  • [out,optional] outSr – указатель на серверный IPC-дескриптор или RTL_NULL, чтобы не создавать серверный IPC-дескриптор, если через параметр ls задан слушающий дескриптор.
  • [out] outCl – указатель на клиентский IPC-дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnHandleConnectEx()

Назначение

Создает и связывает между собой клиентский, серверный и слушающий IPC-дескрипторы.

Параметры

  • [in] server – дескриптор серверного процесса.
  • [in,optional] srListener – слушающий дескриптор из пространства дескрипторов серверного процесса или INVALID_HANDLE, чтобы создать его.
  • [in] client – дескриптор клиентского процесса.
  • [out,optional] outSrListener – указатель на слушающий дескриптор из пространства дескрипторов серверного процесса. Можно указать RTL_NULL, если через параметр srListener задан слушающий дескриптор.
  • [out,optional] outSrEndpoint – указатель на серверный IPC-дескриптор из пространства дескрипторов серверного процесса или RTL_NULL, чтобы не создавать серверный IPC-дескриптор, если через параметр srListener задан слушающий дескриптор.
  • [out] outClEndpoint – указатель на клиентский IPC-дескриптор из пространства дескрипторов клиентского процесса.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnHandleSecurityConnect()

Назначение

Создает клиентский IPC-дескриптор для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности.

Параметры

  • [out] client – указатель на дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnHandleCreateListener()

Назначение

Создает слушающий дескриптор, не связанный с клиентским и серверным IPC-дескрипторами.

Параметры

  • [out] listener – указатель на слушающий дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_handles_create]

Передача дескрипторов

Общие сведения

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

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

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

Условия для передачи дескрипторов

Чтобы процессы могли передавать дескрипторы между собой, должны выполняться следующие условия:

  1. Между процессами создан IPC-канал.
  2. Политика безопасности решения (security.psl) разрешает взаимодействие классов процессов.
  3. Реализованы интерфейсные методы для передачи дескрипторов.

API task.h позволяет родительскому процессу передавать дескрипторы дочернему процессу, который еще не запущен.

В IDL-описании сигнатуры интерфейсных методов для передачи дескрипторов имеют входные (in) и/или выходные (out) параметры типа Handle или array с элементами типа Handle. Через входные параметры одного метода можно передать до 255 дескрипторов. Столько же дескрипторов можно получить через выходные параметры.

Пример IDL-описания, где заданы сигнатуры интерфейсных методов для передачи дескрипторов:

package IpcTransfer interface { PublishResource1(in Handle handle, out UInt32 result); PublishResource7(in Handle handle1, in Handle handle2, in Handle handle3, in Handle handle4, in Handle handle5, in Handle handle6, in Handle handle7, out UInt32 result); OpenResource(in UInt32 ID, out Handle handle); }

Для каждого параметра типа 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() нужно использовать только при разыменовании дескрипторов.

Сценарии передачи дескрипторов

Сценарий передачи дескрипторов от клиента к серверу включает следующие шаги:

  1. Клиент упаковывает дескрипторы и маски прав дескрипторов в поля структуры IPC-запросов *_req типа nk_handle_desc_t.
  2. Клиент вызывает интерфейсный метод для передачи дескрипторов серверу. При вызове этого метода выполняется системный вызов Call().
  3. Сервер получает IPC-запрос, выполняя системный вызов Recv().
  4. Диспетчер на стороне сервера вызывает метод, который соответствует IPC-запросу. Этот метод извлекает дескрипторы и маски прав дескрипторов из полей структуры IPC-запросов *_req типа nk_handle_desc_t.

Сценарий передачи дескрипторов от сервера к клиенту включает следующие шаги:

  1. Клиент вызывает интерфейсный метод для получения дескрипторов от сервера. При вызове этого метода выполняется системный вызов Call().
  2. Сервер получает IPC-запрос, выполняя системный вызов Recv().
  3. Диспетчер на стороне сервера вызывает метод, который соответствует IPC-запросу. Этот метод упаковывает дескрипторы, маски прав дескрипторов и дескрипторы объектов контекстов передачи ресурсов в поля структуры IPC-ответов *_res типа nk_handle_desc_t.
  4. Сервер отвечает на IPC-запрос, выполняя системный вызов Reply().
  5. На стороне клиента интерфейсный метод возвращает управление. После этого клиент извлекает дескрипторы и маски прав дескрипторов из полей структуры IPC-ответов *_res типа nk_handle_desc_t.

Если передающий процесс задает в передаваемой маске прав дескриптора больше прав доступа, чем задано для передаваемого дескриптора (владельцем которого он является), то передача не осуществляется. В этом случае выполнение системного вызова Call() передающим или принимающим клиентом, а также выполнение системного вызова Reply() передающим сервером завершается с ошибкой rcSecurityDisallow.

Сведения о функциях API

Функции handle_api.h

Функция

Сведения о функции

KnHandleCreateBadge()

Назначение

Создает объект контекста передачи ресурса и настраивает механизм уведомлений для контроля жизненного цикла этого объекта.

Параметры

  • [in] notice – идентификатор приемника уведомлений.
  • [in] eventId – идентификатор записи вида "ресурс – маска событий" в приемнике уведомлений.
  • [in,optional] context – указатель на данные, которые нужно ассоциировать с передачей дескриптора, или RTL_NULL, если эта ассоциация не требуется.
  • [out] handle – указатель на дескриптор объекта контекста передачи ресурса.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

Приемник уведомлений настраивается на получение уведомлений о событиях, которые соответствуют флагам маски событий EVENT_OBJECT_DESTROYED и EVENT_BADGE_CLOSED.

В начало
[Topic libkos_handles_transfer]

Копирование дескрипторов

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

Чтобы выполнить копирование дескриптора, нужно вызвать функцию KnHandleCopy(). При этом в маске прав дескриптора должен быть установлен флаг OCAP_HANDLE_COPY.

Сведения о функциях API приведены в таблице ниже.

Функции handle_api.h

Функция

Сведения о функции

KnHandleCopy()

Назначение

Копирует дескриптор.

В результате копирования вызывающий процесс получает потомка дескриптора.

Параметры

  • [in] inHandle – оригинальный дескриптор.
  • [in] newRightsMask – маска прав потомка дескриптора.
  • [in,optional] copyBadge – дескриптор объекта контекста передачи ресурса или INVALID_HANDLE, если не требуется ассоциировать копирование дескриптора с этим объектом.
  • [out] outHandle – указатель на потомка дескриптора.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_handle_copy]

Разыменование дескрипторов

Разыменование дескриптора – это операция, при которой клиент отправляет серверу дескриптор, а сервер получает указатель на контекст передачи ресурса, маску прав отправленного дескриптора и предка отправленного клиентом дескриптора, которым сервер уже владеет. Разыменование выполняется, когда потребитель ресурсов, вызывая методы работы с ресурсом (например, чтение, запись, закрытие доступа), передает поставщику ресурсов дескриптор, который был получен от этого поставщика ресурсов при открытии доступа к ресурсу.

Разыменование дескрипторов требует выполнения тех же условий и использует те же механизмы и типы данных, что и передача дескрипторов. Сценарий разыменования дескриптора включает следующие шаги:

  1. Клиент упаковывает дескриптор в поле структуры IPC-запросов *_req типа nk_handle_desc_t.
  2. Клиент вызывает интерфейсный метод для отправки дескриптора серверу с целью выполнения действий с ресурсом. При вызове этого метода выполняется системный вызов Call().
  3. Сервер принимает IPC-запрос, выполнив системный вызов Recv().
  4. Диспетчер на стороне сервера вызывает метод, который соответствует IPC-запросу. Этот метод проверяет, что выполнена именно операция разыменования, а не передача дескриптора. Затем вызванный метод опционально проверяет, что права доступа разыменованного дескриптора (который отправлен клиентом) разрешают запрашиваемые действия с ресурсом, и извлекает указатель на контекст передачи ресурса из поля структуры запросов *_req типа nk_handle_desc_t.

Для выполнения проверок сервер использует функции nk_is_handle_dereferenced() и nk_get_badge_op(), которые объявлены в заголовочном файле sysroot-*-kos/include/nk/types.h из состава KasperskyOS SDK.

types.h (фрагмент)

/** * Функция возвращает отличное от нуля значение, если * дескриптор в транспортном контейнере дескриптора * desc получен в результате операции разыменования * дескриптора. Функция возвращает нуль, если дескриптор * в транспортном контейнере дескриптора desc получен * в результате операции передачи дескриптора. */ static inline nk_bool_t nk_is_handle_dereferenced(const nk_handle_desc_t *desc) /** * Функция извлекает указатель на контекст передачи ресурса * badge из транспортного контейнера дескриптора desc, * если в маске прав, которая помещена в транспортном * контейнере дескриптора desc, установлены флаги operation. * В случае успеха функция возвращает NK_EOK, иначе возвращает код ошибки. */ static inline nk_err_t nk_get_badge_op(const nk_handle_desc_t *desc, nk_rights_t operation, nk_badge_t *badge)

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

В начало
[Topic libkos_handles_dereference]

Отзыв дескрипторов

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

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

Чтобы отозвать потомков дескриптора, нужно вызвать функцию KnHandleRevoke() или KnHandleRevokeSubtree(). Функция KnHandleRevokeSubtree() использует объект контекста передачи ресурса, который создается при передаче дескрипторов.

Если каждый из дескрипторов системного ресурса во всех процессах, которые владеют этими дескрипторами, будет закрыт (см. "Закрытие дескрипторов") или отозван, то этот системный ресурс будет удален.

Сведения о функциях API приведены в таблице ниже.

Функции handle_api.h

Функция

Сведения о функции

KnHandleRevoke()

Назначение

Закрывает дескриптор и отзывает его потомков.

Параметры

  • [in] handle – дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnHandleRevokeSubtree()

Назначение

Отзывает дескрипторы, которые образуют поддерево наследования заданного дескриптора.

Параметры

  • [in] handle – дескриптор. Дескрипторы, образующие поддерево наследования этого дескриптора, отзываются.
  • [in] badge – дескриптор, идентифицирующий объект контекста передачи ресурса, который определяет поддерево наследования дескрипторов для отзыва. Корневым узлом этого поддерева является дескриптор, который порожден передачей или копированием дескриптора, заданного через параметр handle, в ассоциации с объектом контекста передачи ресурса.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_handles_revoke]

Закрытие дескрипторов

Процесс может закрыть дескрипторы, которыми он владеет. Закрытие дескриптора прекращает ассоциацию идентификатора с ресурсом, тем самым освобождая идентификатор. Закрытие дескриптора не делает недействительными его предков и потомков (в отличие от отзыва дескриптора, который делает недействительными его потомков). То есть через предков и потомков закрытого дескриптора обеспечивается доступ к ресурсу, который они идентифицируют. Также закрытие дескриптора не нарушает целостность дерева наследования дескрипторов, которое относится к ресурсу, идентифицируемому этим дескриптором. Место закрытого дескриптора занимает его предок. То есть предок закрытого дескриптора становится непосредственным предком потомков закрытого дескриптора.

Чтобы закрыть дескриптор, нужно вызвать функцию KnHandleClose().

Если каждый из дескрипторов системного ресурса во всех процессах, которые владеют этими дескрипторами, будет отозван (см. "Отзыв дескрипторов") или закрыт, то этот системный ресурс будет удален.

Сведения о функциях API приведены в таблице ниже.

Функции handle_api.h

Функция

Сведения о функции

KnHandleClose()

Назначение

Закрывает дескриптор.

Параметры

  • [in] handle – дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_handles_delete]

Получение идентификатора безопасности (SID)

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

Чтобы получить идентификатор безопасности по дескриптору, нужно вызвать функцию KnHandleGetSidByHandle(). При этом в маске прав дескриптора должен быть установлен флаг OCAP_HANDLE_GET_SID.

Сведения о функциях API приведены в таблице ниже.

Функции handle_api.h

Функция

Сведения о функции

KnHandleGetSidByHandle()

Назначение

Позволяет получить идентификатор безопасности (SID) по дескриптору.

Параметры

  • [in] handle – дескриптор.
  • [out] sid – указатель на идентификатор безопасности (SID).

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_handle_get_sid]

Пример использования OCap

В этом примере приведен сценарий использования OCap, в котором поставщик ресурсов предоставляет следующие методы доступа к своим ресурсам:

  • OpenResource() – открытие доступа к ресурсу;
  • UseResource() – использование ресурса;
  • CloseResource() – закрытие доступа к ресурсу.

Потребитель ресурсов использует эти методы.

IDL-описание:

package SimpleOCap interface { OpenResource(in UInt32 ID, out Handle handle); UseResource(in Handle handle, in UInt8 param, out UInt8 result); CloseResource(in Handle handle); }

Сценарий включает следующие шаги:

  1. Поставщик ресурсов создает контекст пользовательского ресурса и вызывает функцию KnHandleCreateUserObject() для создания дескриптора ресурса. Поставщик ресурсов сохраняет дескриптор ресурса в контексте пользовательского ресурса.
  2. Потребитель ресурсов вызывает метод открытия доступа к ресурсу OpenResource().
    1. Поставщик ресурсов создает контекст передачи ресурса и вызывает функцию KnHandleCreateBadge() для создания объекта контекста передачи ресурса и настройки приемника уведомлений на получение уведомлений о закрытии и удалении объекта контекста передачи ресурса. Поставщик ресурсов сохраняет дескриптор объекта контекста передачи ресурса и указатель на контекст пользовательского ресурса в контексте передачи ресурса.
    2. Поставщик ресурсов, используя макрос nk_handle_desc(), упаковывает дескриптор ресурса, маску прав дескриптора и указатель на объект контекста передачи ресурса в транспортный контейнер дескриптора.
    3. Выполняется передача дескриптора от поставщика ресурсов к потребителю ресурсов, в результате которой потребитель ресурсов получает потомка дескриптора, которым владеет поставщик ресурсов.
    4. Вызов метода OpenResource() завершается успешно. Потребитель ресурсов извлекает дескриптор и маску прав дескриптора из транспортного контейнера дескриптора функциями nk_get_handle() и nk_get_rights() соответственно. Маска прав дескриптора не требуется потребителю ресурсов для обращения к ресурсу и передается, чтобы потребитель ресурсов мог узнать свои права доступа к ресурсу.
  3. Потребитель ресурсов вызывает метод использования ресурса UseResource().
    1. Дескриптор, который получен от поставщика ресурсов на шаге 2, используется в качестве параметра метода UseResource(). Перед вызовом этого метода потребитель ресурсов упаковывает дескриптор в транспортный контейнер дескриптора макросом nk_handle_desc().
    2. Выполняется разыменование дескриптора, в результате которого поставщик ресурсов получает указатель на контекст передачи ресурса.
    3. Поставщик ресурсов, используя функцию nk_is_handle_dereferenced(), проверяет, что выполнена операция разыменования, а не передача дескриптора.
    4. Поставщик ресурсов проверяет, что права доступа разыменованного дескриптора (который отправлен потребителем ресурсов) разрешают запрашиваемую операцию с ресурсом, и извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора. Для этого поставщик ресурсов использует функцию nk_get_badge_op(), которая извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора, если в полученной маске прав установлены флаги, соответствующие запрашиваемой операции.
    5. Поставщик ресурсов, используя контекст передачи ресурса и контекст пользовательского ресурса, выполняет запрашиваемую потребителем ресурсов операцию с ресурсом. Затем поставщик ресурсов отправляет потребителю ресурсов результат выполнения этой операции.
    6. Вызов метода UseResource() завершается успешно. Потребитель ресурсов получает результат выполнения операции с ресурсом.
  4. Потребитель ресурсов вызывает метод закрытия доступа к ресурсу CloseResource().
    1. Дескриптор, который получен от поставщика ресурсов на шаге 2, используется в качестве параметра метода CloseResource(). Перед вызовом этого метода потребитель ресурсов упаковывает дескриптор в транспортный контейнер дескриптора макросом nk_handle_desc(). После вызова метода CloseResource() потребитель ресурсов закрывает дескриптор функцией KnHandleClose().
    2. Выполняется разыменование дескриптора, в результате которого поставщик ресурсов получает указатель на контекст передачи ресурса.
    3. Поставщик ресурсов, используя функцию nk_is_handle_dereferenced(), проверяет, что выполнена операция разыменования, а не передача дескриптора.
    4. Поставщик ресурсов, используя функцию nk_get_badge(), извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора.
    5. Поставщик ресурсов отзывает дескриптор, которым владеет потребитель ресурсов, функцией KnHandleRevokeSubtree(). В качестве параметров этой функции используются дескриптор ресурса, которым владеет поставщик ресурсов, и дескриптор объекта контекста передачи ресурса. Поставщик ресурсов получает доступ к этим дескрипторам через указатель на контекст передачи ресурса. (Технически не требуется отзывать дескриптор, которым владеет потребитель ресурсов, так как потребитель ресурсов его уже закрыл. Но поставщик ресурсов не может быть уверен в том, что потребитель ресурсов закрыл дескриптор, поэтому выполняется отзыв).
    6. Вызов метода CloseResource() завершается успешно.
  5. Поставщик ресурсов освобождает память, которая была выделена для контекста передачи ресурса и контекста пользовательского ресурса.
    1. Поставщик ресурсов вызовом функции KnNoticeGetEvent() получает уведомление, что объект контекста передачи ресурса закрыт, и закрывает дескриптор объекта контекста передачи ресурса функцией KnHandleClose().
    2. Поставщик ресурсов вызовом функции KnNoticeGetEvent() получает уведомление, что объект контекста передачи ресурса удален, и освобождает память, которая была выделена для контекста передачи ресурса.
    3. Поставщик ресурсов закрывает дескриптор ресурса функцией KnHandleClose() и освобождает память, которая была выделена для контекста пользовательского ресурса.
В начало
[Topic libkos_handles_simple_scenario]

Выделение и освобождение памяти (alloc.h)

API определен в заголовочном файле sysroot-*-kos/include/kos/alloc.h из состава KasperskyOS SDK.

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

Сведения о функциях API приведены в таблице ниже.

Функции alloc.h

Функция

Сведения о функции

KosMemAllocEx()

Назначение

Выделяет память.

Параметры

  • [in] size – размер выделяемой памяти в байтах.
  • [in] align – значение, задающее выравнивание выделяемой памяти. Должно быть степенью двойки. Адрес выделяемой памяти может быть невыравненным (align=1) или выравненным (align=2,4,...,2^N) на границу 2^N-байтовой последовательности (например, двухбайтовой, четырехбайтовой). При выравнивании адреса размер выделяемой памяти может быть увеличен до ближайшего значения, кратного 2^N.
  • [in] zeroed – значение, задающее инициализацию выделяемой памяти (1 – инициализировать нулями, 0 – не инициализировать).

Возвращаемые значения

В случае успеха возвращает указатель на выделенную память, иначе возвращает RTL_NULL.

KosMemAlloc()

Назначение

Выделяет память.

Параметры

  • [in] size – размер выделяемой памяти в байтах.

Возвращаемые значения

В случае успеха возвращает указатель на выделенную памяти, иначе возвращает RTL_NULL.

KosMemZalloc()

Назначение

Выделяет память и инициализирует ее нулями.

Параметры

  • [in] size – размер выделяемой памяти в байтах.

Возвращаемые значения

В случае успеха возвращает указатель на выделенную память, иначе возвращает RTL_NULL.

KosMemFree()

Назначение

Освобождает память.

Параметры

  • [in] ptr – указатель на освобождаемую память.

Возвращаемые значения

Нет.

KosMemGetSize()

Назначение

Позволяет получить фактический размер выделенной памяти.

Фактический размер выделенной памяти превышает запрошенный, так как включает размер служебных данных, а также может быть увеличен в результате выравнивания при вызове функции KosMemAllocEx().

Параметры

  • [in] ptr – указатель на выделенную память.

Возвращаемые значения

Фактический размер выделенной памяти в байтах.

KosMemGetOrigSize()

Назначение

Позволяет получить размер памяти, который был запрошен при ее выделении.

Фактический размер выделенной памяти превышает запрошенный, так как включает размер служебных данных, а также может быть увеличен в результате выравнивания при вызове функции KosMemAllocEx().

Параметры

  • [in] ptr – указатель на выделенную память.

Возвращаемые значения

Размер памяти, который был запрошен при ее выделении, в байтах.

В начало
[Topic libkos_alloc_api]

Использование DMA (dma.h)

API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/dma.h из состава KasperskyOS SDK.

API предназначен для организации обмена данными между устройствами и оперативной памятью в режиме прямого доступа к памяти (англ. Direct Memory Access, DMA), при котором процессор не используется.

Сведения о функциях API приведены в таблице ниже.

Использование API

Типовой сценарий использования API включает следующие шаги:

  1. Создание буфера 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.

  2. Отображение буфера DMA на память процессов.

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

    Чтобы зарезервировать регион виртуальной памяти и отобразить на него буфер DMA, нужно вызвать функцию KnIoDmaMap().

    Дескриптор, полученный при вызове функции KnIoDmaMap(), нельзя передать другому процессу через IPC.

  3. Открытие доступа к буферу DMA для устройства вызовом функции KnIoDmaBegin().

    Вызов функции KnIoDmaBegin() необходим, чтобы создать объект ядра, содержащий адреса и размеры блоков, из которых состоит буфер DMA. Эти сведения необходимы устройству, чтобы использовать буфер DMA. Устройство может работать как с физическими, так и с виртуальными адресами в зависимости от того, задействован ли IOMMU. Если IOMMU задействован, объект содержит виртуальные адреса блоков. В противном случае объект содержит физические адреса блоков.

    Дескриптор, полученный при вызове функции KnIoDmaBegin(), нельзя передать другому процессу через IPC.

  4. Получение сведений о буфере 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, нужно выполнить следующие шаги:

  1. Освободить регионы виртуальной памяти, зарезервированные при вызовах функции KnIoDmaMap().

    Чтобы выполнить этот шаг, нужно использовать функцию KnHandleClose(), указывая дескрипторы, которые были получены при вызовах функции KnIoDmaMap(). (Функция KnHandleClose() объявлена в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.)

    Этот шаг нужно выполнить для всех процессов, на память которых отображен буфер DMA.

  2. Удалить объект ядра, созданный вызовом функции KnIoDmaBegin().

    Чтобы выполнить этот шаг, нужно вызвать функцию KnHandleClose(), указав дескриптор, который был получен при вызове функции KnIoDmaBegin().

  3. Закрыть или отозвать каждый дескриптор буфера DMA во всех процессах, которые владеют этими дескрипторами.

    Чтобы выполнить этот шаг, нужно использовать функцию KnHandleClose() и/или KnHandleRevoke(), которые объявлены в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.

Сведения о функциях API

Функции dma.h

Функция

Сведения о функции

KnIoDmaCreate()

Назначение

Создает буфер DMA.

Параметры

  • [in] order – параметр, задающий минимальное число страниц памяти (2^order) в блоке.
  • [in] size – размер буфера DMA в байтах. Должен быть кратен размеру страницы памяти.
  • [in] flags – флаги, задающие параметры буфера DMA. Тип параметра и флаги определены в заголовочном файле sysroot-*-kos/include/io/io_dma.h из состава KasperskyOS SDK.
  • [out] outRid – указатель на дескриптор буфера DMA.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

В параметре flags можно указать следующие флаги:

  • DMA_DIR_TO_DEVICE – устройство имеет доступ к буферу DMA на чтение.
  • DMA_DIR_FROM_DEVICE – устройство имеет доступ к буферу DMA на запись.
  • DMA_DIR_BIDIR – устройство имеет доступ к буферу DMA на чтение и запись.
  • DMA_ZONE_DMA32 – для создания буфера DMA разрешено использовать только первые четыре гигабайта физической памяти.
  • DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE, DMA_RULE_CACHE_VOLATILE, DMA_RULE_CACHE_FIXED – управление кешированием.

KnIoDmaCreateContinuous()

Назначение

Создает буфер DMA, состоящий из одного блока.

Параметры

  • [in] size – размер буфера DMA в байтах. Должен быть кратен размеру страницы памяти.
  • [in] flags – флаги, задающие параметры буфера DMA. Тип параметра и флаги определены в заголовочном файле sysroot-*-kos/include/io/io_dma.h из состава KasperskyOS SDK.
  • [out] outRid – указатель на дескриптор буфера DMA.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

В параметре flags можно указать следующие флаги:

  • DMA_DIR_TO_DEVICE – устройство имеет доступ к буферу DMA на чтение.
  • DMA_DIR_FROM_DEVICE – устройство имеет доступ к буферу DMA на запись.
  • DMA_DIR_BIDIR – устройство имеет доступ к буферу DMA на чтение и запись.
  • DMA_ZONE_DMA32 – для создания буфера DMA разрешено использовать только первые четыре гигабайта физической памяти.
  • DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE, DMA_RULE_CACHE_VOLATILE, DMA_RULE_CACHE_FIXED – управление кешированием.

KnIoDmaMap()

Назначение

Резервирует регион виртуальной памяти и отображает на него буфер DMA.

Параметры

  • [in] rid – дескриптор буфера DMA.
  • [in] offset – смещение в буфере DMA, с которого нужно начать отображение, в байтах. Должно быть кратно размеру страницы памяти.
  • [in] length – размер части буфера DMA, которую нужно отобразить, в байтах. Должен быть кратен размеру страницы памяти. Также должно выполняться условие: length<=размер буфера DMA-offset.
  • [in,optional] hint – странично выравненный желаемый базовый адрес региона виртуальной памяти или 0, чтобы этот адрес был выбран автоматически.
  • [in] vmflags – флаги, задающие права доступа к региону виртуальной памяти. Флаги определены в заголовочном файле sysroot-*-kos/include/vmm/flags.h из состава KasperskyOS SDK.
  • [out] addr – базовый адрес региона виртуальной памяти.
  • [out] handle – указатель на дескриптор, который используется для освобождения региона виртуальной памяти.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

В параметре vmflags можно указать следующие флаги:

  • VMM_FLAG_READ – доступ на чтение.
  • VMM_FLAG_WRITE – доступ на запись.

KnIoDmaModify()

Назначение

Изменяет параметры кеширования буфера DMA.

Параметры

  • [in] rid – дескриптор буфера DMA.
  • [in] newAttr – флаги, задающие параметры кеширования буфера DMA. Флаги определены в заголовочном файле sysroot-*-kos/include/io/io_dma.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

Функцию можно использовать, если выполняются следующие условия:

  1. Буфер DMA был создан с указанием флага DMA_RULE_CACHE_VOLATILE.
  2. Буфер DMA не отображен на виртуальную память.
  3. Предыдущий вызов функции (если он был) был выполнен с указанием флага DMA_RULE_CACHE_VOLATILE.

В параметре newAttr можно указать следующие флаги:

  • DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE, DMA_RULE_CACHE_VOLATILE – управление кешированием.

KnIoDmaGetInfo()

Назначение

Позволяет получить сведения о буфере DMA.

Сведения включают адреса и размеры блоков.

Параметры

  • [in] rid – дескриптор буфера DMA.
  • [out] outInfo – указатель на адрес объекта, содержащего сведения о буфере DMA. Тип объекта определен в заголовочном файле sysroot-*-kos/include/io/io_dma.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoDmaContinuousGetDmaAddr()

Назначение

Позволяет получить адрес блока для буфера DMA, состоящего из одного блока.

Параметры

  • [in] rid – дескриптор буфера DMA.
  • [out] addr – адрес блока.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoDmaBegin()

Назначение

Открывает доступ к буферу DMA для устройства.

Параметры

  • [in] rid – дескриптор буфера DMA.
  • [out] handle – указатель на дескриптор объекта ядра, содержащего адреса и размеры блоков, которые необходимы устройству, чтобы использовать буфер DMA.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_dma_api]

Управление обработкой прерываний (irq.h)

API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/irq.h из состава KasperskyOS SDK.

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

Аппаратное прерывание возникает при обращении устройства к контроллеру прерываний. Это обращение может осуществляться через линию аппаратного прерывания между устройством и контроллером прерываний или через память MMIO. Во втором случае устройство выполняет запись в память MMIO, вызывая прерывание MSI (англ. Message Signaled Interrupt).

В настоящее время функции для управления обработкой прерываний MSI не реализованы.

Каждой линии аппаратного прерывания соответствует одно прерывание с уникальным номером.

Сведения о функциях API приведены в таблице ниже.

Использование API

Чтобы связать прерывание с его обработчиком, нужно выполнить следующие шаги:

  1. Регистрация прерывания вызовом функции KnRegisterIrq().

    Одно прерывание можно зарегистрировать несколько раз в одном или нескольких процессах.

    Дескриптор прерывания можно передать другому процессу через IPC.

  2. Привязка потока исполнения к прерыванию вызовом функции 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-сообщения данные для информационного обмена между ядром и потоком исполнения, привязанным к прерыванию.

Типовой цикл обработки прерывания включает следующие шаги:

  1. Добавление в IPC-сообщение, которое будет отправлено ядру, сведений об успехе или неуспехе обработки прерывания вызовом функции IoSetIrqAnswer().
  2. Отправка IPC-сообщения ядру и получение IPC-сообщения от ядра.

    Чтобы выполнить этот шаг, нужно вызвать функции Call(). В параметре handle требуется указать дескриптор, полученный при вызове функции KnIoAttachIrq(). Через параметр msgOut необходимо задать IPC-сообщение, которое будет отправлено ядру, а через параметр msgIn необходимо задать IPC-сообщение, которое будет получено от ядра.

  3. Извлечение запроса из IPC-сообщения, полученного от ядра, вызовом функции IoGetIrqRequest().
  4. Обработка прерывания или отвязывание от прерывания в зависимости от запроса.

    Если запрос требует выполнить отвязывание от прерывания, то нужно выйти из цикла обработки прерывания и вызвать функцию KnThreadDetachIrq().

Дерегистрация прерывания

Чтобы дерегистрировать прерывание, нужно выполнить следующие шаги:

  1. Выполнить отвязывание потока исполнения от прерывания.

    Чтобы выполнить этот шаг, нужно вызвать функцию KnThreadDetachIrq().

  2. Закрыть дескриптор, полученный при вызове функции KnIoAttachIrq().

    Чтобы выполнить этот шаг, нужно вызвать функцию KnHandleClose(). (Функция KnHandleClose() объявлена в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.)

  3. Закрыть или отозвать каждый дескриптор прерывания во всех процессах, которые владеют этими дескрипторами.

    Чтобы выполнить этот шаг, нужно использовать функцию KnHandleClose() и/или KnHandleRevoke(), которые объявлены в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.

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

Сведения о функциях API

Функции irq.h

Функция

Сведения о функции

KnRegisterIrq()

Назначение

Регистрирует прерывание.

Параметры

  • [in] irq – номер прерывания.
  • [out] outRid – указатель на дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoAttachIrq()

Назначение

Привязывает вызывающий поток исполнения к прерыванию.

Параметры

  • [in] rid – дескриптор прерывания.
  • [in] flags – флаги, задающие параметры прерывания. Флаги определены в заголовочных файлах sysroot-*-kos/include/io/io_irq.h и sysroot-*-kos/include/hal/irqmode.h из состава KasperskyOS SDK.
  • [out] handle – указатель на клиентский IPC-дескриптор, который используется обработчиком прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

В параметре flags можно указать следующие флаги:

  • IRQ_LEVEL_LOW – прерывание возникает при низком уровне сигнала.
  • IRQ_LEVEL_HIGH – прерывание возникает при высоком уровне сигнала.
  • IRQ_EDGE_RAISE – прерывание возникает при повышении уровня сигнала.
  • IRQ_EDGE_FALL – прерывание возникает при снижении уровня сигнала.
  • IRQ_PRIO_LOW – прерывание имеет низкий приоритет.
  • IRQ_PRIO_NORMAL – прерывание имеет средний приоритет.
  • IRQ_PRIO_HIGH – прерывание имеет высокий приоритет.
  • IRQ_PRIO_RT – прерывание имеет наивысший приоритет.

KnIoDetachIrq()

Назначение

Отправляет потоку исполнения запрос, в результате выполнения которого поток должен выполнить отвязывание от прерывания.

Параметры

  • [in] rid – дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoEnableIrq()

Назначение

Разрешает (демаскирует) прерывание.

Параметры

  • [in] rid – дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoDisableIrq()

Назначение

Запрещает (маскирует) прерывание.

Параметры

  • [in] rid – дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_irq_api]

Инициализация 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:

Сведения о функциях API приведены в таблицах ниже.

В этом разделе приведены примеры использования API. В этих примерах программы, которые являются серверами, имеют следующую формальную спецификацию:

FsDriver.edl

entity FsDriver components { operationsComp : Operations }

Operations.cdl

component Operations endpoints { fileOperations : FileIface }

FileIface.idl

package FileIface interface { Open(in array<UInt8, 1024> path); Read(out sequence<UInt8, 2048> content); }

Инициализация IPC-транспорта для межпроцессного взаимодействия

Чтобы инициализировать IPC-транспорт для взаимодействия с другими процессами, нужно вызвать функцию NkKosTransport_Init() или NkKosTransportSync_Init(), объявленные в заголовочном файле transport-kos.h.

Пример использования функции NkKosTransport_Init() на стороне клиента:

int main(int argc, const char *argv[]) { /* Объявить структуру с параметрами IPC-транспорта */ NkKosTransport driver_transport; /* Объявить прокси-объект. (Тип прокси-объекта является автоматически * сгенерированным транспортным кодом.) */ struct FileIface_proxy file_operations_proxy; /* Объявить структуры для сохранения фиксированной части IPC-запроса и * IPC-ответа для метода службы. (Типы структур являются автоматически * сгенерированным транспортным кодом.) */ struct FileIface_Open_req req; struct FileIface_Open_res res; /* Получить клиентский IPC-дескриптор и идентификатор службы */ Handle driver_handle; rtl_uint32_t file_operations_riid; if (KnCmConnect("FsDriver", "operationsComp.fileOperations", INFINITE_TIMEOUT, &driver_handle, &file_operations_riid) == rcOk) { /* Инициализировать структуру с параметрами IPC-транспорта */ NkKosTransport_Init(&driver_transport, driver_handle, NK_NULL, 0); /* Инициализировать прокси-объект. (Метод инициализации прокси-объекта * является автоматически сгенерированным транспортным кодом.) */ FileIface_proxy_init(&file_operations_proxy, &driver_transport.base, (nk_iid_t) file_operations_riid); } ... /* Вызвать метод службы. (Метод является автоматически * сгенерированным транспортным кодом.) */ strncpy(req.path, "/example/file/path", sizeof(req.path)); if (FileIface_Open(file_operations_proxy.base, &req, NULL, &res, NULL) != NK_EOK) { ... } ... }

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

Пример использования функции NkKosTransport_Init() на стороне сервера:

int main(int argc, const char *argv[]) { ... /* Объявить структуру с параметрами IPC-транспорта */ NkKosTransport transport; /* Получить слушающий дескриптор. (Идентификатор службы * FsDriver_operationsComp_fileOperations_iid является * автоматически сгенерированным транспортным кодом.) */ Handle handle; char client[32]; char endpoint[32]; Retcode rc = KnCmListen(RTL_NULL, INFINITE_TIMEOUT, client, endpoint); if (rc == rcOk) rc = KnCmAccept(client, endpoint, FsDriver_operationsComp_fileOperations_iid, INVALID_HANDLE, &handle); ... /* Инициализировать структуру с параметрами IPC-транспорта */ NkKosTransport_Init(&transport, handle, NK_NULL, 0); ... /* Цикл обработки IPC-запросов */ do { ... /* Получить IPC-запрос */ rc = nk_transport_recv(&transport.base, ...); if (rc == NK_EOK) { /* Обработать IPC-запрос вызовом диспетчера. (Диспетчер * является автоматически сгенерированным транспортным * кодом.) */ rc = FsDriver_entity_dispatch(...); if (rc == NK_EOK) { /* Отправить IPC-ответ */ rc = nk_transport_reply(&transport.base, ...); } } } while (rc == NK_EOK) return EXIT_SUCCESS; }

Если сервер обрабатывает 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-запроса на сервере включает следующие стадии:

  1. Получение IPC-запроса.
  2. Обработка IPC-запроса.
  3. Отправка 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():

/* Функция реализует метод службы. */ static nk_err_t Open_impl(...) { ... } /* Функция реализует метод службы. */ static nk_err_t Read_impl(...) { ... } /* Функция инициализирует указатели на функции, реализующие методы службы. * (Эти указатели используются диспетчером для вызова функций, реализующих * методы службы. Типы структур являются автоматически сгенерированным * транспортным кодом.) */ static struct FileIface *CreateFileOperations() { static const struct FileIface_ops ops = { .Open = Open_impl, .Read = Read_impl }; static struct FileIface impl = { .ops = &ops }; return &impl; } int main(int argc, const char *argv[]) { ... /* Объявить структуру, которая требуется функции * NkKosDoDispatch() для использования транспортного кода. */ NkKosDispatchInfo info; /* Объявить стабы. (Типы стабов являются автоматически сгенерированным * транспортным кодом. */ struct Operations_component component; struct FsDriver_entity entity; /* Получить слушающий дескриптор */ Handle handle = ServiceLocatorRegister("driver_connection", NULL, 0, &iid); assert(handle != INVALID_HANDLE); /* Инициализировать стабы. (Методы инициализации стабов являются * автоматически сгенерированным транспортным кодом. Функция * CreateFileOperations() реализована разработчиком решения на * базе KasperskyOS, чтобы инициализировать * указатели на функции, реализующие методы службы.) */ Operations_component_init(&component, CreateFileOperations()); FsDriver_entity_init(&entity, &component); /* Инициализировать структуру, которая требуется функции * NkKosDoDispatch() для использования транспортного кода. */ info = NK_TASK_DISPATCH_INFO_INITIALIZER(FsDriver, entity); /* Запустить цикл обработки IPC-запросов */ NkKosDoDispatch(handle, info); return EXIT_SUCCESS; }

Пример использования функции NkKosTransport_Dispatch():

/* Функция реализует метод службы. */ static nk_err_t Open_impl(...) { ... } /* Функция реализует метод службы. */ static nk_err_t Read_impl(...) { ... } /* Функция инициализирует указатели на функции, реализующие методы службы. * (Эти указатели используются диспетчером для вызова функций, реализующих * методы службы. Типы структур являются автоматически сгенерированным * транспортным кодом.) */ static struct FileIface *CreateFileOperations() { static const struct FileIface_ops ops = { .Open = Open_impl, .Read = Read_impl }; static struct FileIface impl = { .ops = &ops }; return &impl; } int main(int argc, const char *argv[]) { ... /* Объявить структуру с параметрами IPC-транспорта */ NkKosTransport transport; /* Объявить стабы. (Типы стабов являются автоматически сгенерированным * транспортным кодом. */ struct Operations_component component; struct FsDriver_entity entity; /* Объявить объединения фиксированной части IPC-запросов и * IPC-ответов. (Типы объединений являются автоматически сгенерированным * транспортным кодом.) */ union FsDriver_entity_req req; union FsDriver_entity_res res; /* Объявить массив для арены IPC-ответов. (Размер массива является * автоматически сгенерированным транспортным кодом.) */ char res_buffer[FsDriver_entity_res_arena_size]; /* Объявить и инициализировать дескриптор арены IPC-ответов. * (Тип дескриптора и макрос его инициализации определены в заголовочном файле * sysroot-*-kos/include/nk/arena.h из состава KasperskyOS SDK.) */ struct nk_arena res_arena = NK_ARENA_INITIALIZER(res_buffer, res_buffer + sizeof(res_buffer)); /* Получить слушающий дескриптор */ Handle handle = ServiceLocatorRegister("driver_connection", NULL, 0, &iid); assert(handle != INVALID_HANDLE); /* Инициализировать структуру с параметрами IPC-транспорта */ NkKosTransport_Init(&transport, handle, NK_NULL, 0); /* Инициализировать стабы. (Методы инициализации стабов являются * автоматически сгенерированным транспортным кодом. Функция * CreateFileOperations() реализована разработчиком решения на * базе KasperskyOS, чтобы инициализировать * указатели на функции, реализующие методы службы.) */ Operations_component_init(&component, CreateFileOperations()); FsDriver_entity_init(&entity, &component); /* Запустить цикл обработки IPC-запросов. (Диспетчер FsDriver_entity_dispatch * является автоматически сгенерированным транспортным кодом.) */ NkKosTransport_Dispatch(&transport.base, FsDriver_entity_dispatch, &entity, &req, sizeof(FsDriver_entity_req), RTL_NULL, &res, &res_arena); return EXIT_SUCCESS; }

Копирование данных в арену IPC-сообщений

Чтобы скопировать строку в арену IPC-сообщений, нужно вызвать функцию NkKosCopyStringToArena(), объявленную в заголовочном файле transport-kos.h. Эта функция резервирует участок арены и копирует строку в этот участок.

Пример использования функции NkKosCopyStringToArena():

static nk_err_t Read_impl(struct FileIface *self, const struct FileIface_Read_req *req, const struct nk_arena* req_arena, struct FileIface_Read_res* res, struct nk_arena* res_arena) { /* Скопировать строку в арену IPC-ответов */ if (NkKosCopyStringToArena(&res_arena, &res.content, "CONTENT OF THE FILE") != rcOk) { ... } return NK_EOK; }

Сведения о функциях API

Функции transport-kos.h

Функция

Сведения о функции

NkKosTransport_Init()

Назначение

Инициализирует IPC-транспорт.

Параметры

  • [out] transport – указатель на структуру с параметрами IPC-транспорта.
  • [in] handle – клиентский или серверный IPC-дескриптор.
  • [in] view – параметр, который должен иметь значение NK_NULL.
  • [in] size – параметр, который должен иметь значение 0.

Возвращаемые значения

Нет.

NkKosTransportSync_Init()

Назначение

Инициализирует IPC-транспорт с поддержкой прерывания системных вызовов Call() и/или Recv().

Параметры

  • [out] transport – указатель на структуру с параметрами IPC-транспорта.
  • [in] handle – клиентский или серверный IPC-дескриптор.
  • [in,optional] callSyncHandle – дескриптор объекта синхронизации IPC для системных вызовов Call() или INVALID_HANDLE, если прерывание системных вызовов Call() не требуется.
  • [in,optional] recvSyncHandle – дескриптор объекта синхронизации IPC для системных вызовов Recv() или INVALID_HANDLE, если прерывание системных вызовов Recv() не требуется.

Возвращаемые значения

Нет.

NkKosSetTransportTimeouts()

Назначение

Задает для IPC-транспорта максимальное время блокировки системных вызовов Call() и Recv().

Параметры

  • [out] transport – указатель на структуру с параметрами IPC-транспорта.
  • [in] recvTimeout – максимальное время блокировки системных вызовов Recv() в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время блокировки.
  • [in] callTimeout – максимальное время блокировки системных вызовов Call() в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время блокировки.

Возвращаемые значения

Нет.

NkKosTransport_Dispatch()

Назначение

Запускает цикл обработки IPC-запросов.

Параметры

  • [in] transport – указатель на поле base структуры с параметрами IPC-транспорта.
  • [in] dispatch – указатель на диспетчер (dispatch-метод) из транспортного кода. Диспетчер имеет имя <имя класса процессов>_entity_dispatch.
  • [in] impl – указатель на стаб, который представляет собой структуру с типом <имя класса процессов>_entity из транспортного кода. Через эту структуру диспетчер получает указатели на функции, реализующие методы служб.
  • [out] req – указатель на объединение с типом <имя класса процессов>_entity_req из транспортного кода. Это объединение предназначено для сохранения фиксированной части IPC-запросов для любых методов служб, предоставляемых сервером.
  • [in] req_size – максимальный размер фиксированной части IPC-запросов в байтах. Определяется как sizeof(<имя класса процессов>_entity_req), где <имя класса процессов>_entity_req является типом из транспортного кода.
  • [in,out,optional] req_arena – указатель на дескриптор арены IPC-запросов или RTL_NULL, если арена IPC-запросов не используется. Тип дескриптора определен в заголовочном файле sysroot-*-kos/include/nk/arena.h из состава KasperskyOS SDK.
  • [out] res – указатель на объединение с типом <имя класса процессов>_entity_res из транспортного кода. Это объединение предназначено для сохранения фиксированной части IPC-ответов для любых методов служб, предоставляемых сервером.
  • [in,out,optional] res_arena – указатель на дескриптор арены IPC-ответов или RTL_NULL, если арена IPC-ответов не используется. Тип дескриптора определен в заголовочном файле sysroot-*-kos/include/nk/arena.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае неуспеха возвращает код ошибки.

NkKosCopyStringToArena()

Назначение

Резервирует участок арены и копирует строку в этот участок.

Параметры

  • [in,out] arena – указатель на дескриптор арены. Тип дескриптора определен в заголовочном файле sysroot-*-kos/include/nk/arena.h из состава KasperskyOS SDK.
  • [out] field – указатель на дескриптор участка арены, куда скопирована строка. Тип дескриптора определен в заголовочном файле sysroot-*-kos/include/nk/types.h.
  • [in] src – указатель на строку для копирования в арену IPC-сообщений.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Функции transport-kos-dispatch.h

Функция

Сведения о функции

NkKosDoDispatch()

Назначение

Запускает цикл обработки IPC-запросов.

Параметры

  • [in] h – серверный IPC-дескриптор.
  • [in] info – указатель на структуру, содержащую данные, которые требуются функции для использования транспортного кода (включая имена типов, размеры фиксированной части и арены IPC-сообщений).

Возвращаемые значения

Нет.

В начало
[Topic libkos_ipc_transport_api]

Инициализация 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

entity Verifier security Approve

Approve.idl

package Approve interface { Check(in UInt32 port); }

Фрагмент описания политики в примере:

security.psl

... security src=Verifier, method=Check { assert (message.port > 80) } ...

Использование API

Чтобы инициализировать IPC-транспорт для обращения к модулю безопасности, нужно вызвать функцию NkKosSecurityTransport_Init().

Пример использования функции NkKosSecurityTransport_Init():

int main(void) { /* Объявить структуру с параметрами IPC-транспорта для обращения к * модулю безопасности */ NkKosSecurityTransport security_transport; /* Объявить прокси-объект. (Тип прокси-объекта является автоматически * сгенерированным транспортным кодом.) */ struct Approve_proxy security_proxy; /* Объявить структуры для сохранения фиксированной части IPC-запроса и IPC-ответа для * метода интерфейса безопасности. (Типы структур являются автоматически сгенерированным * транспортным кодом.) */ struct Approve_Check_req security_req; struct Approve_Check_res security_res; /* Инициализировать структуру с параметрами IPC-транспорта для обращения к * модулю безопасности */ if (NkKosSecurityTransport_Init(&security_transport, NK_NULL, 0) == NK_EOK) { /* Инициализировать прокси-объект. (Метод инициализации прокси-объекта и * идентификатор интерфейса безопасности Verifier_securityIid * являются автоматически сгенерированным транспортным кодом.) */ Approve_proxy_init(&security_proxy, &security_transport.base, Verifier_securityIid); } ... /* Вызвать метод интерфейса безопасности. (Метод является автоматически сгенерированным * транспортным кодом. Метод не передает через параметр security_res никакие данные. * Указать этот параметр нужно только потому, что этого требует реализация метода.) */ security_req.port = 80; nk_err_t result = Approve_Check(&security_proxy.base, &security_req, NULL, &security_res, NULL); if (result == NK_EOK) fprintf(stderr, "Granted"); if (result == NK_EPERM) fprintf(stderr, "Denied"); else fprintf(stderr, "Error"); return EXIT_SUCCESS; }

Если процессу требуется использовать несколько интерфейсов безопасности, то нужно инициализировать столько же прокси-объектов, указав один и тот же IPC-транспорт и уникальные идентификаторы интерфейсов безопасности.

Сведения о функциях API

Функции transport-kos-security.h

Функция

Сведения о функции

NkKosSecurityTransport_Init()

Назначение

Инициализирует IPC-транспорт для обращения к модулю безопасности Kaspersky Security Module через интерфейс безопасности.

Параметры

  • [out] transport – указатель на структуру с параметрами IPC-транспорта для обращения к модулю безопасности.
  • [in] view – параметр, который должен иметь значение NK_NULL.
  • [in] size – параметр, который должен иметь значение 0.

Возвращаемые значения

В случае успеха возвращает NK_EOK, иначе возвращает код ошибки.

В начало
[Topic libkos_ipc_security_transport_api]

Генерация случайных чисел (random_api.h)

API определен в заголовочном файле sysroot-*-kos/include/kos/random/random_api.h из состава KasperskyOS SDK.

API позволяет генерировать случайные числа, а также включает функции, которые можно использовать, чтобы обеспечить высокую энтропию (высокий уровень непредсказуемости) начального значения генератора случайных чисел. Начальное значение генератора случайных чисел (англ. seed) определяет последовательность генерируемых случайных чисел. То есть после установки одного и того же начального значения генератор создает одинаковые последовательности случайных чисел. (Энтропия таких чисел полностью определяется энтропией начального значения, поэтому точнее их называть не случайными, а псевдослучайными.)

Генератор случайных чисел одного процесса не зависит от генераторов случайных чисел других процессов.

Сведения о функциях API приведены в таблице ниже.

Использование API

Чтобы сгенерировать последовательность случайных байтовых значений, нужно вызвать функцию KosRandomGenerate() или KosRandomGenerateEx().

Пример использования функции KosRandomGenerate():

size_t random_number; if (KosRandomGenerate(sizeof random_number, &random_number) == rcOk) { ... }

Функция KosRandomGenerateEx() позволяет получить уровень качества сгенерированных случайных значений через выходной параметр quality. Уровень качества может быть высоким или низким. Высококачественными считаются случайные значения, которые сгенерированы при выполнении всех следующих условий:

  1. На момент изменения начального значения генератора случайных чисел зарегистрирован хотя бы один источник энтропии, и успешно получены данные из всех зарегистрированных источников энтропии.

    Чтобы зарегистрировать источник энтропии, нужно вызвать функцию KosRandomRegisterSrc(). Через параметр callback эта функция принимает указатель на callback-функцию следующего типа:

    typedef Retcode (*KosRandomSeedMethod)(void *context, rtl_size_t size, void *output);

    Эта callback-функция должна, используя параметры context, получить данные размером size байт из источника энтропии и записать их в буфер output. Если функция возвращает rcOk, то считается, что данные из источника энтропии были получены успешно. Источником энтропии может быть, например, оцифрованный сигнал какого-либо датчика или аппаратный генератор случайных чисел.

    Чтобы дерегистрировать источник энтропии, нужно вызвать функцию KosRandomUnregisterSrc().

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

    Если уровень качества низкий, то сделать его высоким без инициализации генератора случайных чисел нельзя.

    Чтобы инициализировать генератор случайных чисел, нужно вызвать функцию KosRandomInitSeed(). Энтропию данных, передаваемых через параметр seed, должен гарантировать вызывающий процесс.

  3. Счетчик случайных байтовых значений, которые сгенерированы после изменения начального значения генератора случайных чисел с выполнением условия 1, не превышает заданный в системе лимит.
  4. Счетчик времени, которое прошло после изменения начального значения генератора случайных чисел с выполнением условия 1, не превышает заданный в системе лимит.

Если хотя бы одно из этих условий не выполняется, сгенерированные случайные значения считаются низкокачественными.

При запуске процесса начальное значение генератора случайных чисел задается системой автоматически. Затем начальное значение генератора случайных чисел изменяется в следующих случаях:

  • Генерация последовательности случайных значений.

    Каждый успешный вызов функции KosRandomGenerateEx() с параметром size больше нуля и каждый успешный вызов функции KosRandomGenerate() изменяют начальное значение генератора случайных чисел, но не каждое такое изменение выполняется с получением данных из зарегистрированных источников энтропии. Зарегистрированные источники энтропии используются только при нарушении условия 3 или 4. При этом, если зарегистрирован хотя бы один источник энтропии, то сбрасывается счетчик времени изменения начального значения генератора случайных чисел. А если данные из хотя бы одного источника энтропии получены успешно, то также сбрасывается счетчик сгенерированных случайных байтовых значений.

    Уровень качества может измениться с высокого на низкий.

  • Инициализация генератора случайных чисел.

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

    Уровень качества может измениться с высокого на низкий и наоборот.

  • Регистрация источника энтропии.

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

    Уровень качества не может измениться.

Возможный сценарий генерации случайных значений высокого качества включает следующие шаги:

  1. Зарегистрировать хотя бы один источник энтропии вызовом функции KosRandomRegisterSrc().
  2. Сгенерировать последовательность случайных значений вызовом функции KosRandomGenerateEx().
  3. Проверить уровень качества случайных значений.

    Если уровень качества низкий, инициализировать генератор случайных чисел вызовом функции KosRandomInitSeed() и перейти к шагу 2.

    Если уровень качестве высокий, перейти к шагу 4.

  4. Использовать случайные значения.

Чтобы получить уровень качества без генерации случайных значений, нужно вызвать функцию KosRandomGenerateEx() со значениями 0 и RTL_NULL в параметрах size и output соответственно.

Сведения о функциях API

Функции random_api.h

Функция

Сведения о функции

KosRandomInitSeed()

Назначение

Инициализирует генератор случайных чисел.

Параметры

  • [in] seed – указатель на байтовый массив, который используется, чтобы изменить начальное значение генератора случайных чисел. Массив должен иметь размер 32 байта.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosRandomGenerate()

Назначение

Генерирует последовательность случайных байтовых значений.

Параметры

  • [in] size – размер буфера для сохранения последовательности (в байтах).
  • [out] output – указатель на буфер для сохранения последовательности.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosRandomGenerateEx()

Назначение

Генерирует последовательность случайных байтовых значений.

Параметры

  • [in] size – размер буфера для сохранения последовательности (в байтах).
  • [out] output – указатель на буфер для сохранения последовательности.
  • [out] quality – указатель на булевое значение, которое истинно, если сгенерированные случайные значения имеют высокое качество, и ложно, если сгенерированные случайные значения имеют низкое качество.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosRandomRegisterSrc()

Назначение

Регистрирует источник энтропии.

Параметры

  • [in] callback – указатель на функцию, которая позволяет получить данные из источника энтропии для изменения начального значения генератора случайных чисел.
  • [in,optional] context – указатель на параметры, передаваемые функции, заданной через параметр callback, или RTL_NULL, если параметров нет.
  • [in] size – размер данных (в байтах), которые нужно получить из источника энтропии при вызове функции, заданной через параметр callback. Должен быть не менее 32 байт.
  • [out] handle – адрес указателя, используемого для дерегистрации источника энтропии.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosRandomUnregisterSrc()

Назначение

Дерегистрирует источник энтропии.

Параметры

  • [in] handle – указатель, который получен при регистрации источника энтропии.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_random_api]

Получение и изменение значений времени (time_api.h)

API определен в заголовочном файле sysroot-*-kos/include/coresrv/time/time_api.h из состава KasperskyOS SDK.

Основные возможности API:

  • получать и изменять системное время;
  • получать монотонное время, отсчитанное с момента запуска ядра KasperskyOS;
  • получать разрешение источников системного и монотонного времени.

Сведения о функциях API приведены в таблице ниже.

Функции time_api.h

Функция

Сведения о функции

KnGetSystemTimeRes()

Назначение

Позволяет получить разрешение источника системного времени.

Параметры

  • [out] res – указатель на структуру, содержащую в поле nsec разрешение источника системного времени в наносекундах. Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnSetSystemTime()

Назначение

Задает системное время.

Параметры

  • [in] time – указатель на структуру, содержащую следующие сведения: в поле sec – число секунд, прошедших с 1 января 1970 года; в поле nsec – число наносекунд, прошедших с момента, заданного в поле sec. Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnGetSystemTime()

Назначение

Позволяет получить системное время.

Параметры

  • [out] time – указатель на структуру, содержащую следующие сведения: в поле sec – число секунд, прошедших с 1 января 1970 года; в поле nsec – число наносекунд, прошедших с момента, заданного в поле sec. Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnGetUpTimeRes()

Назначение

Позволяет получить разрешение источника монотонного времени, отсчитываемого с момента запуска ядра KasperskyOS.

Параметры

  • [out] res – указатель на структуру, содержащую в поле nsec разрешение источника монотонного времени, отсчитываемого с момента запуска ядра KasperskyOS, в наносекундах. Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnGetUpTime()

Назначение

Позволяет получить монотонное время, отсчитанное с момента запуска ядра KasperskyOS.

Параметры

  • [out] time – указатель на структуру, содержащую следующие сведения: в поле sec – число секунд, прошедших с момента запуска ядра KasperskyOS; в поле nsec – число наносекунд, прошедших с момента, заданного в поле sec. Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnGetRtcTime()

Назначение

Позволяет получить системное время.

Параметры

  • [out] rt – указатель на структуру, содержащую следующие сведения о времени: год, месяц, день, часы, минуты, секунды, миллисекунды. Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnGetMSecSinceStart()

Назначение

Позволяет получить монотонное время, отсчитанное с момента запуска ядра KasperskyOS.

Параметры

Нет.

Возвращаемые значения

Монотонное время, отсчитанное с момента запуска ядра KasperskyOS, в миллисекундах.

KnAdjSystemTime()

Назначение

Запускает постепенную корректировку системного времени.

Параметры

  • [in] adj – указатель на структуру, содержащую интервал времени, на который нужно скорректировать системное время (sec*10^9+nsec наносекунд) или RTL_NULL, если не требуется запускать корректировку, а нужно только получить сведения о ранее запущенной корректировке (через параметр prev). Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.
  • [in] slew – скорость корректировки системного времени (микросекунд в секунду).
  • [out] prev – указатель на структуру, содержащую интервал времени, отражающий, на какое значение оставалось (или остается в случае указания RTL_NULL в параметре adj) скорректировать системное время, чтобы уже запущенная постепенная корректировка была полностью завершена (sec*10^9+nsec наносекунд). Тип структуры определен в заголовочном файле sysroot-*-kos/include/rtl/rtc.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

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

В начало
[Topic libkos_time_api]

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

Типовой сценарий получения уведомлений о событиях, происходящих с ресурсами, включает следующие шаги:

  1. Создание приемника уведомлений (объекта ядра KasperskyOS, в котором накапливаются уведомления) вызовом функции KnNoticeCreate().
  2. Добавление в приемник уведомлений записей вида "ресурс – маска событий", чтобы настроить его на получение уведомлений о событиях, которые происходят с интересующими ресурсами.

    Чтобы добавить запись вида "ресурс – маска событий" в приемник уведомлений, нужно вызвать функцию KnNoticeSubscribeToObject(). (В маске прав дескриптора ресурса, указанного в параметре object, должен быть флаг OCAP_HANDLE_GET_EVENT.) Для одного и того же ресурса можно добавить несколько записей вида "ресурс – маска событий", при этом не требуется, чтобы идентификаторы этих записей были уникальными. Отслеживаемые события для каждой записи вида "ресурс – маска событий" нужно задать маской событий, которая может соответствовать одному или нескольким событиям.

    Добавленные в приемник уведомлений записи вида "ресурс – маска событий" можно полностью или частично удалить, чтобы этот приемник не получал уведомления, соответствующие этим записям. Чтобы удалить из приемника уведомлений все записи вида "ресурс – маска событий", нужно вызвать функцию KnNoticeDropAndWake(). Чтобы удалить из приемника уведомлений записи вида "ресурс – маска событий", относящиеся к одному ресурсу, нужно вызвать функцию KnNoticeUnsubscribeFromObject(). Чтобы удалить из приемника уведомлений записи вида "ресурс – маска событий" с конкретным идентификатором, нужно вызвать функцию KnNoticeUnsubscribeFromEvent().

    Записи вида "ресурс – маска событий" можно добавлять в приемник уведомлений и удалять из него на протяжении всего жизненного цикла этого приемника уведомлений.

  3. Извлечение уведомлений из приемника с использованием функции KnNoticeGetEvent().

    При вызове функции KnNoticeGetEvent() можно задать время ожидания появления уведомлений в приемнике. Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновят свое исполнение при появлении уведомлений, даже если эти уведомления соответствуют записям вида "ресурс – маска событий", добавленным после начала ожидания.

    Потоки, заблокированные в ожидании появления уведомлений в приемнике, возобновят свое исполнение, если из этого приемника будут удалены все записи вида "ресурс – маска событий" вызовом функции KnNoticeDropAndWake(). Если после вызова функции KnNoticeDropAndWake() добавить в приемник уведомлений хотя бы одну запись вида "ресурс – маска событий", то потоки исполнения, получающие уведомления из этого приемника, будут снова заблокированы при вызове функции KnNoticeGetEvent() на заданное время ожидания при отсутствии уведомлений. Если все записи вида "ресурс – маска событий" удалены из приемника уведомлений с использованием функции KnNoticeUnsubscribeFromObject() и/или функции KnNoticeUnsubscribeFromEvent(), то исполнение потоков, ожидающих появления уведомлений в этом приемнике, не возобновляется до истечения времени ожидания.

  4. Удаление приемника уведомлений вызовом функции 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

Функция

Сведения о функции

KnNoticeCreate()

Назначение

Создает приемник уведомлений.

Параметры

  • [out] notice – указатель на идентификатор приемника уведомлений.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnNoticeSubscribeToObject()

Назначение

Добавляет запись вида "ресурс – маска событий" в приемник уведомлений, чтобы он получал уведомления о событиях, которые происходят с заданным ресурсом и соответствуют заданной маске событий.

Параметры

  • [in] notice – идентификатор приемника уведомлений.
  • [in] object – дескриптор ресурса.
  • [in] evMask – маска событий.
  • [in] evId – идентификатор записи вида "ресурс – маска событий".

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnNoticeGetEvent()

Назначение

Извлекает уведомления из приемника.

Параметры

  • [in] notice – идентификатор приемника уведомлений.
  • [in] msec – время ожидания появления уведомлений в приемнике в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.
  • [in] countMax – максимальное число уведомлений, извлекаемое за один вызов функции.
  • [out] events – указатель на набор уведомлений, которые представляют собой структуры, содержащие идентификатор записи вида "ресурс – маска событий" и маску событий, произошедших с ресурсом.
  • [out] count – число извлеченных уведомлений.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если время ожидания появления уведомлений в приемники истекло, возвращает rcTimeout.

Если ожидание появления уведомлений в приемнике прервано вызовом функции KnNoticeRelease() или KnNoticeDropAndWake(), возвращает rcResourceNotFound.

KnNoticeUnsubscribeFromObject()

Назначение

Удаляет записи вида "ресурс – маска событий", соответствующие заданному ресурсу, из приемника уведомлений, чтобы он не получал уведомления о событиях, соответствующих этим записям.

Параметры

  • [in] notice – идентификатор приемника уведомлений.
  • [in] object – дескриптор ресурса.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

Уведомления, соответствующие удаленным записям вида "ресурс – маска событий", будут удалены из приемника.

KnNoticeUnsubscribeFromEvent()

Назначение

Удаляет записи вида "ресурс – маска событий" с заданным идентификатором из приемника уведомлений, чтобы он не получал уведомления о событиях, соответствующих этим записям.

Параметры

  • [in] notice – идентификатор приемника уведомлений.
  • [in] evId – идентификатор записи вида "ресурс – маска событий".

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

Уведомления, соответствующие удаленным записям вида "ресурс – маска событий", будут удалены из приемника.

KnNoticeDropAndWake()

Назначение

Удаляет все записи вида "ресурс – маска событий" из заданного приемника уведомлений и возобновляет исполнение всех потоков, ожидающих появления уведомлений в заданном приемнике.

Параметры

  • [in] notice – идентификатор приемника уведомлений.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnNoticeRelease()

Назначение

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

Параметры

  • [in] notice – идентификатор приемника уведомлений.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnNoticeSetObjectEvent()

Назначение

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

Параметры

  • [in] object – дескриптор пользовательского ресурса.
  • [in] evMask – маска событий, о которых требуется сигнализировать.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_notice_api]

Динамическое создание 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-канала на стороне сервера включает следующие шаги:

  1. Подключиться к серверу имен вызовом функции NsCreate().
  2. Опубликовать предоставляемые службы на сервере имен, используя функцию NsPublishService().

    Чтобы отменить публикацию службы, нужно вызвать функцию NsUnPublishService().

  3. Получить запрос клиента на создание IPC-канала вызовом функции KnCmListen().

    Функция KnCmListen() позволяет получить первый запрос в очереди, но при этом не удаляет этот запрос, а помещает в конец очереди. Если в очереди всего один запрос, то вызов функции KnCmListen() несколько раз подряд дает один и тот же результат. Запрос удаляется из очереди при вызове функции KnCmAccept() или KnCmDrop().

  4. Принять запрос клиента на создание 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-канала на стороне клиента включает следующие шаги:

  1. Подключиться к серверу имен вызовом функции NsCreate().
  2. Найти сервер, предоставляющий требуемую службу, используя функцию NsEnumServices().

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

  3. Выполнить запрос на создание IPC-канала с требуемым сервером вызовом функции KnCmConnect().

К серверу имен можно подключить несколько клиентов и серверов. Каждый клиент и сервер может создать несколько подключений к серверу имен. Сервер может отменить публикацию службы, выполненную другим сервером.

Удаление динамически созданных IPC-каналов

Динамически созданный IPC-канал будет удален при закрытии его клиентского и серверного IPC-дескрипторов.

Сведения о функциях API

Функции ns_api.h

Функция

Сведения о функции

NsCreate()

Назначение

Создает подключение к серверу имен.

Параметры

  • [in,optional] name – указатель на имя процесса сервера имен или RTL_NULL, чтобы задать имя по умолчанию (соответствует значению макроса NS_SERVER_NAME).
  • [in] msecs – время ожидания создания подключения к серверу имен в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.
  • [out] ns – указатель на идентификатор подключения к серверу имен.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

NsPublishService()

Назначение

Публикует службу на сервере имен.

Параметры

  • [in] ns – идентификатор подключения к серверу имен.
  • [in] type – указатель на имя интерфейса службы.
  • [in,optional] server – указатель на имя сервера, предоставляющего службу, или RTL_NULL, чтобы использовать имя вызывающего процесса.
  • [in] service – указатель на квалифицированное имя службы.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

NsUnPublishService()

Назначение

Отменяет публикацию службы на сервере имен.

Параметры

  • [in] ns – идентификатор подключения к серверу имен.
  • [in] type – указатель на имя интерфейса службы.
  • [in,optional] server – указатель на имя сервера, предоставляющего службу, или RTL_NULL, чтобы использовать имя вызывающего процесса.
  • [in] service – указатель на квалифицированное имя службы.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

NsEnumServices()

Назначение

Перечисляет службы, опубликованные на сервере имен.

Параметры

  • [in] ns – идентификатор подключения к серверу имен.
  • [in] type – указатель на имя интерфейса служб.
  • [in] index – индекс для перечисления служб. Нумерация начинается с нуля.
  • [out] server – указатель на буфер для имени сервера, предоставляющего службу.
  • [in] serverSize – размер буфера для имени сервера, предоставляющего службу, в байтах.
  • [out] service – указатель на буфер для квалифицированного имени службы.
  • [in] serviceSize – размер буфера для квалифицированного имени службы в байтах.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Функции cm_api.h

Функция

Сведения о функции

KnCmConnect()

Назначение

Выполняет запрос на создание IPC-канала с сервером для использования заданной службы.

Параметры

  • [in] server – указатель на имя сервера.
  • [in] service – указатель на квалифицированное имя службы.
  • [in] msecs – время ожидания выполнения запроса в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.
  • [out] handle – указатель на клиентский IPC-дескриптор.
  • [out] rsid – указатель на идентификатор службы (RIID).

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnCmListen()

Назначение

Позволяет получить запрос клиента на создание IPC-канала для использования службы.

Параметры

  • [in] filter – фиктивный параметр, который должен иметь значение RTL_NULL.
  • [in] msecs – время ожидания появления запроса клиента в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.
  • [out] client – указатель на имя клиента.
  • [out] service – указатель на квалифицированное имя службы.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnCmDrop()

Назначение

Отклоняет запрос клиента на создание IPC-канала для использования заданной службы.

Параметры

  • [in] client – указатель на имя клиента.
  • [in] service – указатель на квалифицированное имя службы.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnCmAccept()

Назначение

Принимает запрос клиента на создание IPC-канала для использования заданной службы.

Параметры

  • [in] client – указатель на имя клиента.
  • [in] service – указатель на квалифицированное имя службы.
  • [in] rsid – идентификатор службы (RIID).
  • [in,optional] listener – слушающий дескриптор или INVALID_HANDLE, чтобы создать его.
  • [out] handle – указатель на серверный IPC-дескриптор.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_cm_ns_api]

Использование примитивов синхронизации (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 для работы с событиями включает следующие шаги:

  1. Инициализация события вызовом функции KosEventInit().
  2. Использование события потоками исполнения:
    • Ожидание перехода события из несигнального состояния в сигнальное вызовом функции KosEventWait() или KosEventWaitTimeout() (на стороне уведомляемых потоков исполнения).
    • Изменение состояния события вызовами функций KosEventSet() и KosEventReset() (на стороне уведомляющих потоков исполнения).

Сведения о функциях API для работы с событиями приведены в таблице ниже.

Функции event.h

Функция

Сведения о функции

KosEventInit()

Назначение

Инициализирует событие.

После инициализации событие находится в несигнальном состоянии.

Параметры

  • [out] event – указатель на событие. Тип события определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosEventSet()

Назначение

Устанавливает событие в сигнальное состояние.

Параметры

  • [out] event – указатель на событие. Тип события определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosEventReset()

Назначение

Устанавливает событие в несигнальное состояние.

Параметры

  • [out] event – указатель на событие. Тип события определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosEventWait()

Назначение

Ожидает перехода события из несигнального состояния в сигнальное сколь угодно долго.

Параметры

  • [in,out] event – указатель на событие. Тип события определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] reset – значение, которое задает, нужно ли установить событие в несигнальное состояние после завершения ожидания (rtl_true – да, rtl_false – нет). Тип параметра определен в заголовочном файле sysroot-*-kos/include/rtl/stdbool.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosEventWaitTimeout()

Назначение

Ожидает перехода события из несигнального состояния в сигнальное не дольше заданного времени.

Параметры

  • [in,out] event – указатель на событие. Тип события определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] reset – значение, которое задает, нужно ли установить событие в несигнальное состояние после завершения ожидания (rtl_true – да, rtl_false – нет). Тип параметра определен в заголовочном файле sysroot-*-kos/include/rtl/stdbool.h из состава KasperskyOS SDK.
  • [in] mdelay – время ожидания в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если время ожидания истекло, возвращает rcTimeout.

Мьютексы

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

Типовой сценарий использования API для работы с мьютексами включает следующие шаги:

  1. Инициализация мьютекса вызовом функции KosMutexInit() или KosMutexInitEx().
  2. Использование мьютекса потоками исполнения:
    1. Захват мьютекса вызовом функции KosMutexTryLock(), KosMutexLock() или KosMutexLockTimeout().
    2. Освобождение мьютекса вызовом функции KosMutexUnlock().

Сведения о функциях API для работы с мьютексами приведены в таблице ниже.

Функции mutex.h

Функция

Сведения о функции

KosMutexInit()

Назначение

Инициализирует мьютекс, который не является рекурсивным.

Параметры

  • [out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosMutexInitEx()

Назначение

Инициализирует мьютекс.

Параметры

  • [out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] recursive – значение, которое задает, должен ли мьютекс быть рекурсивным (1 – да, 0 – нет).

Возвращаемые значения

Нет.

KosMutexTryLock()

Назначение

Захватывает мьютекс.

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

Параметры

  • [in,out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если мьютекс уже захвачен, возвращает rcBusy.

KosMutexLock()

Назначение

Захватывает мьютекс.

Если мьютекс уже захвачен, ожидает его освобождения сколь угодно долго.

Параметры

  • [in,out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosMutexUnlock()

Назначение

Освобождает мьютекс.

Параметры

  • [in,out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosMutexLockTimeout()

Назначение

Захватывает мьютекс.

Если мьютекс уже захвачен, ожидает его освобождения не дольше заданного времени.

Параметры

  • [in,out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] mdelay – время ожидания в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если время ожидания истекло, возвращает rcTimeout.

Блокировки чтения-записи

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

Типовой сценарий использования API для работы с блокировками чтения-записи включает следующие шаги:

  1. Инициализация блокировки чтения-записи вызовом функции KosRWLockInit().
  2. Использование блокировки чтения-записи потоками исполнения:
    1. Захват блокировки чтения-записи для записи (вызовом функции KosRWLockWrite() или KosRWLockTryWrite()) или для чтения (вызовом функции KosRWLockRead() или KosRWLockTryRead()).
    2. Освобождение блокировки-чтения вызовом функции KosRWLockUnlock().

Сведения о функциях API для работы с блокировками чтения-записи приведены в таблице ниже.

Функции rwlock.h

Функция

Сведения о функции

KosRWLockInit()

Назначение

Инициализирует блокировку чтения-записи.

Параметры

  • [out] rwlock – указатель на блокировку чтения-записи. Тип блокировки чтения-записи определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosRWLockRead()

Назначение

Захватывает блокировку чтения-записи для чтения.

Если блокировка чтения-записи уже захвачена для записи, или есть потоки исполнения, ожидающие захвата этой блокировки чтения-записи для записи, то ожидает освобождения этой блокировки чтения-записи от захвата для записи сколь угодно долго.

Параметры

  • [in,out] rwlock – указатель на блокировку чтения-записи. Тип блокировки чтения-записи определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosRWLockTryRead()

Назначение

Захватывает блокировку чтения-записи для чтения.

Если блокировка чтения-записи уже захвачена для записи, или есть потоки исполнения, ожидающие захвата этой блокировки чтения-записи для записи, то не ожидает освобождения этой блокировки чтения-записи от захвата для записи, а возвращает управление.

Параметры

  • [in,out] rwlock – указатель на блокировку чтения-записи. Тип блокировки чтения-записи определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosRWLockWrite()

Назначение

Захватывает блокировку чтения-записи для записи.

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

Параметры

  • [in,out] rwlock – указатель на блокировку чтения-записи. Тип блокировки чтения-записи определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosRWLockTryWrite()

Назначение

Захватывает блокировку чтения-записи для записи.

Если блокировка чтения-записи уже захвачена для записи или чтения, не ожидает освобождения этой блокировки чтения-записи, а возвращает управление.

Параметры

  • [in,out] rwlock – указатель на блокировку чтения-записи. Тип блокировки чтения-записи определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosRWLockUnlock()

Назначение

Освобождает блокировку чтения-записи.

Параметры

  • [in,out] rwlock – указатель на блокировку чтения-записи. Тип блокировки чтения-записи определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

Дополнительные сведения

Если блокировка чтения-записи захвачена для чтения, то эта блокировка чтения-записи остается захваченной для чтения, пока все потоки исполнения, выполняющие чтение, не освободят ее.

Семафоры

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

Типовой сценарий использования API для работы с семафорами включает следующие шаги:

  1. Инициализация семафора вызовом функции KosSemaphoreInit().
  2. Использование семафора потоками исполнения:
    1. Ожидание семафора вызовом функции KosSemaphoreWait(), KosSemaphoreWaitTimeout() или KosSemaphoreTryWait().
    2. Сигнализация семафора вызовом функции KosSemaphoreSignal() или KosSemaphoreSignalN().
  3. Освобождение ресурсов семафора вызовом функции KosSemaphoreDeinit().

Сведения о функциях API для работы с семафорами приведены в таблице ниже.

Функции semaphore.h

Функция

Сведения о функции

KosSemaphoreInit()

Назначение

Инициализирует семафор.

Параметры

  • [out] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] count – значение счетчика.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если значение в параметре count превышает константу KOS_SEMAPHORE_VALUE_MAX, возвращает rcInvalidArgument. (Константа KOS_SEMAPHORE_VALUE_MAX определена в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.)

KosSemaphoreDeinit()

Назначение

Освобождает ресурсы семафора.

Параметры

  • [in] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если есть потоки исполнения, ожидающие семафор, возвращает rcBusy.

KosSemaphoreSignal()

Назначение

Сигнализирует семафор с увеличением счетчика на единицу.

Параметры

  • [in,out] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosSemaphoreSignalN()

Назначение

Сигнализирует семафор с увеличением счетчика на заданное число.

Параметры

  • [in,out] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] n – натуральное число, на которое нужно увеличить счетчик.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosSemaphoreWaitTimeout()

Назначение

Ожидает семафор не дольше заданного времени.

Параметры

  • [in,out] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] mdelay – время ожидания семафора в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если время ожидания истекло, возвращает rcTimeout.

KosSemaphoreWait()

Назначение

Ожидает семафор сколь угодно долго.

Параметры

  • [in,out] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosSemaphoreTryWait()

Назначение

Ожидает семафор.

Если счетчик семафора имеет нулевое значение, не ожидает увеличения счетчика этого семафора, а возвращает управление.

Параметры

  • [in,out] semaphore – указатель на семафор. Тип семафора определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Если счетчик семафора имеет нулевое значение, возвращает rcBusy.

Условные переменные

Условная переменная – примитив синхронизации, который используется для уведомления одного или нескольких потоков исполнения о выполнении требуемого этим потокам условия. Условная переменная используется совместно с мьютексом. Уведомляющий и уведомляемый потоки захватывают мьютекс для исполнения критических секций. Уведомляемый поток при исполнении критической секции проверяет, выполняется ли требуемое ему условие (например, подготовлены ли данные уведомляющим потоком). Если условие выполняется, то уведомляемый поток исполняет критическую секцию и освобождает мьютекс. Если условие не выполняется, то уведомляемый поток блокируется на условной переменной, ожидая выполнения условия. При этом мьютекс автоматически освобождается. Уведомляющий поток при исполнении критической секции проверяет, выполняется ли условие, требуемое уведомляемому потоку. Если условие выполняется, то уведомляющий поток сигнализирует об этом через условную переменную и освобождает мьютекс. Уведомляемый поток, заблокированный в ожидании выполнения требуемого ему условия, возобновляет исполнение критической секции, автоматически захватывая мьютекс. После исполнения критической секции уведомляемый поток освобождает мьютекс.

Типовой сценарий использования API для работы с условными переменными включает следующие шаги:

  1. Инициализация условной переменной и мьютекса.

    Чтобы инициализировать условную переменную, нужно вызвать функцию KosCondvarInit().

  2. Использование условной переменной и мьютекса потоками исполнения.

Использование условной переменной и мьютекса на стороне уведомляемых потоков исполнения включает следующие шаги:

  1. Захват мьютекса.
  2. Проверка выполнения условия.
  3. Ожидание выполнения условия вызовом функции KosCondvarWait() или KosCondvarWaitTimeout().

    После возврата функции KosCondvarWait() или KosCondvarWaitTimeout() обычно нужно снова проверить, что условие выполняется, так как другой уведомляемый поток исполнения также получил сигнал и мог сделать условие снова недействительным. (Например, другой поток мог извлечь данные, подготовленные уведомляющим потоком). Для этого нужно использовать следующую конструкцию:

    while(<условие>) <вызов KosCondvarWait() или KosCondvarWaitTimeout()>
  4. Освобождение мьютекса.

Использование условной переменной и мьютекса на стороне уведомляющих потоков исполнения включает следующие шаги:

  1. Захват мьютекса.
  2. Проверка выполнения условия.
  3. Сигнализация о выполнении условия вызовом функции KosCondvarSignal() или KosCondvarBroadcast().
  4. Освобождение мьютекса.

Сведения о функциях API для работы с условными переменными приведены в таблице ниже.

Функции condvar.h

Функция

Сведения о функции

KosCondvarInit()

Назначение

Инициализирует условную переменную.

Параметры

  • [out] condvar – указатель на условную переменную. Тип условной переменной определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosCondvarWaitTimeout()

Назначение

Ожидает выполнения условия не дольше заданного времени.

Параметры

  • [in] condvar – указатель на условную переменную. Тип условной переменной определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in,out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in] mdelay – время ожидания выполнения условия в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.

Возвращаемые значения

В случае успеха возвращает rcOk.

Если время ожидания истекло, возвращает rcTimeout.

KosCondvarWait()

Назначение

Ожидает выполнения условия сколь угодно долго.

Параметры

  • [in] condvar – указатель на условную переменную. Тип условной переменной определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.
  • [in,out] mutex – указатель на мьютекс. Тип мьютекса определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KosCondvarSignal()

Назначение

Сигнализирует о выполнении условия одному из потоков исполнения, ожидающих выполнения этого условия.

Параметры

  • [in,out] condvar – указатель на условную переменную. Тип условной переменной определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

KosCondvarBroadcast()

Назначение

Сигнализирует о выполнении условия всем потокам исполнения, ожидающим выполнения этого условия.

Параметры

  • [in,out] condvar – указатель на условную переменную. Тип условной переменной определен в заголовочном файле sysroot-*-kos/include/kos/sync_types.h из состава KasperskyOS SDK.

Возвращаемые значения

Нет.

В начало
[Topic libkos_sync_api]

Управление изоляцией памяти для ввода-вывода (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

Функция

Сведения о функции

KnIommuAttachDevice()

Назначение

Прикрепляет устройство на шине PCIe к домену IOMMU, ассоциированному с вызывающим процессом.

Параметры

  • [in] bdf – адрес устройства на шине PCIe в формате BDF.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

Если IOMMU не задействован, возвращает rcOk.

KnIommuDetachDevice()

Назначение

Открепляет устройство на шине PCIe от домена IOMMU, ассоциированного с вызывающим процессом.

Параметры

  • [in] bdf – адрес устройства на шине PCIe в формате BDF.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

Если IOMMU не задействован, возвращает rcOk.

В начало
[Topic libkos_iommu_api]

Использование очередей (queue.h)

API определен в заголовочном файле sysroot-*-kos/include/kos/queue.h из состава KasperskyOS SDK.

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

Сведения о функциях API приведены в таблице ниже.

Использование API

Типовой сценарий использования API включает следующие шаги:

  1. Создание абстракции очереди.

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

    Чтобы выполнить этот шаг, нужно вызвать функцию KosQueueCreate(). Эта функция может выделить память для буфера очереди или использовать уже выделенную память. Размер уже выделенной памяти должен быть достаточным, чтобы вместить максимальное число элементов в очереди. При этом нужно учитывать, что размер участка в буфере очереди округляется до ближайшего большего кратного значению выравнивания, заданному через параметр objAlign. Также начальный адрес уже выделенной памяти должен быть выравнен так, чтобы соответствовать типам данных элементов очереди. Если выравнивание адреса памяти, указанного в параметре buffer, меньше заданного через параметр objAlign, то функция вернет RTL_NULL.

  2. Обмен данными между потоками исполнения через добавление и извлечение элементов очереди.

    Чтобы добавить один элемент в конец очереди, нужно зарезервировать участок в буфере очереди вызовом функции KosQueueAlloc(), скопировать этот элемент в зарезервированный участок и вызвать функцию KosQueuePush().

    Чтобы добавить последовательность элементов в конец очереди, нужно зарезервировать требуемое количество участков в буфере очереди вызовами функции KosQueueAlloc(), скопировать элементы этой последовательности в зарезервированные участки и вызвать функцию KosQueuePushArray(). Порядок элементов последовательности не изменяется после добавления этой последовательности в очередь. То есть элементы добавляются очередь в том же порядке, в каком указатели на зарезервированные участки в буфере очереди помещены в массив, передаваемый через параметр objs функции KosQueuePushArray().

    Чтобы извлечь первый элемент очереди, нужно вызвать функцию KosQueuePop(). Эта функция возвращает указатель на зарезервированный участок в буфере очереди, который содержит первый элемент очереди. После использования извлеченного элемента (например, после проверки или сохранения значения элемента) нужно отменить резервирование занятого этим элементом участка в буфере очереди. Для этого нужно вызвать функцию KosQueueFree().

    Чтобы очистить очередь и отменить резервирование всех зарезервированных участков в буфере очереди, нужно вызвать функцию KosQueueFlush().

  3. Удаление абстракции очереди.

    Чтобы выполнить этот шаг, нужно вызвать функцию KosQueueDestroy(). Эта функция удаляет буфер очереди, если только память для этого буфера была выделена функцией KosQueueCreate(). В противном случае нужно отдельно выполнить удаление буфера очереди.

Сведения о функциях API

Функции queue.h

Функция

Сведения о функции

KosQueueCreate()

Назначение

Создает абстракцию очереди.

Параметры

  • [in] objCount – максимальное число элементов в очереди.
  • [in] objSize – размер элемента очереди в байтах.
  • [in] objAlign – выравнивание адресов участков в буфере очереди. Адреса участков в буфере очереди могут быть невыравненными (objAlign=1) или выравненными (objAlign=2,4,...,2^N) на границу 2^N-байтовой последовательности (например, двухбайтовой, четырехбайтовой).
  • [in,optional] buffer – указатель на выделенную память для буфера очереди или RTL_NULL, чтобы память была выделена автоматически.

Возвращаемые значения

В случае успеха возвращает идентификатор абстракции очереди, иначе возвращает RTL_NULL.

KosQueueDestroy()

Назначение

Удаляет абстракцию очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.

Возвращаемые значения

Нет.

KosQueueAlloc()

Назначение

Резервирует участок в буфере очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.

Возвращаемые значения

В случае успеха возвращает указатель на зарезервированный участок в буфере очереди, иначе возвращает RTL_NULL.

KosQueueFree()

Назначение

Отменяет резервирование заданного участка в буфере очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.
  • [in] obj – указатель на зарезервированный участок в буфере очереди.

Возвращаемые значения

Нет.

KosQueuePush()

Назначение

Добавляет элемент в конец очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.
  • [in] obj – указатель на зарезервированный участок в буфере очереди.

Возвращаемые значения

Нет.

KosQueuePushArray()

Назначение

Добавляет последовательность элементов в конец очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.
  • [in] objs – массив указателей на зарезервированные участки в буфере очереди.
  • [in] count – число элементов в последовательности.

Возвращаемые значения

Нет.

KosQueuePop()

Назначение

Извлекает первый элемент очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.
  • [in] timeout – время ожидания появления элемента в очереди в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.

Возвращаемые значения

В случае успеха возвращает указатель на зарезервированный участок в буфере очереди, который содержит первый элемент очереди. Иначе возвращает RTL_NULL.

KosQueueFlush()

Назначение

Очищает очередь и отменяет резервирование всех зарезервированных участков в буфере очереди.

Параметры

  • [in] queue – идентификатор абстракции очереди.

Возвращаемые значения

Нет.

В начало
[Topic libkos_queue_api]

Использование барьеров памяти (barriers.h)

API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/barriers.h из состава KasperskyOS SDK.

API позволяет устанавливать барьеры на чтение из памяти и/или на запись в память. Барьер памяти (англ. memory barrier) – это инструкция для компилятора и процессора, которая гарантирует, что операции доступа к памяти, указанные в исходном коде до установки барьера, будут выполнены до операций доступа к памяти, указанных в исходном коде после установки барьера. Использование барьеров памяти требуется, если важен порядок операций чтения из памяти и/или записи в память, поскольку действия компилятора и/или процессора, связанные с оптимизацией, могут привести к тому, что эти операции будут выполнены в порядке, отличном от указанного в исходном коде.

Сведения о функциях API приведены в таблице ниже.

Функции barriers.h

Функция

Сведения о функции

IoReadBarrier()

Назначение

Устанавливает барьер на чтение из памяти.

Параметры

Нет.

Возвращаемые значения

Нет.

IoWriteBarrier()

Назначение

Устанавливает барьер на запись в память.

Параметры

Нет.

Возвращаемые значения

Нет.

IoReadWriteBarrier()

Назначение

Устанавливает барьер на запись в память и чтение из памяти.

Параметры

Нет.

Возвращаемые значения

Нет.

В начало
[Topic libkos_barriers_api]

Выполнение системных вызовов (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

Функция

Сведения о функции

Call()

Назначение

Выполняет системный вызов Call() с неограниченным временем ожидания его завершения.

Параметры

  • [in] handle – клиентский IPC-дескриптор.
  • [in] msgOut – указатель на заголовок IPC-запросов.
  • [in,out] msgIn – указатель на заголовок IPC-ответов.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

CallEx()

Назначение

Выполняет системный вызов Call() с заданным временем ожидания его завершения и возможностью прервать его выполнение.

Параметры

  • [in] handle – клиентский IPC-дескриптор.
  • [in] msgOut – указатель на заголовок IPC-запросов.
  • [in,out] msgIn – указатель на заголовок IPC-ответов.
  • [in] mdelay – время ожидания завершения системного вызова Call() в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.
  • [in,optional] syncHandle – дескриптор объекта синхронизации IPC или INVALID_HANDLE, если прерывание системного вызова Call() не требуется.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Reply()

Назначение

Выполняет системный вызов Reply().

Параметры

  • [in] handle – серверный IPC-дескриптор.
  • [in] msgOut – указатель на заголовок IPC-ответов.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Recv()

Назначение

Выполняет системный вызов Recv() с неограниченным временем ожидания его завершения.

Параметры

  • [in] handle – серверный IPC-дескриптор.
  • [in,out] msgIn – указатель на заголовок IPC-запросов.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

RecvEx()

Назначение

Выполняет системный вызов Recv() с заданным временем ожидания его завершения и возможностью прервать его выполнение.

Параметры

  • [in] handle – серверный IPC-дескриптор.
  • [in,out] msgIn – указатель на заголовок IPC-ответов.
  • [in] mdelay – время ожидания завершения системного вызова Recv() в миллисекундах или INFINITE_TIMEOUT, чтобы задать неограниченное время ожидания.
  • [in,optional] syncHandle – дескриптор объекта синхронизации IPC или INVALID_HANDLE, если прерывание системного вызова Recv() не требуется.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_syscalls_api]

Прерывание 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

Функция

Сведения о функции

KnIpcCreateSyncObject()

Назначение

Создает объект синхронизации IPC.

Параметры

  • [out] syncHandle – указатель на дескриптор объекта синхронизации IPC.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIpcSetInterrupt()

Назначение

Переводит заданный объект синхронизации IPC в состояние, при котором системные вызовы Call() и Recv() прерываются.

Параметры

  • [in] syncHandle – дескриптор объекта синхронизации IPC.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIpcClearInterrupt()

Назначение

Переводит заданный объект синхронизации IPC в состояние, при котором системные вызовы Call() и Recv() не прерываются.

Параметры

  • [in] syncHandle – дескриптор объекта синхронизации IPC.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

В начало
[Topic libkos_ipc_api][Topic posix_api]

Ограничения поддержки POSIX

В KasperskyOS ограниченно реализован POSIX с ориентацией на стандарт POSIX.1-2008. Прежде всего ограничения связаны с обеспечением безопасности.

Отсутствует поддержка XSI и опциональной функциональности.

Ограничения затрагивают:

  • взаимодействие между процессами;
  • взаимодействие между потоками исполнения посредством сигналов;
  • асинхронный ввод-вывод;
  • использование робастных мьютексов;
  • работу с терминалом;
  • работу с оболочкой;
  • управление дескрипторами файлов;
  • использование таймеров;
  • получение системных параметров.

Ограничения представлены:

  • нереализованными интерфейсами;
  • интерфейсами, которые реализованы с отклонениями от стандарта POSIX.1-2008;
  • интерфейсами-заглушками, которые не выполняют никаких действий, кроме присвоения переменной errno значения ENOSYS и возвращения значения -1.

В KasperskyOS сигналы не могут прервать системные вызовы Call(), Recv(), Reply(), которые обеспечивают работу библиотек, реализующих интерфейс POSIX.

Ядро KasperskyOS не посылает сигналы.

Ограничения взаимодействия между процессами

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

fork()

Создать новый (дочерний) процесс.

Не реализован.

unistd.h

pthread_

atfork()

Зарегистрировать обработчики, которые вызываются перед и после создания дочернего процесса.

Не реализован.

pthread.h

wait()

Ожидать остановки или завершения дочернего процесса.

Заглушка.

sys/wait.h

waitid()

Ожидать изменения состояния дочернего процесса.

Не реализован.

sys/wait.h

waitpid()

Ожидать остановки или завершения дочернего процесса.

Заглушка.

sys/wait.h

execl()

Запустить исполняемый файл.

Заглушка.

unistd.h

execle()

Запустить исполняемый файл.

Заглушка.

unistd.h

execlp()

Запустить исполняемый файл.

Заглушка.

unistd.h

execv()

Запустить исполняемый файл.

Не реализован.

unistd.h

execve()

Запустить исполняемый файл.

Не реализован.

unistd.h

execvp()

Запустить исполняемый файл.

Заглушка.

unistd.h

fexecve()

Запустить исполняемый файл.

Заглушка.

unistd.h

setpgid()

Перевести процесс в другую группу или создать группу.

Заглушка.

unistd.h

setsid()

Создать сессию.

Заглушка.

unistd.h

getpgrp()

Получить идентификатор группы вызывающего процесса.

Заглушка.

unistd.h

getpgid()

Получить идентификатор группы.

Заглушка.

unistd.h

getppid()

Получить идентификатор родительского процесса.

Заглушка.

unistd.h

getsid()

Получить идентификатор сессии.

Заглушка.

unistd.h

times()

Получить значения времени для процесса и его потомков.

Заглушка.

sys/times.h

kill()

Послать сигнал процессу или группе процессов.

Можно посылать только сигнал SIGTERM. Параметр pid игнорируется.

signal.h

pause()

Ожидать сигнала.

Заглушка.

unistd.h

sigpending()

Проверить наличие полученных заблокированных сигналов.

Не реализован.

signal.h

sigqueue()

Послать сигнал процессу.

Не реализован.

signal.h

sigtimedwait()

Ожидать сигнала из заданного набора сигналов.

Не реализован.

signal.h

sigwaitinfo()

Ожидать сигнала из заданного набора сигналов.

Не реализован.

signal.h

sem_init()

Создать неименованный семафор.

Нельзя создать неименованный семафор для синхронизации между процессами. Если передать ненулевое значение через параметр pshared, то только вернет значение -1 и присвоит переменной errno значение ENOTSUP.

semaphore.h

sem_open()

Создать/открыть именованный семафор.

Нельзя открыть именованный семафор, который был создан другим процессом. Именованные семафоры (как и неименованные) являются локальными, то есть они доступны только тому процессу, который их создал.

semaphore.h

pthread_

spin_init()

Создать спин-блокировку.

Нельзя создать спин-блокировку для синхронизации между процессами. Если передать значение PTHREAD_PROCESS_SHARED через параметр pshared, то это значение будет проигнорировано.

pthread.h

mmap()

Отобразить в память.

Нельзя выполнить отображение в память для взаимодействия между процессами. Если передать значения MAP_SHARED и PROT_WRITE через параметры flags и prot соответственно, то только вернет значение MAP_FAILED и присвоит переменной errno значение EACCES. Для остальных возможных значений параметра prot значение MAP_SHARED параметра flags игнорируется. Кроме того, через параметр prot нельзя передавать сочетания флагов PROT_WRITE|PROT_EXEC и PROT_READ|PROT_WRITE|PROT_EXEC. В этом случае только вернет значение MAP_FAILED и присвоит переменной errno значение ENOMEM.

sys/mman.h

mprotect()

Задать права доступа к памяти.

Для целей безопасности некоторые конфигурации ядра KasperskyOS запрещают предоставлять доступ к регионам виртуальной памяти на запись и исполнение одновременно. Если при использовании такой конфигурации ядра через параметр prot передать значение PROT_WRITE|PROT_EXEC, то только вернет значение -1 и присвоит переменной errno значение ENOTSUP.

sys/mman.h

pipe()

Создать неименованный канал.

Нельзя использовать неименованный канал для передачи данных между процессами. Неименованные каналы являются локальными, то есть они доступны только тому процессу, который их создал.

unistd.h

mkfifo()

Создать специальный файл FIFO (именованный канал).

Заглушка.

sys/stat.h

mkfifoat()

Создать специальный файл FIFO (именованный канал).

Не реализован.

sys/stat.h

Ограничения взаимодействия между потоками исполнения посредством сигналов

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

pthread_kill()

Послать сигнал потоку исполнения.

Нельзя послать сигнал потоку исполнения. Если передать номер сигнала через параметр sig, то только возвращается значение ENOSYS.

signal.h

siglongjmp()

Восстановить состояние потока управления и маску сигналов.

Не реализован.

setjmp.h

sigsetjmp()

Сохранить состояние потока управления и маску сигналов.

Не реализован.

setjmp.h

Ограничения асинхронного ввода-вывода

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

aio_cancel()

Отменить запросы ввода-вывода, которые ожидают обработки.

Не реализован.

aio.h

aio_error()

Получить ошибку операции асинхронного ввода-вывода.

Не реализован.

aio.h

aio_fsync()

Запросить выполнение операций ввода-вывода.

Не реализован.

aio.h

aio_read()

Запросить чтение из файла.

Не реализован.

aio.h

aio_return()

Получить статус операции асинхронного ввода-вывода.

Не реализован.

aio.h

aio_suspend()

Ожидать завершения операций асинхронного ввода-вывода.

Не реализован.

aio.h

aio_write()

Запросить запись в файл.

Не реализован.

aio.h

lio_listio()

Запросить выполнение набора операций ввода-вывода.

Не реализован.

aio.h

Ограничения использования робастных мьютексов

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

pthread_mutex_consistent()

Вернуть робастный мьютекс в консистентное состояние.

Не реализован.

pthread.h

pthread_mutexattr_getrobust()

Получить атрибут робастности мьютекса.

Не реализован.

pthread.h

pthread_mutexattr_setrobust()

Задать атрибут робастности мьютекса.

Не реализован.

pthread.h

Ограничения работы с терминалом

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

ctermid()

Получить путь к файлу управляющего терминала.

Только возвращает или передает через параметр s пустую строку.

stdio.h

tcsetattr()

Задать параметры терминала.

Скорость ввода, скорость вывода и другие параметры, специфичные для аппаратных терминалов, игнорируются.

termios.h

tcdrain()

Ожидать завершения вывода.

Только возвращает значение -1.

termios.h

tcflow()

Приостановить или возобновить прием или передачу данных.

Приостановка вывода и запуск приостановленного вывода не поддерживаются.

termios.h

tcflush()

Очистить очередь ввода или очередь вывода, или обе эти очереди.

Только возвращает значение -1.

termios.h

tcsendbreak()

Разорвать соединение с терминалом на заданное время.

Только возвращает значение -1.

termios.h

ttyname()

Получить путь к файлу терминала.

Только возвращает нулевой указатель.

unistd.h

ttyname_r()

Получить путь к файлу терминала.

Только возвращает значение ошибки.

unistd.h

tcgetpgrp()

Получить идентификатор группы процессов, использующих терминал.

Только возвращает значение -1.

unistd.h

tcsetpgrp()

Задать идентификатор группы процессов, использующих терминал.

Только возвращает значение -1.

unistd.h

tcgetsid()

Получить идентификатор группы процессов для лидера сессии, связанной с терминалом.

Только возвращает значение -1.

termios.h

Ограничения работы с оболочкой

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

popen()

Создать дочерний процесс для выполнения команды и неименованный канал с этим процессом.

Только присваивает переменной errno значение ENOSYS и возвращает значение NULL.

stdio.h

pclose()

Закрыть неименованный канал с дочерним процессом, созданным popen(), и ожидать завершения дочернего процесса.

Нельзя использовать, так как popen() всегда возвращает NULL вместо дескриптора неименованного канала, который является входными параметром для pclose().

stdio.h

system()

Создать дочерний процесс для выполнения команды.

Заглушка.

stdlib.h

wordexp()

Раскрыть строку как в оболочке.

Не реализован.

wordexp.h

wordfree()

Освободить память, выделенную для результатов вызова wordexp().

Не реализован.

wordexp.h

Ограничения управления дескрипторами файлов

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

dup()

Сделать копию дескриптора открытого файла.

Поддерживаются дескрипторы обычных файлов, стандартных потоков ввода-вывода, сокетов и каналов. Не гарантируется, что будет получен наименьший свободный дескриптор.

fcntl.h

dup2()

Сделать копию дескриптора открытого файла.

Поддерживаются дескрипторы обычных файлов, стандартных потоков ввода-вывода, сокетов и каналов. Через параметр fildes2 нужно передавать дескриптор открытого файла.

fcntl.h

Ограничения использования таймеров

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

clock_gettime()

Получить значение времени.

Если передать значение CLOCK_PROCESS_CPUTIME_ID или CLOCK_THREAD_CPUTIME_ID через параметр clock_id, то только вернет значение -1 и присвоит переменной errno значение EINVAL.

time.h

clock()

Получить процессорное время, затраченное на исполнение вызывающего процесса.

Возвращает время с момента запуска ядра KasperskyOS в миллисекундах.

time.h

Получение системных параметров

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

confstr()

Получить системный параметр.

Заглушка.

unistd.h

В начало
[Topic posix_uns_ifaces]

Особенности реализации POSIX

В KasperskyOS реализация некоторых интерфейсов POSIX в части, которая не определяется стандартом POSIX.1-2008, отличается от реализации этих интерфейсов в Linux и других UNIX-подобных операционных системах. Сведения об этих интерфейсах приведены в таблице ниже.

Интерфейсы POSIX с особенностями реализации

Интерфейс

Назначение

Реализация

Заголовочный файл по стандарту POSIX.1-2008

bind()

Назначить имя сокету.

При использовании версии VFS, которая поддерживает только сетевые операции, файлы сокетов семейства AF_UNIX при вызове bind() сохраняются в специальной файловой системе, реализуемой этой версией VFS. Файл сокета может быть создан только в корне файловой системы или в директории /tmp, а также может быть повторно использован после закрытия сокета.

sys/socket.h

mmap()

Отобразить в память.

На аппаратных платформах с процессорной архитектурой AArch64 (ARM64) нельзя выполнить отображение более 4 ГБ.

sys/mman.h

read()

Выполнить чтение из файла.

Если размер буфера buf превышает размер считанных данных, то оставшаяся часть этого буфера заполняется нулями.

unistd.h

В начало
[Topic posix_ifaces_impl_features]

Совместное использование POSIX и API libkos

В потоке исполнения, созданном с помощью Pthreads, нельзя использовать следующие API libkos:

Следующие API libkos можно использовать совместно с Pthreads (и другими API POSIX):

Интерфейсы POSIX нельзя использовать в потоках исполнения, созданных с помощью API thread.h и thread_api.h.

API syscalls.h можно использовать в любых потоках исполнения, созданных с использованием Pthreads или API thread.h и thread_api.h.

В начало
[Topic posix_and_libkos]

Получение статистических сведений о системе

Библиотеки libkos и libc предоставляют API для получения статистических сведений о системе. Эти сведения включают следующие пункты:

  • об использовании процессорного времени системой и отдельным процессом;
  • об использовании памяти системой и отдельным процессом;
  • о процессах и потоках исполнения;
  • о файловых системах и сетевых интерфейсах.

В этом разделе

Получение статистических сведений о системе через API библиотеки libkos

Получение статистических сведений о системе через API библиотеки libc

В начало
[Topic sys_inf]

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

Сведения об использовании процессорного времени

Функция

Значение параметра param

Получаемое значение

KnGroupStatGetParam()

GROUP_PARAM_CPU_KERNEL

Время работы всех процессоров в режиме ядра

KnGroupStatGetParam()

GROUP_PARAM_CPU_USER

Время работы всех процессоров в пользовательском режиме

KnGroupStatGetParam()

GROUP_PARAM_CPU_IDLE

Время работы всех процессоров в режиме бездействия

KnTaskStatGetParam()

TASK_PARAM_TIME_TOTAL

Время работы всех процессоров, затраченное на исполнение заданного процесса

KnTaskStatGetParam()

TASK_PARAM_TIME_USER

Время работы всех процессоров, затраченное на исполнение заданного процесса в пользовательском режиме

KnCpuStatGetParam()

CPU_STAT_PARAM_IDLE

Время работы заданного процессора в режиме бездействия

KnCpuStatGetParam()

CPU_STAT_PARAM_USER

Время работы заданного процессора в пользовательском режиме

KnCpuStatGetParam()

CPU_STAT_PARAM_KERNEL

Время работы заданного процессора в режиме ядра

Процессорное время, полученное вызовом функции KnGroupStatGetParam(), KnTaskStatGetParam() или KnCpuStatGetParam(), представлено в наносекундах.

Входным параметром функции KnCpuStatGetParam() является индекс процессора (нумерация начинается с нуля). Чтобы получить общее число процессоров на аппаратной платформе, нужно использовать функцию KnHalGetCpuCount(), объявленную в заголовочном файле sysroot-*-kos/include/coresrv/hal/hal_api.h из состава KasperskyOS SDK.

Получение сведений об использовании памяти

Чтобы получить сведения об использовании памяти, нужно использовать функции KnGroupStatGetParam() и KnTaskStatGetParam(). При этом через параметр param этих функций нужно передать значения, приведенные в таблице ниже.

Сведения об использовании памяти

Функция

Значение параметра param

Получаемое значение

KnGroupStatGetParam()

GROUP_PARAM_MEM_TOTAL

Размер всей установленной физической памяти

KnGroupStatGetParam()

GROUP_PARAM_MEM_FREE

Размер свободной физической памяти

KnGroupStatGetParam()

GROUP_PARAM_MEM_EXEC

Размер физической памяти с атрибутом "доступ на исполнение"

KnGroupStatGetParam()

GROUP_PARAM_MEM_SHARED

Размер физической памяти, используемой в качестве разделяемой

KnTaskStatGetParam()

TASK_PARAM_MEM_PHY

Размер физической памяти, используемой заданным процессом

KnTaskStatGetParam()

TASK_PARAM_MEM_VIRT

Размер виртуальной памяти заданного процесса

KnTaskStatGetParam()

TASK_PARAM_MEM_SHARED

Размер виртуальной памяти заданного процесса, отображаемой на разделяемую физическую память

KnTaskStatGetParam()

TASK_PARAM_MEM_PAGE_TABLE

Размер таблицы страниц заданного процесса

Размер памяти, полученный вызовом функции KnGroupStatGetParam() или KnTaskStatGetParam(), представляет собой число страниц памяти. Размер страницы памяти составляет 4 КБ для всех аппаратных платформ, поддерживаемых KasperskyOS.

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

Получение сведений о процессах и потоках исполнения

Помимо сведений об использовании процессорного времени и памяти функции KnGroupStatGetParam() и KnTaskStatGetParam() позволяют получить сведения о процессах и потоках исполнения. Для этого через параметр param этих функций нужно передать значения, приведенные в таблице ниже.

Сведения о процессах и потоках исполнения

Функция

Значение параметра param

Получаемое значение

KnGroupStatGetParam()

GROUP_PARAM_TASKS

Число пользовательских процессов (без учета процесса ядра)

KnGroupStatGetParam()

GROUP_PARAM_THREADS

Общее число потоков исполнения (включая потоки ядра)

KnTaskStatGetParam()

TASK_PARAM_PPID

Идентификатор родительского процесса заданного процесса (PPID)

KnTaskStatGetParam()

TASK_PARAM_PRIO

Приоритет начального потока заданного процесса

KnTaskStatGetParam()

TASK_PARAM_STATE

Состояние заданного процесса (в соответствии с перечислением TaskExecutionStates, определенным в заголовочном файле sysroot-*-kos/include/task/pcbpage.h из состава KasperskyOS SDK)

KnTaskStatGetParam()

TASK_PARAM_IMGSIZE

Размер загруженного в память образа программы, исполняемой в контексте заданного процесса, в байтах

KnTaskStatGetParam()

TASK_PARAM_TIME_START

Время между запуском ядра и запуском заданного процесса в наносекундах

KnTaskStatGetParam()

TASK_PARAM_HANDLES

Число дескрипторов, принадлежащих заданному процессу

KnTaskStatGetParam()

TASK_PARAM_THREADS

Число потоков исполнения в заданном процессе

Кроме функций KnGroupStatGetParam() и KnTaskStatGetParam() для получения сведений о процессах и потоках исполнения можно использовать следующие функции:

  • KnTaskStatGetName() позволяет получить имя заданного процесса.
  • KnTaskStatGetPath() позволяет получить имя исполняемого файла в ROMFS, из которого запущен заданный процесс.

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

  • KnTaskStatGetId() позволяет получить идентификатор заданного процесса (PID).
  • KnProfilerGetCounters() позволяет получить значения счетчиков производительности.

    Например, чтобы получить число потоков ядра и общее число дескрипторов, нужно передать через параметр names значения kl.core.Core.threads и handles.total.

Получение сведений об использовании процессорного времени и памяти каждым процессом

Чтобы получить сведения об использовании процессорного времени и памяти каждым процессом, нужно выполнить следующие действия:

  1. Получить список процессов вызовом функции KnGroupStatGetTaskList().
  2. Получить число элементов списка процессов вызовом функции KnTaskStatGetTasksCount().
  3. Выполнить в цикле следующие действия:
    1. Получить элемент списка процессов вызовом функции KnTaskStatEnumTaskList().
    2. Получить имя процесса вызовом функции KnTaskStatGetName().

      Это требуется, чтобы идентифицировать процесс, для которого будут получены сведения об использовании процессорного времени и памяти.

    3. Получить сведения об использовании процессорного времени и памяти процессом вызовами функции KnTaskStatGetParam().
    4. Проверить, что процесс не завершился. Если процесс завершился, то отбросить полученные сведения об использовании процессорного времени и памяти этим процессом.

      Чтобы проверить, что процесс не завершился, нужно вызвать функцию KnTaskStatGetParam() с передачей через параметр param значения TASK_PARAM_STATE. Должно быть получено значение, отличное от TaskStateTerminated.

    5. Завершить работу с элементом списка процессов вызовом функции KnTaskStatCloseTask().
  4. Завершить работу со списком процессов вызовом функции 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).

В начало
[Topic sys_inf_libkos]

Получение статистических сведений о системе через API библиотеки libc

Библиотека libc предоставляет API, которые позволяют получить статистические сведения о файловых системах и сетевых интерфейсах, управляемых VFS. Функции этих API приведены в таблице ниже.

Сведения о файловых системах и сетевых интерфейсах

Функция

Заголовочный файл из состава KasperskyOS SDK

Получаемые сведения

statvfs()

sysroot-*-kos/include/strict/posix/sys/statvfs.h

Сведения о файловой системе, такие как размер блока, число блоков, число свободных блоков

getvfsstat()

sysroot-*-kos/include/sys/statvfs.h

Сведения обо всех смонтированных файловых системах, идентичные предоставляемым функцией statvfs()

getifaddrs()

sysroot-*-kos/include/ifaddrs.h

Сведения о сетевых интерфейсах, такие как имя, IP-адрес, маска подсети

В начало
[Topic sys_inf_libc]

Компонент 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

Интерфейс IProviderControl

Интерфейс IProvider (компонент MessageBus)

Интерфейсы ISubscriber, IWaiter и ISubscriberRunner

В начало
[Topic messagebus_component]

Интерфейс 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 (фрагмент)

class IProviderFactory { ... virtual fdn::ResultCode CreateBusControl(IProviderControlPtr& controlPtr) = 0; virtual fdn::ResultCode CreateBus(IProviderPtr& busPtr) = 0; virtual fdn::ResultCode CreateCallbackWaiter(IWaiterPtr& waiterPtr) = 0; virtual fdn::ResultCode CreateSubscriberRunner(ISubscriberRunnerPtr& runnerPtr) = 0; ... }; ... fdn::ResultCode InitConnection(const std::string& connectionId, IProviderFactoryPtr& busFactoryPtr);
В начало
[Topic messagebus_component_iproviderfactory]

Интерфейс IProviderControl

Интерфейс IProviderControl предоставляет методы для регистрации и дерегистрации издателей и подписчиков в шине сообщений.

Описание интерфейса IProviderControl представлено в файле messagebus/i_messagebus_control.h.

Для получение экземпляра интерфейса используется интерфейс IProviderFactory.

Регистрация и дерегистрация издателя

Для регистрации издателя в шине сообщений используется метод IProviderControl::RegisterPublisher(). Метод принимает тему сообщения и помещает в выходной параметр уникальный идентификатор клиента шины. Если тема уже зарегистрирована в шине, то вызов будет отклонен, и идентификатор клиента не будет заполнен.

Для дерегистрации издателя в шине сообщений используется метод IProviderControl::UnregisterPublisher(). Метод принимает идентификатор клиента шины, полученный при регистрации. Если указан идентификатор, не зарегистрированный как идентификатор издателя, то вызов будет отклонен.

i_messagebus_control.h (фрагмент)

class IProviderControl { ... virtual fdn::ResultCode RegisterPublisher(const Topic& topic, ClientId& id) = 0; virtual fdn::ResultCode UnregisterPublisher(ClientId id) = 0; ... };

Регистрация и дерегистрация подписчика

Для регистрации подписчика в шине сообщений используется метод IProviderControl::RegisterSubscriber(). Метод принимает имя подписчика и список тем, на которые нужно подписаться, а в выходной параметр помещает уникальный идентификатор клиента шины.

Для дерегистрации подписчика в шине сообщений используется метод IProviderControl::UnregisterSubscriber(). Метод принимает идентификатор клиента шины, полученный при регистрации. Если указан идентификатор, не зарегистрированный как идентификатор подписчика, то вызов будет отклонен.

i_messagebus_control.h (фрагмент)

class IProviderControl { ... virtual fdn::ResultCode RegisterSubscriber(const std::string& subscriberName, const std::set<Topic>& topics, ClientId& id) = 0; virtual fdn::ResultCode UnregisterSubscriber(ClientId id) = 0; ... };
В начало
[Topic messagebus_component_icontrol]

Интерфейс IProvider (компонент MessageBus)

Интерфейс IProvider предоставляет методы для отправки издателем сообщений в шину.

Описание интерфейса IProvider представлено в файле messagebus/i_messagebus.h.

Для получение экземпляра интерфейса используется интерфейс IProviderFactory.

Отправка сообщения в шину

Для оправки сообщения в шину используется метод IProvider::Push(). Метод принимает идентификатор клиента шины, полученный при регистрации, и идентификатор сообщения. Если очередь сообщений в шине заполнена, то вызов будет отклонен.

i_messagebus.h (фрагмент)

class IProvider { public: ... virtual fdn::ResultCode Push(ClientId id, BundleId dataId) = 0; ... };
В начало
[Topic messagebus_component_iprovider]

Интерфейсы 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 (фрагмент)

class ISubscriber { ... virtual fdn::ResultCode OnMessage(const std::string& topic, BundleId id) = 0; }; ... class IWaiter { ... [[deprecated("Use ISubscriberRunner::Run method instead.")]] virtual fdn::ResultCode Wait(ClientId id, const ISubscriberPtr& subscriberPtr) = 0; }; ... class ISubscriberRunner { ... virtual fdn::ResultCode Run(ClientId id, const ISubscriberPtr& subscriberPtr) = 0; };
В начало
[Topic messagebus_component_isubwait]

Компонент 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

#include <component/execution_manager/kos_ipc/execution_manager_proxy.h> ... namespace execmgr = execution_manager; int main(int argc, const char *argv[]) { // ... execmgr::IExecutionManagerPtr ptr; // имя IPC-канала для соединения с процессом ExecutionManager. Должно совпадать со значением MAIN_CONN_NAME в файле CMakeLists.txt для сборки ExecutionManager. char mainConnection[] = "ExecMgrEntity"; execmgr::ipc::ExecutionManagerConfig cfg{mainConnection}; if (CreateExecutionManager(cfg, ptr) != eka::sOk) { std::cerr << "Cannot create execution manager" << std::endl; return EXIT_FAILURE; } // ... }

Интерфейс IExecutionManager

API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_execution_manager.h

Интерфейс IExecutionManager позволяет получить доступ к указателям на следующие интерфейсы:

  • IApplicationController - интерфейс для запуска\остановки процессов;
  • ISystemController - интерфейс для управления системой.

Пример использования:

client.cpp

int main(int argc, const char *argv[]) { // ... execmgr::IApplicationControllerPtr ac; if (ptr->GetApplicationController(ac) != eka::sOk) { std::cerr << "Cannot get application controller" << std::endl; return EXIT_FAILURE; } execmgr::ISystemControllerPtr sc; if (ptr->GetSystemController(sc) != eka::sOk) { std::cerr << "Cannot get system controller" << std::endl; return EXIT_FAILURE; } // ... }

Интерфейс 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, идентифицирующую запущенный процесс.

struct IApplicationController { // Все поля структуры StartEntityInfo являются опциональными для инициализации. struct StartEntityInfo { // Имя процесса. Если не указано, то будет использовано имя класса процесса. // Если не указано имя класса процесса, то будет использовано имя исполняемого файла. std::string entityName; // Класс процесса. Если не указан, то будет использовано имя процесса. Если не указано имя процесса, то будет использовано имя исполняемого файла. std::string eiid; std::vector<std::string> args; // Аргументы командной строки. std::vector<std::string> envs; // Переменные окружения. // Политика перезапуска процесса при его аварийном завершении. Возможные значения: // EntityRestartPolicy::DoNotRestart - не перезапускать. // EntityRestartPolicy::AlwaysRestart - всегда перезапускать. EntityRestartPolicy restartPolicy { EntityRestartPolicy::DoNotRestart }; }; struct StartEntityResultInfo { std::string eiid; // Класс безопасности, присвоенный процессу. EntityId entId; // Структура, идентифицирующая запущенный процесс. Uid sid; // Идентификатор безопасности запущенного процесса. std::string taskName; // Имя запущенного процесса. }; };

Пример использования:

client.cpp

int main(int argc, const char *argv[]) { // ... const fs::path appPath{"/application"}; execmgr::IApplicationController::StartEntityResultInfo result; execmgr::IApplicationController::StartEntityInfo info; info.entityName = std::string{"application.Application"}; info.eiid = std::string{"application.Application"}; info.args = std::vector<std::string>{"1", "ARG1", "ARG2" , "ARG3"}; info.envs = std::vector<std::string>{"ENV1=10", "ENV2=envStr"}; std::cout << "Starting application from elf\n"; if (ac->StartEntity(appPath, info, result) != eka::sOk) { std::cerr << "Can not start application from " << appPath << std::endl; return EXIT_FAILURE; } std::cout << "Application started with process sid " << result.sid << "\n"; auto AppId = result.entId; if (ac->StopEntity(AppId) != eka::sOk) { std::cerr << "Cannot stop process " << appPath << std::endl; return EXIT_FAILURE; } // ... }

Интерфейс ISystemController

API определен в заголовочном файле sysroot-*-kos/include/component/execution_manager/i_system_control.h

Интерфейс ISystemController предоставляет следующий метод для управления системой:

  • StopAllEntities() - метод останавливает все запущенные процессы; затем завершает процесс ExecutionManager; а затем отправляет в ядро запрос на выключение устройства.

Пример использования:

client.cpp

int main(int argc, const char *argv[]) { // ... if (sc->StopAllEntities() != eka::sOk) { std::cerr << "Cannot stop all processes\n"; return EXIT_FAILURE; } // ... }
В начало
[Topic execmgr_component]