Перед вызовом door_call клиент устанавливает указатель rbuf на буфер для результатов, a rsize делает равным размеру буфера. После возвращения из функции и data_ptr, и desc_ptr будут указывать на этот буфер. Если он слишком мал для хранения результатов, возвращаемых сервером, библиотека дверей автоматически выделит новый буфер в адресном пространстве клиента с помощью mmap (раздел 12.2) и обновит значения rbuf и rsize соответствующим образом. Поля data_ptr и desc_ptr будут указывать на новый буфер. Клиент отвечает за то, чтобы обнаружить изменение этих указателей и впоследствии освободить занимаемую память вызовом munmap с аргументами rbuf и rsize. Пример будет приведен в листинге 15.4.

<p>15.3. Функция door_create</p>

Процесс-сервер определяет некоторую функцию как процедуру сервера вызовом door_create:

#include door.h

typedef void Door_server_proc(void *cookie, char *dataptr, size_t datasize, door_desc_t *descptr, size_t ndesc);

int door_create(Door_server_proc *proc, void *cookie, u_int attr);

/* Возвращает неотрицательный дескриптор в случае успешного завершения, –1 –в случае ошибки */

Здесь мы добавили наше собственное определение типа, что упрощает прототип функции. Это определение утверждает, что процедуры сервера (например, servproc в листинге 15.2) вызываются с пятью аргументами и ничего не возвращают.

Когда сервер вызывает door_create, первый аргумент (proc) указывает адрес процедуры сервера, которая будет вызываться через дескриптор двери, возвращаемый этим вызовом. При вызове процедуры сервера ее аргумент cookie содержит значение, передаваемое в качестве второго аргумента door_create. Это дает серверу возможность передавать процедуре какой-либо указатель каждый раз, когда эта процедура вызывается клиентом. Следующих четыре аргумента процедуры сервера — dataptr, datasize, descptr и ndesc — описывают аргументы-данные и аргументы-дескрипторы клиента. Они соответствуют первым четырем полям структуры door_arg_t, описанной в предыдущем разделе.

Последний аргумент door_create(attr) описывает специальные атрибуты процедуры сервера и может быть равен либо 0, либо логической сумме двух констант:

■ DOOR_PRIVATE — библиотека дверей автоматически создает новые потоки в процессе-сервере при поступлении запросов от клиентов. По умолчанию эти потоки помещаются в пул потоков и могут использоваться для обслуживания запросов клиентов по всем дверям данного процесса.

Указание атрибута DOOR_PRIVATE говорит библиотеке, что для данной двери следует создать собственный пул потоков, отдельный от пула потоков процесса.

■ DOOR_UNREF — когда количество дескрипторов, открытых для данной двери, изменяется с двух до одного, процедура сервера вызывается со вторым аргументом, имеющим значение DOOR_UNREF_DATA. При этом аргумент descptr представляет собой нулевой указатель, а аргументы datasize и ndesc равны нулю. Мы приведем пример использования этого атрибута в листинге 15.13.

Возвращаемое сервером значение имеет тип void, поскольку процедура сервера никогда не завершает работу вызовом return. Вместо этого процедура должна вызывать door_return (функция описана в следующем разделе).

В листинге 15.2 мы видели, что после получения дескриптора двери вызовом door_create сервер должен вызвать fattach для связывания этого дескриптора с некоторым файлом. Клиент затем может открыть этот файл для получения дескриптора двери, который впоследствии может быть использован при вызове door_call.

ПРИМЕЧАНИЕ

Функция fattach не включена в стандарт Posix.1, но ее наличие требуется стандартом Unix 98. Кроме того, этот стандарт определяет также функцию fdetach, отключающую связь дескриптора и файла, и программу fdetach, вызывающую эту функцию.

Для дескрипторов дверей, создаваемых door_create, устанавливается бит FD_CLOEXEC. Это означает, что дескриптор закрывается при вызове процессом функций типа exec. Что касается вызова fork, несмотря на то что открытые родительским процессом дескрипторы используются дочерним процессом совместно с ним, только родительский процесс будет принимать вызовы от клиентов. Дочерним процессам вызовы не передаются, хотя дескриптор, возвращаемый door_create, и будет в них открыт.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже