Читать «UNIX: взаимодействие процессов» онлайн - страница 248
Уильям Ричард Стивенс
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
Сервер при этом выведет вот что:
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.8. Передача дескрипторов
Когда мы говорим о передаче открытого дескриптора от одного процесса другому, обычно подразумевается одно из двух: