Инициализация IPC-транспорта для межпроцессного взаимодействия и управление обработкой IPC-запросов (transport-kos.h, transport-kos-dispatch.h)

21 мая 2024

ID libkos_ipc_transport_api

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-сообщений).

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

Нет.

Вам помогла эта статья?
Что нам нужно улучшить?
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!