Читать «UNIX: взаимодействие процессов» онлайн - страница 236

Уильям Ричард Стивенс

solaris % client1 /tmp/server19

result: 81

solaris % ls -l /tmp/server1

Drw-r-r– 1 rstevens other1 0 Apr 9 10:09 /tmp/server1

Мы получили ожидаемый результат. Вызвав ls, мы видим, что эта пpoгрaммa выводит букву D в начале строки, соответствующей файлу, указывая, что этот файл является дверью.

На рис. 15.2 приведена диaгрaммa работы данного примера. Функция door_call вызывает процедуру на сервере, которая затем вызывает door_return для возврата.

На рис. 15.3 приведена диaгрaммa, показывающая, что в действительности происходит при вызове процедуры в другом процессе на том же узле.

Рис. 15.2. Внешний вид вызова процедуры в другом процессе

На рис. 15.3 выполняются следующие действия:

0. Запускается сервер, вызывает door_create, чтобы создать дескриптор для функции servproc, затем связывает этот дескриптор с именем файла в файловой системе.

1. Запускается клиент и вызывает door_call. Это функция в библиотеке дверей.

2. Библиотечная функция door_call делает системный вызов. При этом указывается процедура, которая должна быть выполнена, а управление передается функции из библиотеки дверей процесса-сервера.

3. Вызывается процедура сервера (servproc в данном примере).

4. Процедура сервера делает все необходимое для обработки запроса клиента и вызывает door_return по завершении работы.

5. Библиотечная функция door_return осуществляет системный вызов, передавая управление ядру.

6. В этом вызове указывается процесс-клиент, которому и передается управление.

Рис. 15.3. Что в действительности происходит при вызове процедуры в другом процессе

Последующие разделы этой главы описывают интерфейс дверей (doors API) более подробно, с множеством примеров. В приложении А мы убедимся, что двери представляют собой наиболее быструю форму IPC (при измерении времени ожидания).

15.2. Функция door_call

Функция door_call вызывается клиентом для обращения к процедуре сервера, выполняемой в адресном пространстве процесса-сервера:

#include <door.h>

int door_call(int fd, door_arg_t *argp);

/* Возвращает 0 в случае успешного завершения. –1 – в случае ошибки */

Дескриптор fd обычно возвращается функцией open (см. листинг 15.1). Полное имя файла, открываемого клиентом, однозначно идентифицирует процедуру сервера, которая вызывается door_call при передаче дескриптора.

Второй аргумент — argp — указывает на структуру, описывающую аргументы и приемный буфер для возвращаемых значений:

typedef struct door_arg {

 char *data_ptr; /* при вызове указывает на аргументы, при возврате – на результаты */

 size_t data_size; /* при вызове определяет общий размер аргументов в байтах, при возврате – общий размер возвращаемых данных в байтах */

 door_desc_t *desc_ptr; /* при вызове указывает на аргументы-дескрипторы, при возврате указывает на возвращаемые дескрипторы */

 size_t desc_num; /* при вызове задает количество аргументов-дескрипторов, при возврате задает количество возвращаемых дескрипторов */

 char *rbuf; /* указатель на буфер результатов */