на главную | войти | регистрация | DMCA | контакты | справка | donate |      

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я


моя полка | жанры | рекомендуем | рейтинг книг | рейтинг авторов | впечатления | новое | форум | сборники | читалки | авторам | добавить





Листинг 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 ");

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

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

solaris % serverunref2 /tmp/door2

thread id 4, arg = 44

thread id 5, arg = 55

thread id 6, arg = 66

thread id 4 returning

thread id 5 returning

thread id 6 returning

door unreferenced

Проследим за значением счетчика открытых ссылок для этой двери. Он становится равным 1 после вызова door_create, 2 после вызова fattach. Когда три клиента вызывают open, счетчик увеличивается с 2 до 5. После удаления имени файла счетчик уменьшается до 4. После завершения работы трех клиентов счетчик уменьшается с 4 до 1 (последовательно), и последнее его изменение с 2 до 1 приводит к специальному вызову процедуры.

Этими примерами мы показали, что хотя описание атрибута DOOR_UNREF выглядит просто («специальный вызов происходит при изменении счетчика ссылок с 2 до 1»), мы должны понимать принципы работы этого счетчика, чтобы им пользоваться.


Листинг 15.13. Процедура сервера, обрабатывающая специальный вызов | UNIX: взаимодействие процессов | 15.8. Передача дескрипторов