API определены в заголовочных файлах transport-kos.h
и transport-kos-dispatch.h
из состава KasperskyOS SDK, которые расположены по пути sysroot-*-kos/include/coresrv/nk
.
Возможности API:
IPC-транспорт – это надстройка над системными вызовами отправки и приема IPC-сообщений, которая позволяет отдельно работать с фиксированной частью и ареной IPC-сообщений. Поверх этой надстройки работает транспортный код.
Сведения о функциях 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-каналов, то нужно учитывать следующие особенности:
Функция NkKosTransportSync_Init()
позволяет инициализировать IPC-транспорт с поддержкой прерывания блокирующих системных вызовов Call()
и Recv()
. (Прерывание этих вызовов может потребоваться, например, чтобы корректно завершить процесс, который их выполняет.) Чтобы прерывать системные вызовы Call()
и Recv()
, нужно использовать API ipc_api.h.
Функция NkKosSetTransportTimeouts()
, объявленная в заголовочном файле transport-kos.h
, позволяет задать для IPC-транспорта максимальное время блокировки системных вызовов Call()
и Recv()
.
Запуск цикла обработки IPC-запросов
Цикл обработки IPC-запроса на сервере включает следующие стадии:
Каждую стадию этого цикла можно выполнять отдельно, последовательно вызывая функции nk_transport_recv()
, диспетчер, nk_transport_reply()
. (Функции nk_transport_recv()
и nk_transport_reply()
объявлены в заголовочном файле sysroot-*-kos/include/nk/transport.h
из состава KasperskyOS SDK.) А можно вызвать функцию NkKosTransport_Dispatch()
или NkKosDoDispatch()
, внутри которых этот цикл выполняется полностью. (Функции NkKosTransport_Dispatch()
и NkKosDoDispatch()
объявлены в заголовочных файлах transport-kos.h
и transport-kos-dispatch.h
соответственно.) Использовать функцию NkKosDoDispatch()
удобнее, поскольку нужно выполнять меньше подготовительных операций (в том числе не требуется инициализировать IPC-транспорт).
Для инициализации структуры, передаваемой функции NkKosDoDispatch()
через параметр info
, можно использовать макросы, определенные в заголовочном файле transport-kos-dispatch.h
.
Функции NkKosTransport_Dispatch()
и NkKosDoDispatch()
можно вызывать из параллельных потоков исполнения, если реализация методов служб потокобезопасна.
Пример использования функции NkKosDoDispatch()
:
/* Функция реализует метод службы. */
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
Функция |
Сведения о функции |
---|---|
|
Назначение Инициализирует IPC-транспорт. Параметры
Возвращаемые значения Нет. |
|
Назначение Инициализирует IPC-транспорт с поддержкой прерывания системных вызовов Параметры
Возвращаемые значения Нет. |
|
Назначение Задает для IPC-транспорта максимальное время блокировки системных вызовов Параметры
Возвращаемые значения Нет. |
|
Назначение Запускает цикл обработки IPC-запросов. Параметры
Возвращаемые значения В случае неуспеха возвращает код ошибки. |
|
Назначение Резервирует участок арены и копирует строку в этот участок. Параметры
Возвращаемые значения В случае успеха возвращает |
Функции transport-kos-dispatch.h
Функция |
Сведения о функции |
---|---|
|
Назначение Запускает цикл обработки IPC-запросов. Параметры
Возвращаемые значения Нет. |