Содержание
Транспортный код на языке C++
Перед чтением этого раздела, нужно ознакомиться со сведениями о механизме IPC в KasperskyOS и об IDL-, CDL-, EDL-описаниях.
Чтобы реализовать взаимодействие процессов, необходим транспортный код, отвечающий за формирование, отправку, прием и обработку IPC-сообщений.
У разработчика решения на базе KasperskyOS нет необходимости самостоятельно писать транспортный код. Вместо этого можно использовать специальные инструменты и библиотеки, поставляемые в составе KasperskyOS SDK. Эти библиотеки позволяют разработчику компонента решения сгенерировать транспортный код на основе IDL-, CDL-, EDL-описаний, относящихся к этому компоненту.
Транспортный код
Для генерации транспортного кода на языке C++ в составе KasperskyOS SDK поставляется компилятор nkppmeta
.
Компилятор nkppmeta
позволяет генерировать транспортные C++ прокси-объекты (proxy) и стабы (stub) для использования как клиентом, так и сервером.
Прокси-объекты используются клиентом для упаковки параметров вызываемого метода в IPC-запрос, выполнения IPC-запроса и распаковки IPC-ответа.
Стабы используются сервером для распаковки параметров из IPC-запроса, диспетчеризации вызова на соответствующую реализацию метода и упаковки IPC-ответа.
Генерация транспортного кода для разработки на C++
Для генерации транспортных прокси-объектов и стабов с помощью генератора nkppmeta
при сборке решения используются CMake
-команды add_nk_idl(), add_nk_cdl() и add_nk_edl().
Типы С++ в файле *.idl.cpp.h
Каждый интерфейс определяется в IDL-описании. Это описание задает имя интерфейса, сигнатуры интерфейсных методов и типы данных для параметров интерфейсных методов.
Для генерации транспортного кода при сборке решения используются CMake
-команда add_nk_idl(), которая создает CMake
-цель для генерации заголовочных файлов для заданного IDL-файла при помощи компилятора nkppmeta
.
Генерируемые заголовочные файлы содержат представление на языке C++ для интерфейса и типов данных, описанных в IDL-файле, а также методы, необходимые для использования прокси-объектов и стабов.
Соответствие типов данных, объявленных в IDL-файле, типам C++ приведены в таблице ниже.
Соответствие типов IDL типам C++
Тип IDL |
Тип С++ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Работа с транспортным кодом на C++
Сценарии разработки клиента и сервера, которые обмениваются IPC-сообщениями, представлены в разделах "Статическое создание IPC-каналов при разработке на языке C++" и "Динамическое создание IPC-каналов при разработке на языке C++"
В началоСтатическое создание IPC-каналов при разработке на языке C++
Чтобы реализовать клиентскую программу, вызывающую метод службы, предоставляемой серверной программой, необходимо:
- Подключить сгенерированный заголовочный файл описания (
*.edl.cpp.h
) клиентской программы. - Подключить сгенерированные заголовочные файлы описаний используемых интерфейсов (
*.idl.cpp.h
). - Подключить заголовочные файлы:
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/application.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/api.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/connect_static_channel.h
- Инициализировать объект приложения, вызвав функцию
kosipc::MakeApplicationAutodetect()
. (Также можно использовать функцииkosipc::MakeApplication()
иkosipc::MakeApplicationPureClient()
.) - Получить клиентский IPC-дескриптор канала и идентификатор службы (
riid
) вызвав функциюkosipc::ConnectStaticChannel()
.Функция принимает имя IPC-канала (из файла init.yaml) и квалифицированное имя службы (из CDL- и EDL-описаний компонента решения).
- Инициализировать прокси-объект для используемой службы, вызвав функцию
MakeProxy()
.
Пример
Чтобы реализовать серверную программу, предоставляющую службы другим программам, необходимо:
- Подключить сгенерированный заголовочный файл
*.edl.cpp.h
, содержащий описание компонентной структуры программы, включая все предоставляемые службы. - Подключить заголовочные файлы:
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/event_loop.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/api.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/serve_static_channel.h
- Создать классы, содержащие реализации интерфейсов, которые данная программа и её компоненты предоставляют в виде служб.
- Инициализировать объект приложения, вызвав функцию
kosipc::MakeApplicationAutodetect()
. - Инициализировать структуру
kosipc::components::Root
, которая описывает компонентную структуру программы и описания интерфейсов всех предоставляемых программой служб. - Связать поля структуры
kosipc::components::Root
с объектами, реализующими соответствующие службы.Поля структуры
Root
повторяют иерархию компонентов и служб, заданную совокупностью CDL- и EDL-файлов. - Получить серверный IPC-дескриптор канала, вызвав функцию
ServeStaticChannel()
.Функция принимает имя IPC-канала (из файла init.yaml) и структуру, созданную на шаге 5.
- Создать объект
kosipc::EventLoop
, вызвав функциюMakeEventLoop()
. - Запустить цикл диспетчеризации входящих IPC-сообщений, вызвав метод
Run()
объектаkosipc::EventLoop
.
Пример
Динамическое создание IPC-каналов при разработке на языке C++
Динамическое создание IPC-канала на стороне клиента включает следующие шаги:
- Подключить к клиентской программе сгенерированный заголовочный файл описания (
*.edl.cpp.h
). - Подключить сгенерированные заголовочные файлы описаний используемых интерфейсов (
*.idl.cpp.h
). - Подключить заголовочные файлы:
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/application.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/make_application.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/connect_dynamic_channel.h
- Получить указатели на имя сервера и квалифицированное имя службы с помощью сервера имен – специального сервиса ядра, представленного программой
NameServer
. Для этого необходимо подключиться к серверу имен вызовом функцииNsCreate()
и найти сервер, предоставляющий требуемую службу, используя функциюNsEnumServices()
. Подробнее см. "Динамическое создание IPC-каналов (cm_api.h, ns_api.h)". - Создать объект приложения, вызвав функцию
kosipc::MakeApplicationAutodetect()
. (Также можно использовать функцииkosipc::MakeApplication()
иkosipc::MakeApplicationPureClient()
.) - Создать прокси-объект для требуемой службы, вызвав функцию
MakeProxy()
. В качестве входного параметра функцииMakeProxy()
использовать вызов функцииkosipc::ConnectDynamicChannel()
. В функциюkosipc::ConnectDynamicChannel()
передать указатели на имя сервера и квалифицированное имя службы, полученные на шаге 4.
После успешной инициализации прокси-объекта клиенту доступен вызов методов требуемой службы.
Пример
Динамическое создание IPC-канала на стороне сервера включает следующие шаги:
- Подключить к серверной программе сгенерированный заголовочный файл (
*.edl.cpp.h
), содержащий описание компонентной структуры сервера, включая все предоставляемые службы. - Подключить заголовочные файлы:
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/application.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/event_loop.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/make_application.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/root_component.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/serve_dynamic_channel.h
/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/simple_connection_acceptor.h
- Создать классы, содержащие реализации интерфейсов, которые сервер предоставляет в виде служб. Создать и инициализировать объекты этих классов.
- Создать объект приложения, вызвав функцию
kosipc::MakeApplicationAutodetect()
. - Создать и инициализировать объект класса
kosipc::components::Root
, который описывает структуру компонентов и служб сервера. Эта структура генерируется из описаний в CDL- и EDL-файлах. - Cвязать объект класса
kosipc::components::Root
с объектами классов, созданными на шаге 3. - Создать и инициализировать объект класса
kosipc::EventLoop
, который реализует цикл диспетчеризации входящих IPC-сообщений, вызвав функциюMakeEventLoop()
. В качестве входного параметра функцииMakeEventLoop()
использовать вызов функцииServeDynamicChannel()
. В функциюServeDynamicChannel()
передать объект классаkosipc::components::Root
, созданный на шаге 5. - Запустить цикл диспетчеризации входящих IPC-сообщений в отдельном потоке, вызвав метод
Run()
объектаkosipc::EventLoop
. - Создать и инициализировать объект, который реализует обработчик приема входящих запросов на динамическое создание IPC-канала.
При создании объекта можно использовать класс
kosipc::SimpleConnectionAcceptor
, который является стандартной реализацией интерфейсаkosipc::IConnectionAcceptor
. (Интерфейсkosipc::IConnectionAcceptor
определен в файле/opt/KasperskyOS-Community-Edition-<version>/sysroot-*-kos/include/kosipc/connection_acceptor.h
.) В этом случае обработчик будет реализовать следующую логику: если запрашиваемая клиентом служба опубликована на сервере, то запрос от клиента будет принят, иначе отклонен.Если необходимо создать собственный обработчик, то следует реализовать свою логику обработки запросов в методе
OnConnectionRequest()
, унаследованном от интерфейсаkosipc::IConnectionAcceptor
. Этот метод будет вызываться сервером при получении от клиента запроса на динамическое создание IPC-канала. - Создать объект класса
kosipc::EventLoop
, который реализует цикл приема входящих запросов на динамическое создание IPC-канала, вызвав функциюMakeEventLoop()
. В качестве входного параметра функцииMakeEventLoop()
использовать вызов функцииServeConnectionRequests()
. В функциюServeConnectionRequests()
передать объект, созданный на шаге 9.Цикл приема входящих запросов на динамическое создание IPC-канала может быть только один. Цикл должен работать в одном потоке. Цикл приема входящих запросов на динамическое создание IPC-канала должен быть создан после создания цикла диспетчеризации входящих IPC-сообщений (см. на шаг 7).
- Запустить цикл приема входящих запросов на динамическое соединение в текущем потоке, вызвав метод
Run()
объектаkosipc::EventLoop
.
Пример
При необходимости можно создать и инициализировать несколько объектов класса kosipc::components::Root
, объединенных в список объектов типа ServiceList
с помощью метода AddServices()
. Использование нескольких объектов позволяет, например, разделять компоненты и службы сервера на группы или публиковать службы под разными именами.
Пример