Читать «UNIX: взаимодействие процессов» онлайн - страница 256
Уильям Ричард Стивенс
solaris % client6 /tmp/door6 11
result: 121
solaris % client6 /tmp/door6 22
result: 484
solaris % client6 /tmp/door6 33
result: 1089
Посмотрим, что при этом выводит сервер. При поступлении первого запроса клиента создается новый поток (с идентификатором потока 5), а поток с номером 4 обслуживает все запросы клиентов. Библиотека дверей всегда держит один лишний поток наготове:
my_thread: created server thread 5
thread id 4, arg = 11
thread id 4, arg = 22
thread id 4, arg = 33
Запустим теперь три экземпляра клиента одновременно в фоновом режиме:
solaris % client6 /tmp/door6 44 &client6 /tmp/door6 55 &client6 /tmp/door6 66 &
[2] 4919
[3] 4920
[4] 4921
solaris % result: 1936
result: 4356
result: 3025
Посмотрев на вывод сервера, мы увидим, что было создано два новых потока (с идентификаторами 6 и 7) и потоки 4, 5 и 6 обслужили три запроса от клиентов:
thread id 4, arg = 44
my_thread: created server thread 6
thread id 5, arg = 66
my_thread: created server thread 7
thread id 6, arg = 55
15.10. Функции door_bind, door unbind и door_revoke
Рассмотрим еще три функции, дополняющие интерфейс дверей:
#include <door.h>
int door_bind(int
int door_unbind(void);
int door_revoke(int
/* Всe три возвращают 0 в случае успешного завершения, –1 – в случае ошибки */
Функция door_bind впервые появилась в листинге 15.18. Она связывает вызвавший ее поток с частным пулом сервера, относящимся к двери с дескриптором fd. Если вызвавший поток уже подключен к какой-либо другой двери, производится его неявное отключение.
Функция door_unbind осуществляет явное отключение потока от текущего пула, к которому он подключен.
Функция door_revoke отключает доступ к двери с дескриптором fd. Дескриптор двери может быть отменен только процессом, создавшим эту дверь. Все вызовы через эту дверь, находящиеся в процессе выполнения в момент вызова этой функции, будут благополучно завершены.
15.11. Досрочное завершение клиента или сервера
В наших примерах до настоящего момента предполагалось, что в процессе работы клиента и сервера не возникает непредусмотренных ситуаций. Посмотрим, что произойдет, если у клиента или сервера возникнут ошибки. В случае если клиент и сервер являются частями одного процесса (локальный вызов процедуры на рис. 15.1), клиенту не нужно беспокоиться о возникновении ошибок на сервере, и наоборот. Однако если клиент и сервер находятся в различных процессах, нужно учесть возможность досрочного завершения одного из них и предусмотреть способ уведомления второго об этом событии. Об этом нужно заботиться вне зависимости от того, находятся ли клиент и сервер на одном узле или нет.
Досрочное завершение сервера
Если клиент блокируется в вызове door_call, ожидая получения результатов, ему нужно каким-то образом получить уведомление о завершении потока сервера по какой-либо причине. Посмотрим, что происходит в этом случае, прервав работу сервера вызовом pthread_exit. Это приведет к завершению потока сервера (а не всего процесса). В листинге 15.20 приведен текст процедуры сервера.