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

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

251 pthreadj tid:

252 tid = (ptr == NULL) ? pthread self() : *ptr: /* Digital Unix */

253 return(pthread getsequence np(tid));

254 #else

255 /* прочие системы */

256 returnCCptr == NULL) ? pthread selfО : *ptr):

257 #endif

258 }

Если в данной реализации идентификатор потока не является небольшим целым числом, функция может быть сложнее. Она может осуществлять отображение значений типа pthreadt в целые числа и сохранять эти отображения для последующих вызовов в массиве или связном списке. Эта задача решена в функции thread name в книге [13].

Вернемся к программе из листинга 15.6. Запустим ее три раза подряд. Поскольку нам приходится ждать возвращения подсказки интерпретатора, чтобы запустить клиент еще раз, мы можем быть уверены, что каждый раз выполняется пяти-секундная пауза:

Solaris X clients /tmp/serverS 55

result: 3025

Solaris X clients /tmp/serverS 66

result: 4356

Solaris X clients /tmp/serverS 77

result: 5929

Взглянув на текст, выводимый сервером, мы увидим, что клиенты каждый раз обслуживались одним и тем же потоком сервера:

Solaris X servers /tmp/servers

thread id 4. arg = 55 thread id 4. arg = 66 thread id 4. arg = 77

Теперь запустим три экземпляра программы-клиента одновременно:

Solaris X clients /tmp/serverS 11 & clients /tmp/serverS 22 & clients /tmp/serverS 33 &

[2] 3812 [3] 3813 [4] 3814

Solaris X result: 484

result: 121 result: 1089

Выводимый сервером текст показывает, что для обработки второго и третьего вызова процедуры сервера создаются новые потоки:

thread id 4. arg = 22 thread id 5. arg = И thread id 6. arg = 33

Затем мы запустим еще два клиента одновременно (первые три уже завершили работу):

Solaris X clients /tmp/serverS 11 & clients /tmp/serverS 22 &

[2] 3830 [3] 3831

Solaris X result: 484 result: 121



При этом сервер использует созданные ранее потоки:

thread id 6. arg = 22 thread id 5. arg = 11

Этот пример показывает, что серверный процесс (то есть библиотека дверей, подключенная к нему) автоматически создает потоки серверных процедур по мере необходимости. Если приложению требуется контроль над созданием потоков, оно может его осуществить с помощью функций, описанных в разделе 15.9.

Мы также убедились, что сервер в этом случае является параллельным (concurrent): одновременно может выполняться несколько экземпляров процедуры сервера в виде отдельных потоков для обслуживания клиентов. Это следует также из того, что результат работы сервера выводится тремя экземплярами клиента одновременно пять секунд спустя после их одновременного запуска. Если бы сервер был последовательным, первый результат появился бы через 5 секунд после запуска, следующий - через 10, а последний - через 15.

Автоматическое управление потоками сервера: несколько процедур

в предыдущем примере процесс-сервер содержал лищь одну процедуру сервера. Вопрос, которым мы займемся теперь, звучит так: могут ли несколько процедур одного процесса использовать один и тот же пул потоков сервера? Чтобы узнать ответ, добавим к нащему серверу еще одну процедуру, а заодно перепищем нащи программы заново, чтобы продемонстрировать более приличный стиль передачи аргументов и результатов между процессами.

Первый файл в этом примере называется squareproc. h. В нем определен один тип данных для входных аргументов функции, возводящей в квадрат, и еще один - для возвращаемых ею результатов. В этом заголовочном файле также определяется полное имя двери для данной процедуры. Его текст его приведен в листинге 15.8.

Листинг 15.8. Заголовочный файл squareproc.h

doors/squareproc.h

1 #define PATH SQUARE DOOR /tmp/squareproc door

2 typedef struct { /* аргументы squareprocO */

3 long argl:

4 } squareprocJn t:

5 typedef struct { /* возврат squareprocO */

6 long resl:

7 } squareproc out t:

Наща новая процедура будет принимать длинное целое и возвращать квадратный корень из него (типа doubl е). Мы определяем полное имя двери этой процедуры, структуры аргументов и результатов в заголовочном файле sqrtproc.h в листинге 15.9.

Листинг 15.9. Заголовочный файл sqrtproc.h

doors/sqrtproc.h

1 #define PATH SQRT DOOR 7tmp/sqrtproc door

2 typedef struct { /* входные данные sqrtprocO */

3 long argl:



4 } sqrtproc in t:

5 typedef struct { /* возвращаемые sqrtprocO данные */

6 double resl:

7 } sqrtproc out t:

Программа-клиент приведена в листинге 15.10. Она последовательно вызывает две процедуры сервера и выводит возвращаемые ими результаты. Эта программа устроена аналогично другим клиентским программам, приведенным в этой главе.

Листинг 15.10. Клиент, вызывающий две процедуры

doors/client7.c

1 finclude unpipc.h

2 finclude squareproc.h

3 finclude sqrtproc.h

4 int

5 mainCint argc. char **argv)

7 int fdsquare. fdsqrt;

8 door arg t arg:

9 squareprocJn t squarejn:

10 squareproc out t square out;

11 sqrtproc in t sqrt in:

12 sqrtproc out t sqrt out:

13 if Cargc != 2)

14 err quitC usage: client7 <integer-value> ):

15 fdsquare = OpenCPATH SQUARE DOOR. 0 RDWR);

16 fdsqrt = OpenCPATH SQRT DOOR. 0 RDWR):

17 /* подготовка аргументов и вызов squareprocC) */

18 squarejn.argl = atolCargv[l]):

19 arg.data ptr = Cchar *) &square in:

20 arg.data size = sizeof Csquarejn):

21 arg.desc ptr = NULL;

22 arg.desc num = 0:

23 arg.rbuf = Cchar *) &square out:

24 arg.rsize = sizeofCsquare out):

25 Door callCfdsquare. &arg);

26 /* подготовка аргументов и вызов sqrtprocO */

27 sqrt in.argl = atoiCargv[l]);

28 arg.data ptr = Cchar *) &sqrt in;

29 arg.data size = sizeof Csqrtjn):

30 arg.desc ptr = NULL:

31 arg.desc num = 0:

32 arg.rbuf = Cchar *) &sqrt out:

33 arg.rsize = sizeofCsqrt out):

34 Door cal1Сfdsqrt. &arg):

35 printfC result: *ld *g\n , square out.resl. sqrt out.resl):

36 exitCO):

37 }



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.
Копирование материалов разрешено исключительно при условии цититирования.