Читать «UNIX: взаимодействие процессов» онлайн - страница 235
Уильям Ричард Стивенс
Подготовка аргументов и указателя на результат
11-18 Структура arg содержит указатели на аргументы и результат. Поле data_ptr указывает на первый байт аргументов, a data_size содержит количество байтов в аргументах. Два поля desc_ptr и desc_num предназначены для передачи дескрипторов, о чем мы будем подробно говорить в разделе 15.8. rbuf указывает на первый байт буфера результата, a rsize задает его размер.
Вызов процедуры на сервере и вывод результата
19-21 Мы вызываем процедуру на сервере с помощью door_call; аргументами этого вызова являются дескриптор двери и указатель на структуру аргументов. После возвращения из этого вызова программа печатает получившийся результат.
Программа-сервер приведена в листинге 15.2. Она состоит из процедуры сервера с именем servproc и функции main.
Листинг 15.2. Сервер, возводящий длинное целое в квадрат
//doors/server1.c
1 #include "unpipc.h"
2 void
3 servproc(void *cookie, char *dataptr, size_t datasize,
4 door_desc_t *descptr, size_t ndesc)
5 {
6 long arg, result;
7 arg = *((long *) dataptr);
8 result = arg * arg;
9 Door_return((char *) &result, sizeof(result), NULL, 0);
10 }
11 int
12 main(int argc, char **argv)
13 {
14 int fd;
15 if (argc != 2)
16 err_quit("usage: server1 <server-pathname>");
17 /* создание двери и связывание ее с файлом */
18 fd = Door_create(servproc, NULL, 0);
19 unlink(argv[1]);
20 Close(Open(argv[1], O_CREAT | O_RDWR, FILE_MODE));
21 Fattach(fd, argv[1]);
22 /* функция servproc() обрабатывает все запросы клиентов */
23 for (;;)
24 pause();
25 }
Процедура сервера
2-10 Процедура сервера вызывается с пятью аргументами, но мы используем только один из них — dataptr. Он указывает на первый байт аргумента. Аргумент, представляющий собой длинное целое, передается через этот указатель и возводится в квадрат. Управление передается клиенту вместе с результатом вызовом door_return. Первый аргумент указывает на результат, второй задает его размер, а оставшиеся предназначены для возврата дескрипторов.
Создание дескриптора двери и связывание с ним файла
17-21 Дескриптор двери создается вызовом door_create. Первый аргумент является указателем на функцию, соответствующую этой двери (servproc). После получения этого дескриптора его нужно связать с некоторым именем в файловой системе, поскольку оно будет использоваться клиентом для подключения к этой двери. Делается это путем создания обычного файла в файловой системе (сначала мы вызываем unlink, на тот случай, если такой файл уже существует, причём возможная ошибка игнорируется) и вызова fattach — функции SVR4, связывающей дескриптор с полным именем файла.
Главный поток сервера ничего не делает
22-24 Главный поток сервера блокируется при вызове pause. Вся функциональность обеспечивается функцией servproc, которая будет запускаться как отдельный поток каждый раз при получении запроса клиента.
Запустим сервер в отдельном окне:
solaris % server1 /tmp/server1
После этого запустим пpoгрaммy-клиeнт в другом окне, указав в качестве аргумента то же полное имя, которое было указано при вызове сервера: