KasperskyOS Community Edition 1.2

Инициализация 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-сообщений).

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

Нет.