28 Теперь мы закрываем дескриптор двери после выполнения fattach. Этот дескриптор может быть нужен серверу только для вызовов door_bind, doo_info и door_revoke.

Запустив сервер, мы увидим, что немедленно произойдет специальный вызов:

solaris % serverunref1 /tmp/door1

door unreferenced

Если мы проследим за значением счетчика открытых дескрипторов, мы увидим, что он становится равен 1 после возврата из door_create и 2 после возврата из fattach. Вызов close уменьшает количество открытых дескрипторов с двух до одного, что приводит к специальному вызову процедуры. Единственная оставшаяся ссылка при этом представляет собой имя в файловой системе, а этого клиенту достаточно, чтобы обратиться к двери. Поэтому клиент продолжает работать правильно:

solaris % clientunref1 /tmp/door1 11

result: 121

solaris % clientunref1 /tmp/door1 22

result: 484

Более того, дальнейших специальных вызовов серверной процедуры не происходит. Для каждой двери осуществляется только один специальный вызов.

Теперь изменим нашу программу-сервер обратно, убрав вызов close для дескриптора двери. Процедура сервера и функция main приведены в листинге 15.14.

Листинг 15.14. Сервер, не закрывающий дескриптор двери

//doors/serverunref2.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   if (dataptr == DOOR_UNREF_DATA) {

8    printf("door unreferenced\n");

9    Door_return(NULL, 0, NULL, 0);

10  }

11  arg = *((long *)dataptr);

12  printf("thread id %ld, arg = %ld\n", pr_thread_id(NULL), arg);

13  sleep(6);

14  result = arg * arg;

15  printf("thread id %ld returning\n", pr_thread_id(NULL));

16  Door_return((char *)result, sizeof(result), NULL, 0);

17 }

18 int

19 main(int argc, char **argv)

20 {

21  int fd;

23  if (argc != 2)

24   err_quit("usage: server1 server-pathname");

25  /* создание двери, дескриптора и подключение к файлу */

26  fd = Door_create(servproc, NULL, DOOR_UNREF);

27  unlink(argv[1]);

28  Close(Open(argv[1], O_CREAT | O_RDWR, FILE_MODE));

29  Fattach(fd, argv[1]);

30  /* servproc обрабатывает все запросы клиентов */

31  for(;;)

32   pause;

33 }

Мы оставляем 6-секундную паузу и выводим сообщение о возврате из процедуры сервера. Запустим сервер в одном окне, а из другого проверим существование имени файла двери в файловой системе и удалим его с помощью rm:

solaris % ls –l /tmp/door2

Drw-r--r-- 1 rstevens other1 0 Apr 16 08:58 /tmp/door2

solaris % rm /tmp/door2

После удаления имени файла происходит специальный вызов процедуры сервера:

solaris % serverunref2 /trap/door2

door unreferenced после удаления файла из файловой системы

Если мы проследим за количеством ссылок на эту дверь, то увидим следующее: одна ссылка появляется после вызова door_create, вторая — после fattach. После удаления файла с помощью rm количество ссылок снова уменьшается до единицы, что приводит к специальному вызову процедуры.

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

solaris % clientunref2 /tmp/door2 44 clientunref2 /tmp/door2 55 clientunref2/tmp/door2 55

[2] 13552

[3] 13553

[4] 13554

solaris % rm /tmp/door2 клиенты все еще выполняются

solaris % result: 1936

result: 3025

result: 4356

Сервер при этом выведет вот что:

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