Читать «UNIX: взаимодействие процессов» онлайн - страница 247
Уильям Ричард Стивенс
Первый пример показывает, что если сервер закрывает свой дескриптор после вызова fattach, немедленно происходит специальный вызов процедуры сервера. В листинге 15.13 приведен текст процедуры сервера и функции main.
Листинг 15.13. Процедура сервера, обрабатывающая специальный вызов
//doors/serverunref1.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 Door_return((char *)&result, sizeof(result), NULL, 0);
16 }
17 int
18 main(int argc, char **argv)
19 {
20 int fd;
21 if (argc != 2)
22 err_quit("usage: server1 <server-pathname>");
23 /* создание дескриптора и связывание с файлом */
24 fd = Door_create(servproc, NULL, DOOR_UNREF);
25 unlink(argv[1]);
26 Close(Open(argv[1], O_CREAT | O_RDWR, FILE_MODE));
27 Fattach(fd, argv[1]);
28 Close(fd);
29 /* процедура servproc() обрабатывает все запросы клиентов */
30 for(;;)
31 pause();
32 }
7-10 Процедура сервера распознает специальный вызов и выводит сообщение об этом. Возврат из специального вызова происходит путем вызова door_return с двумя нулевыми указателями и нулевыми значениями размеров.
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");