Главная страница Взаимодействие нетривиальных процессов 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 }
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |