Мы оставляем 6-секундную паузу и выводим сообщение о возврате из процедуры сервера. Запустим сервер в одном окне, а из другого проверим существование имени файла двери в файловой системе и удалим его с помощью rm: После удаления имени файла происходит специальный вызов процедуры сервера: Если мы проследим за количеством ссылок на эту дверь, то увидим следующее: одна ссылка появляется после вызова door_create, вторая — после fattach. После удаления файла с помощью rm количество ссылок снова уменьшается до единицы, что приводит к специальному вызову процедуры. В последнем примере использования этого атрибута мы снова удалим имя из файловой системы. Но на этот раз мы сначала запустим три экземпляра программы-клиента. Специальный вызов процедуры произойдет только после завершения последнего клиента, потому что каждый экземпляр клиента увеличивает количество ссылок на дверь. Используем сервер из листинга 15.14 и клиент из листинга 15.2. Сервер при этом выведет вот что: Проследим за значением счетчика открытых ссылок для этой двери. Он становится равным 1 после вызова door_create, 2 после вызова fattach. Когда три клиента вызывают open, счетчик увеличивается с 2 до 5. После удаления имени файла счетчик уменьшается до 4. После завершения работы трех клиентов счетчик уменьшается с 4 до 1 (последовательно), и последнее его изменение с 2 до 1 приводит к специальному вызову процедуры. Этими примерами мы показали, что хотя описание атрибута DOOR_UNREF выглядит просто («специальный вызов происходит при изменении счетчика ссылок с 2 до 1»), мы должны понимать принципы работы этого счетчика, чтобы им пользоваться.Листинг 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 }
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 после удаления файла из файловой системы
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