Читать «UNIX: взаимодействие процессов» онлайн - страница 253
Уильям Ричард Стивенс
44 {
45 if (argc != 2)
46 err_quit("usage: server6 <server-pathname>");
47 Door_server_create(my_create);
48 /* создание дескриптора двери и связывание его с именем */
49 Pthread_mutex_lock(&fdlock);
50 fd = Door_create(servproc, NULL, DOOR_PRIVATE);
51 Pthread_mutex_unlock(&fdlock);
52 unlink(argv[1]);
53 Close(Open(argv[1], O_CREAT | O_RDWR, FILE_MODE));
54 Fattach(fd, argv[1]);
55 /* servproc() обслуживает запросы клиентов */
56 for(;;)
57 pause();
58 }
По сравнению с листингом 15.2 было внесено четыре изменения:
1. Убрано объявление дескриптора двери fd (теперь это глобальная переменная, описанная в листинге 15.18).
2. Вызов door_create защищен взаимным исключением (также описанным в листинге 15.18).
3. Вызов door_server_create делается перед созданием двери, при этом указывается процедура создания сервера (my_thread, которая, будет показана позже).
4. В вызове door_create последний аргумент (атрибуты) имеет значение DOOR_PRIVATE вместо 0. Это говорит библиотеке о том, что данная дверь будет иметь собственный пул потоков, называемый частным пулом сервера.
Задание процедуры создания сервера с помощью door_server_create и выделение частного пула сервера с помощью DOOR_PRIVATE осуществляются независимо друг от друга. Возможны четыре ситуации:
1. По умолчанию частный пул сервера и процедура создания сервера отсутствуют. Система создает потоки по мере необходимости и они переходят в пул потоков процесса.
2. Указан флаг DOOR_PRIVATE, но процедура создания сервера отсутствует. Система создает потоки по мере необходимости и они отходят в пул потоков процесса, если относятся к тем дверям, для которых флаг DOOR_PRIVATE не был указан, либо в пул данной двери, если она была создана с флагом DOOR_PRIVATE.
3. Отсутствует частный пул сервера, но указана процедура создания сервера. Процедура создания вызывается при необходимости создания нового потока, который затем переходит в пул потоков процесса.
4. Указан флаг DOOR_PRIVATE и процедура создания сервера. Процедура создания сервера вызывается каждый раз при необходимости создания потока. После создания поток должен вызвать door_bind для отнесения его к нужному частному пулу сервера, иначе он будет добавлен к пулу потоков процесса.
В листинге 15.18 приведен текст двух новых функций: my_create (процедура создания сервера) и my_thread (функция, выполняемая каждым потоком, который создается my_create).
Листинг 15.18. Функции управления потоками
//doors/server6.c
13 pthread_mutex_t fdlock = PTHREAD_MUTEX_INITIALIZER;
14 static int fd = –1; /* дескриптор двери */
15 void *
16 my_thread(void *arg)
17 {
18 int oldstate;
19 door_info_t *iptr = arg;
20 if ((Door_server_proc*)iptr->di_proc == servproc) {
21 Pthread_mutex_lock(&fdlock);
22 Pthread_mutex_unlock(&fdlock);
23 Pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
24 Door_bind(fd);
25 Door_return(NULL, 0, NULL, 0);
26 } else
27 err_quit("my_thread: unknown function: %p", arg);
28 return(NULL); /* никогда не выполняется */