KasperskyOS Community Edition 1.0

Группы каналов

Каналы, в которых сущность выступает сервером, могут быть объединены в одну или несколько групп.

Каждой группе каналов соответствует свой слушающий дескриптор (listener handle).

Два IPC-канала имеют одинаковое имя "second_connection_to_A" и объединены в группу. Еще один канал с именем "first_connection_to_A" не входит в эту группу. Обозначения: cl_1, cl_2, cl_3 — клиентские IPC-дескрипторы; srv_1 — серверный IPC-дескриптор; ls_1 — слушающий IPC-дескриптор.

Слушающий дескриптор позволяет серверу принимать запросы сразу по всем каналам из группы. При этом нет необходимости создавать отдельный поток на каждый канал — достаточно в одном потоке сервера выполнить системный вызов Recv(), указав слушающий дескриптор.

Создание группы каналов с помощью init-описания

Чтобы каналы образовали группу, они должны соединяться с одной серверной сущностью и иметь одинаковые имена. Например, чтобы получить систему каналов, изображенную выше, можно использовать следующее init-описание:

init.yaml

entities:

# Сущность "A" выступает как сервер, поэтому ее список соединений пуст.

- name: A

# Сущность "B" будет соединена сущностью "A" двумя разными каналами.

- name: B

connections:

- target: A

id: first_connection_to_A

- target: A

id: second_connection_to_A

# Сущность "С" будет соединена с сущностью "A" каналом с именем

# "second_connection_to_A". Два канала с одинаковыми именами будут объединены

# в группу: на стороне сущности "A" они будут иметь один и тот же

# IPC-дескриптор (слушающий дескриптор ls_1).

- name: C

connections:

- target: A

id: second_connection_to_A

Обмен сообщениями в случае группы каналов

Рассмотрим, как происходит обмен сообщениями для группы каналов, описанной выше.

Клиентские сущности B и C получают значение клиентского дескриптора по имени соединения first_connection_to_A и отправляют запрос:

entity_B.c, entity_C.c

// Получение клиентского IPC-дескриптора cl, соответствующего соединению " second_connection_to_A".

Handle cl = ServiceLocatorConnect("second_connection_to_A");

// Отправка запроса

Call(cl, &RequestBuffer, &ResponseBuffer);

Оба используемых канала имеют одно имя — second_connection_to_A. Однако по этому имени сущности B и C получат разные значения дескрипторов: сущность B получит значение cl_2, а сущность C — значение cl_3.

Серверная сущность A получает значение слушающего дескриптора ls_1. Далее сущность A ожидает запросы по двум каналам сразу (от B и от C), используя дескриптор ls_1. После получения и обработки запроса сущность A отравляет ответ, используя дескриптор ls_1. Ответ будет отправлен тому клиенту, который инициировал запрос:

entity_A.c

nk_iid_t iid;

// Получение слушающего дескриптора ls_1, соответствующего соединению

"second_connection_to_A"

Handle ls_1 = ServiceLocatorRegister("second_connection_to_A", NULL, 0, &iid);

// Ожидание запроса от сущности B или C

Recv(ls_1, &RequestBuffer);

// Обработка поступившего запроса

// Отправка ответа тому клиенту, от которого пришел запрос

Reply(ls_1, &ResponseBuffer);