KasperskyOS API > Библиотека libkos > Инициализация IPC-транспорта для межпроцессного взаимодействия и управление обработкой IPC-запросов (transport-kos.h, transport-kos-dispatch.h)
Инициализация IPC-транспорта для межпроцессного взаимодействия и управление обработкой IPC-запросов (transport-kos.h, transport-kos-dispatch.h)
API определены в заголовочных файлах transport-kos.h и transport-kos-dispatch.h из состава KasperskyOS SDK, которые расположены по пути sysroot-*-kos/include/coresrv/nk.
Возможности API:
Инициализировать IPC-транспорт на стороне клиента и на стороне сервера.
Инициализация IPC-транспорта для межпроцессного взаимодействия
Чтобы инициализировать IPC-транспорт для взаимодействия с другими процессами, нужно вызвать функцию NkKosTransport_Init() или NkKosTransportSync_Init(), объявленные в заголовочном файле transport-kos.h.
Пример использования функции NkKosTransport_Init() на стороне клиента:
intmain(int argc, constchar *argv[]){
/* Объявить структуру с параметрами IPC-транспорта */
NkKosTransport driver_transport;
/* Объявить прокси-объект. (Тип прокси-объекта является автоматически
* сгенерированным транспортным кодом.) */structFileIface_proxy file_operations_proxy;
/* Объявить структуры для сохранения фиксированной части IPC-запроса и
* IPC-ответа для метода службы. (Типы структур являются автоматически
* сгенерированным транспортным кодом.) */structFileIface_Open_req req;
structFileIface_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() на стороне сервера:
intmain(int argc, constchar *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-запроса на сервере включает следующие стадии:
Получение IPC-запроса.
Обработка IPC-запроса.
Отправка IPC-ответа.
Каждую стадию этого цикла можно выполнять отдельно, последовательно вызывая функции nk_transport_recv(), диспетчер, nk_transport_reply(). (Функции nk_transport_recv() и nk_transport_reply() объявлены в заголовочном файле sysroot-*-kos/include/nk/transport.h из состава KasperskyOS SDK.) А можно вызвать функцию NkKosTransport_Dispatch(), NkKosDoDispatch() или NkKosDoDispatchEx(), внутри которых этот цикл выполняется полностью. (Функция NkKosTransport_Dispatch() объявлена в заголовочном файле transport-kos.h, функции NkKosDoDispatch() и NkKosDoDispatchEx() объявлены в заголовочном файле transport-kos-dispatch.h.) Использовать функцию NkKosDoDispatch() или NkKosDoDispatchEx() удобнее по сравнению с функцией NkKosTransport_Dispatch(), поскольку нужно выполнять меньше подготовительных операций (в том числе не требуется инициализировать IPC-транспорт).
Для инициализации структуры, передаваемой функции NkKosDoDispatch() или NkKosDoDispatchEx() через параметр info, можно использовать макросы, определенные в заголовочном файле transport-kos-dispatch.h. Используя параметр syncHandle функции NkKosDoDispatchEx(), можно прерывать системный вызовRecv(). Через параметр cb функции NkKosDoDispatchEx() можно задать callback-функции, вызываемые после выполнения системных вызовов Recv() и Reply(), а также после выхода из цикла обработки IPC-запросов (все функции задавать не требуется). Callback-функция, соответствующая указателю enterDispatchProcessing, вызывается сразу после выполнения системного вызова Recv(). Callback-функция, соответствующая указателю leaveDispatchProcessing, вызывается сразу после выполнения системного вызова Reply(). Callback-функция, соответствующая указателю stopDispatchLoop, вызывается сразу после выхода из цикла обработки IPC-запросов. Каждой из этих callback-функций передается указатель callbackContext. Эти callback-функции могут использоваться, например, в реализации пула потоков исполнения.
Функции NkKosTransport_Dispatch(), NkKosDoDispatch() и NkKosDoDispatchEx() можно вызывать из параллельных потоков исполнения, если реализация методов служб потокобезопасна.
Пример использования функции NkKosDoDispatch():
/* Функция реализует метод службы. */staticnk_err_tOpen_impl(...){
...
}
/* Функция реализует метод службы. */staticnk_err_tRead_impl(...){
...
}
/* Функция инициализирует указатели на функции, реализующие методы службы.
* (Эти указатели используются диспетчером для вызова функций, реализующих
* методы службы. Типы структур являются автоматически сгенерированным
* транспортным кодом.) */staticstructFileIface *CreateFileOperations()
{
staticconststructFileIface_ops ops = {
.Open = Open_impl,
.Read = Read_impl
};
staticstructFileIface impl = {
.ops = &ops
};
return &impl;
}
intmain(int argc, constchar *argv[]){
...
/* Объявить структуру, которая требуется функции
* NkKosDoDispatch() для использования транспортного кода. */
NkKosDispatchInfo info;
/* Объявить стабы. (Типы стабов являются автоматически сгенерированным
* транспортным кодом. */structOperations_component component;
structFsDriver_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():
/* Функция реализует метод службы. */staticnk_err_tOpen_impl(...){
...
}
/* Функция реализует метод службы. */staticnk_err_tRead_impl(...){
...
}
/* Функция инициализирует указатели на функции, реализующие методы службы.
* (Эти указатели используются диспетчером для вызова функций, реализующих
* методы службы. Типы структур являются автоматически сгенерированным
* транспортным кодом.) */staticstructFileIface *CreateFileOperations()
{
staticconststructFileIface_ops ops = {
.Open = Open_impl,
.Read = Read_impl
};
staticstructFileIface impl = {
.ops = &ops
};
return &impl;
}
intmain(int argc, constchar *argv[]){
...
/* Объявить структуру с параметрами IPC-транспорта */
NkKosTransport transport;
/* Объявить стабы. (Типы стабов являются автоматически сгенерированным
* транспортным кодом. */structOperations_component component;
structFsDriver_entity entity;
/* Объявить объединения фиксированной части IPC-запросов и
* IPC-ответов. (Типы объединений являются автоматически сгенерированным
* транспортным кодом.) */unionFsDriver_entity_req req;
unionFsDriver_entity_res res;
/* Объявить массив для арены IPC-ответов. (Размер массива является
* автоматически сгенерированным транспортным кодом.) */char res_buffer[FsDriver_entity_res_arena_size];
/* Объявить и инициализировать дескриптор арены IPC-ответов.
* (Тип дескриптора и макрос его инициализации определены в заголовочном файле
* sysroot-*-kos/include/nk/arena.h из состава KasperskyOS SDK.) */structnk_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():
[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-сообщений).
Возвращаемые значения
Нет.
NkKosDoDispatchEx()
Назначение
Запускает цикл обработки IPC-запросов.
Параметры
[in] h – серверный IPC-дескриптор.
[in] info – указатель на структуру, содержащую данные, которые требуются функции для использования транспортного кода (включая имена типов, размеры фиксированной части и арены IPC-сообщений).
[in,optional] cb – указатель на структуру, содержащую указатели на callback-функции, вызываемые после выполнения системных вызовов Recv() и Reply(), а также после выхода из цикла обработки IPC-запросов. Помимо указателей на callback-функции эта структура содержит указатель, который передается этим callback-функциям при вызове. В параметре можно указать RTL_NULL, если не требуется задавать callback-функции.
[in,optional] syncHandle – дескриптор объекта синхронизации IPC или INVALID_HANDLE, если прерывание системного вызова Recv() не требуется.
Возвращаемые значения
Нет.
Идентификатор статьи: libkos_ipc_transport_api, Последнее изменение: 27 янв. 2025 г.