Чтение онлайн

ЖАНРЫ

UNIX: взаимодействие процессов

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

Шрифт:

typedef struct doo_info {

 pid_t di_target; /* идентификатор процесса сервера */

 door_ptr_t di_proc; /* процедура сервера */

 door_ptr_t di_data; /* принимаемые процедурой сервера данные */

 door_attr_t di_attributes; /* атрибуты, связанные с данной дверью */

 door_id_t di_uniquifier; /* уникальный номер двери */

} door info t;

Поле di_target содержит идентификатор процесса сервера, a di_proc — адрес процедуры сервера в процессе (от которого клиенту, вообще говоря, пользы мало).

Указатель, передаваемый процедуре сервера в качестве первого аргумента (cookie), возвращается клиенту в поле di_data.

Текущие атрибуты двери помещаются в поле di_attributes, и два из них уже были описаны в разделе 15.3. Это атрибуты DOOR_PRIVATE и DOOR_UNREF. Два других атрибута называются DOOR_LOCAL (процедура является локальной для данного процесса) и DOOR_REVOKE (сервер аннулировал процедуру, связанную с этой дверью, вызвав door_revoke).

Каждой двери при создании сопоставляется уникальный в пределах системы номер, который возвращается в поле di_uniquifier.

Эта функция обычно вызывается клиентом для получения информации о сервере. Однако она может быть вызвана и из процедуры сервера, причем первым аргументом в этом случае должна быть константа DOOR_QUERY. Тогда функция возвратит информацию о вызвавшем потоке, то есть о данном экземпляре процедуры сервера. В этом случае адреса процедуры сервера и принимаемых аргументов (di_proc и di_data) могут представлять интерес.

15.7. Примеры

В этом разделе мы приведем примеры использования пяти только что описанных функций.

Функция door_info

В листинге 15.3 приведен текст программы, открывающей дверь и вызывающей door_infо для получения информации об этой двери, которая затем выводится на экран.

Листинг 15.3. Вывод информации о двери

//doors/doorinfo.c

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5 int fd;

6 struct stat stat;

7 struct door_info info;

8 if (argc != 2)

9 err_quit("usage; doorinfo <pathname>");

10 fd = Open(argv[1], O_RDONLY);

11 Fstat(fd, &stat);

12 if (S_ISDOOR(stat.st_mode) == 0)

13 err_quit("pathname is not a door");

14 Door_info(fd, &info);

15 printf("server PID = %ld, uniquifier = %ld",

16 (long)info.di_target, (long)info.di_uniquifier);

17 if (info.di_attributes & DOOR_LOCAL)

18 printf(", DOOR_LOCAL");

19 if (info.di_attributes & DOOR_PRIVATE)

20 printf(", DOOR_PRIVATE");

21 if (info.di_attributes & DOOR_REVOKED)

22 printf(", DOOR_REVOKED");

23 if (info.di_attributes & DOOR_UNREF)

24 printf(", DOOR_UNREF");

25 printf("\n");

26 exit(0);

27 }

Сначала программа открывает файл с указанным полным именем и проверяет, что это действительно дверь. Поле st_mode структуры stat в

этом случае должно содержать такое значение, что макрос S_ISDOOR будет возвращать значение «истина». Затем вызывается функция door_info.

Сначала мы укажем этой программе полное имя файла, не являющегося дверью, а затем попробуем получить информацию о двух встроенных дверях Solaris 2.6:

solaris % doorinfo/etc/passwd

pathname is not a door

solaris % doorinfo /etc/.name_service_door

server PID = 308, uniquifier = 18, DOOR_UNREF

solaris % doorinfo /etc/.syslog_door

server PID = 282, uniquifier = 1635

solaris % ps –f -p 308

root 308 1 0 Apr 01 ? 0:34 /usr/sbin/nscd

solaris % ps –f -p 282

root 282 1 0 Apr 01 ? 0:10 /usr/sbin/syslogd –n –z 14

Команду ps мы используем для того, чтобы узнать, какая программа выполняется с идентификатором, возвращаемым door_info.

Буфер результатов слишком мал

Когда мы рассказывали о функции door_call, мы отметили, что если буфер результатов оказывается слишком мал, библиотека дверей осуществляет автоматическое выделение нового буфера. Сейчас мы покажем это на примере. В листинге 15.4 приведен текст новой программы-клиента, которая представляет собой измененную версию листинга 15.2.

Листинг 15.4. Вывод адреса полученного результата

//doors/client2.c

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5 int fd;

6 long ival, oval;

7 door_arg_t arg;

8 if (argc != 3)

9 err_quit("usage: client2 <server-pathname> <integer-value>");

10 fd = Open(argv[1], O_RDWR); /* открываем дверь */

11 /* подготовка аргументов и указателя на результат */

12 ival = atol(argv[2]);

13 arg.data_ptr = (char *) &ival; /* аргументы-данные */

14 arg.data_size = sizeof(long); /* объем данных */

15 arg.desc_ptr = NULL;

16 arg.desc_num = 0;

17 arg.rbuf = (char *) &oval; /* возвращаемые данные */

18 arg.rsize = sizeof(long); /* объем возвращаемых данных */

19 /* вызов процедуры сервера и вывод результата */

20 Door_call(fd, &arg);

21 printf("&oval = %p, data_ptr = %p, rbuf = %p, rsize = %d\n",

22 &oval, arg.data_ptr, arg.rbuf, arg.rsize);

23 printf("result: %ld\n", *((long *) arg.data_ptr));

24 exit(0);

25 }

19-22 В этой версии программы на экран выводится адрес переменной oval, содержимое указателя data_ptr, который должен указывать на возвращаемые функцией door_call данные, и адрес и размер приемного буфера (rbuf и rsize).

Поделиться с друзьями: