Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 [ 129 ] 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

1. По умолчанию частный пул сервера и процедура создания сервера отсутствуют. Система создает потоки по мере необходимости и они переходят в пул потоков процесса.

2. Указан флаг DOOR PRI VATE, но процедура создания сервера отсутствует. Система создает потоки по мере необходимости и они отходят в пул потоков процесса, если относятся к тем дверям, для которых флаг DOOR PRI VATE не был указан, либо в пул данной двери, если она была создана с флагом DOOR PRIVATE.

3. Отсутствует частный пул сервера, но указана процедура создания сервера. Процедура создания вызывается при необходимости создания нового потока, который затем переходит в пул потоков процесса.

4. Указан флаг DOOR PRIVATE и процедура создания сервера. Процедура создания сервера вызывается каждый раз при необходимости создания потока. После создания поток должен вызвать cloor bincl для отнесения его к нужному частному пулу сервера, иначе он будет добавлен к пулу потоков процесса.

В листинге 15.18 приведен текст двух новых функций: niy create (процедура создания сервера) и my threacl (функция, выполняемая каждым потоком, который создается my create).

Листинг 15.18. Функции управления потоками

doors/server6.c

13 pthread mutex t fdlock = PTHREAD MUTEX INITIALIZER:

14 static 1nt 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 mutexJock(&fdlock):

22 Pthread mutex unlock(&fdlock):

23 Pthread setcancelStateCPTHREAD CANCEL DISABLE. &oldstate):

24 Door bind(fd):

25 Door returnCNULL. 0. NULL. 0):

26 } else

27 err quit( my thread: unknown function: *p . arg):

28 return(NULL): /* никогда не выполняется */

29 }

30 void

31 ГПУ createCdoor info t *iptr)

32 {

33 pthread t tid:

34 pthread attr t attr:

35 Pthread attr 1nit(&attr):

36 Pthread attr setscope(&attr. PTHREAD SCOPE SYSTEM):

37 Pthread attr setdetachstate(&attr. PTHREAD CREATE DETACHED);

38 Pthread create(&tid, &attr. myjhread. (void *) iptr):



39 Pthread attr destroy(&attr)i

40 pr1ntfCmy thread: created server thread *ld\n . pr thread 1d(&tid)):

41 }

Процедура создания сервера

30-41 Каждый раз при вызове my create создается новый поток. Перед вызовом pthreacl create атрибуты потока инициализируются, область потока устанавливается равной PTHREAD SCOPE SYSTEM и поток определяется как неприсоединенный (detached). Созданный поток вызывает функцию niy threacl. Аргументом этой функции является указатель на структуру типа cloor info t. Если у нас имеется сервер с несколькими дверьми и мы указываем процедуру создания сервера, эта процедура создания сервера будет вызываться при необходимости создания потока для любой из дверей. Единственный способ, которым эта процедура может определить тип сервера, соответствующий нужной двери, заключается в изучении указателя cli proc в структуре типа cloor i nfo t.

ПРИМЕЧАНИЕ

Установка области выполнения PTHREAD SCOPE SYSTEM означает, что поток будет конкурировать в распределении ресурсов процессора с другими потоками системы. Альтернативой является указание PTHREAD SCOPE PROCESS; при этом поток будет конкурировать только с другими потоками данного процесса. Последнее не будет работать с дверьми, поскольку библиотека дверей требует, чтобы тот процесс ядра, который привел к вызову данного потока, выполнял и doorreturn. Поток с PTHREAD SCOPE PROCESS может сменить поток ядра во время выполнения процедуры сервера.

Причина, по которой поток должен создаваться как неприсоединенный, заключается в том, что нужно предотвратить сохранение в системе информации о потоке после его завершения, потому что отсутствует поток, вызывающий pthread Join.

Функция, запускающая поток

15-20 При создании потока запускается функция my threacl, указанная в вызове pthreacl create. Аргументом является указатель на структуру типа door J nf о J, передаваемый my create. В данном примере есть только одна процедура сервера - servproc, и мы просто проверяем, что аргумент указывает на эту процедуру.

Ожидание присваивания дескриптору правильного значения

21-22 Процедура создания сервера вызывается в первый раз при вызове door create для создания первого потока сервера. Этот вызов осуществляется из библиотеки дверей до заверщения работы door create. Однако переменная f d не примет значения дескриптора двери до тех пор, пока не произойдет возврата из функции door create (проблема курицы и яйца). Поскольку мы знаем, что my thread выполняется отдельно от основного потока, рещение состоит в том, чтобы использовать взаимное исключение fdl оск следующим образом: основной поток блокирует взаимное исключение перед вызовом door create и разблокирует после возврата из door create (когда дескриптору fd уже присвоено некоторое значе-



ние). Функция my threacl делает попытку заблокировать взаимное исключение (ее выполнение приостанавливается до тех пор, пока основной поток не разблокирует это взаимное исключение), а затем разблокирует его. Мы могли бы добавить условную переменную и передавать по ней уведомление, но здесь это не нужно, поскольку мы заранее знаем, в каком порядке будут происходить вызовы.

Отключение отмены потока

23 При создании нового потока вызовом pthreacl create его отмена по умолчанию разрешена. Если отмена потока разрешена и клиент прерывает вызов doorcall в процессе его выполнения (что мы продемонстрируем в листинге 15.26), вызываются обработчики отмены потока, после чего он завершается. Если отмена потока отключена (как это делаем мы) и клиент прерывает работу в вызове door cal 1, процедура сервера спокойно завершает работу (поток не завершается), а результаты doorreturn просто сбрасываются. Поскольку серверный поток завершается, если происходит отмена потока, и поскольку процедура сервера может в этот момент выполнять какие-то действия (возможно, с заблокированными семафорами или блокировками), библиотека дверей на всякий случай отключает отмену всех создаваемых ею потоков. Если нам нужно, чтобы процедура сервера отменялась при досрочном завершении работы клиента, для этого потока следует включить возможность отмены и приготовиться обработать такую ситуацию.

ПРИМЕЧАНИЕ

Обратите внимание, что область выполнения PTHREAD SCOPE SYSTEM и непри-соединенность потока указываются как атрибуты при создании потока. А отмена потока может быть отключена только в процессе выполнения потока. Таким образом, хотя мы и отключаем отмену потока, он сам может ее включить и выключить тогда, когда потребуется.

Связывание потока с дверью

24 Вызов door bind позволяет добавить поток к пулу, связанному с дверью, дескриптор которой передается door bi nd в качестве аргумента. Поскольку для этого нам нужно знать дескриптор двери, в этой версии сервера он является глобальной переменной.

Делаем поток доступным клиенту

25 Мы делаем поток доступным клиенту вызовом door return с двумя нулевыми указателями и нулевыми значениями длин буферов в качестве аргументов.

Процедура сервера приведена в листинге 15.19. Она идентична программе из листинга 15.6.

Листинг 15.19. Процедура сервера

doors/server6.c

1 finclude unpipc.h

2 void

3 servprocCvoid *cook1e. char *dataptr. size t datasize,



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 [ 129 ] 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.