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

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

цессам. В такой ситуации мы обычно называем вызвавшую процедуру клиентом, а вызванную - сервером. Во втором сценарии на рис. 15.1 клиент и сервер выполняются на одном и том же узле. Это типичный частный случай третьего сценария, и это именно то, что осуществляется с помощью дверей (doors). Итак, двери дают возможность вызывать процедуру (функцию) другого процесса на том же узле. Один из процессов (сервер) делает процедуру, находящуюся внутри него, доступной для вызова другим процессам (клиентам), создавая для этой процедуры дверь. Мы можем считать двери специальным типом IPC, поскольку при этом между процессами (клиентом и сервером) передается информация в форме аргументов функции и возвращаемых значений.

3. RPC в общем случае дает возможность клиенту на одном узле вызвать процедуру сервера на другом узле, если эти два узла связаны каким-либо образом по сети (третий сценарий на рис. 15,1). Такой вид взаимодействия будет описан в главе 16.

ПРИМЕЧАНИЕ-

Впервые двери были разработаны для распределенной операционной системы Spring. Детали этого проекта доступны по адресу httpi www,sun,com/tecli/projects/spring. Описание механизма дверей в этой операционной системе можно найти в книге [7],

Затем двери появились в версии Solaris 2,5, хотя единственная страница документации, к ним относящаяся, содержала только предупреждение о том, что двери являются экспериментальным интерфейсом, используемым отдельными приложениями Sun, В Solaris 2.6 описание этого интерфейса занимает уже 8 страниц, но в них он характеризуется как развивающийся . В будущих версиях Solaris 2,6 описываемый в этой главе интерфейс API может быть изменен. Предварительная версия дверей для Linux уже разрабатывается, детали можно выяснить по адресу http: www,cs,brown.edu/-tor/ doors.

Чтобы воспользоваться интерфейсом дверей в Solaris 2,6, нужно подключить соответствующую библиотеку (-Idoor), содержащую функции door XXX, описываемые в этой главе, и использовать файловую систему ядра (/kernel/sys/doorfs).

Хотя двери поддерживаются только в системе Solaris, мы описываем их достаточно подробно, поскольку это описание позволяет подготовить читателя к удаленному вызову процедур без необходимости обсуждать какие-либо детали сетевого интерфейса. В приложении А мы увидим, что этот интерфейс достаточно быстр - едва ли не быстрее, чем все остальные средства передачи сообшений.

Локальные вызовы процедур являются синхронными (synchronous): вызывающий процесс не получает управление до тех пор, пока не происходит возврат из вызванной процедуры, Потоки могут восприниматься как средство асинхронного вызова процедур: функция (указанная в третьем аргументе pthread create) выполняется одновременно с вызвавшим процессом. Вызвавший процесс может ожидать завершения вызванного процесса с помощью функции pthreadjoi п, Удаленный вызов процедур может быть как синхронным, так и асинхронным, но мы увидим, что вызовы через двери являются синхронными.

Внутри процесса двери идентифицируются дескрипторами. Извне двери могут идентифицироваться именами в файловой системе. Сервер создает дверь вы-



зовом door create; аргументом этой функции является указатель на процедуру, которая будет связана с данной дверью, а возвращаемое значение является дескриптором двери, Затем сервер связывает полное имя файла с дескриптором двери с помощью функции fattach. Клиент открывает дверь вызовом open, при этом аргументом функции является полное имя файла, которое сервер связал с дверью, а возвращаемым значением - дескриптор, который будет использоваться клиентом для доступа к двери. Затем клиент может вызывать процедуру с помощью door cal 1. Естественно, программа, являющаяся сервером для некоторой двери, может являться клиентом для другой.

Мы уже сказали, что вызовы через двери являются синхронными: когда клиент вызывает door ca 11, возврата из этой функции не происходит до тех пор, пока процедура на сервере не заверщит работу (возможно, с ошибкой). Реализация дверей в Solaris связана с потоками. Каждый раз, когда клиент вызывает процедуру сервера, для обработки этого вызова создается новый поток в процессе-сервере. Работа с потоками обычно осуществляется автоматически функциями библиотеки дверей, при этом потоки создаются по мере необходимости, но мы увидим, что сервер может и сам управлять этими потоками, если это требуется. Это также означает, что одна и та же процедура может выполняться сервером для нескольких клиентов, причем для каждого из них будет создан отдельный поток, Такой сервер является параллельным. Поскольку одновременно могут выполняться несколько экземпляров процедуры сервера (каждая из которых представляет собой отдельный поток), содержимое этих процедур должно соответствовать определенным требованиям, которые обычно предъявляются к многопоточным программам.

При удаленном вызове процедуры и данные, и дескрипторы могут быть переданы от клиента к серверу. Обратно также могут быть переданы данные и дескрипторы. Передача дескрипторов вообще является неотъемлемым свойством дверей. Более того, поскольку двери идентифицируются дескрипторами, это позволяет процессу передать дверь другому процессу. Более подробно о передаче дескрипторов будет говориться в разделе 15,8.

Пример

Начнем описание интерфейса дверей с простого примера; клиент передает серверу длинное целое, а сервер возвращает клиенту квадрат этого значения тоже как длинное целое. В листинге 15.1 приведен текст программы-клиента (в этом примере мы опускаем множество деталей, большую часть которых мы обсудим далее в тексте главы).

Листинг 15.1. Клиент передает серверу длинное целое для возведения его в квадрат

doors/clientl.c

1 finclude unpipc.h

2 int ал

продолжение w



Листинг 15.1 (продолжение)

3 maindnt argc. char **argv)

5 int fd:

6 long ival, oval:

7 door arg t arg:

8 if (argc 3)

9 err quit( usage: clientl <server-pathname> <integer-value> );

10 fd = Open(argv[l], 0 RDWR); /* открываем дверь */

11 /* задаем аргументы и указатель на результат */

12 ival = atol(argv[2]):

13 arg,data ptr = (char *) Sival; /* аргументы */

14 arg,data size = sizeof(long): /* размер аргументов */

15 arg.desc ptr = NULL:

16 arg,desc num = 0:

17 arg.rbuf = (char *) Soval: /* результат */

18 arg,rsize = sizeof(long): /* размер результата */

19 /* вызываем процедуру на сервере и выводим результат */

20 Door call(fd. &arg):

21 printf ( result; %Шп . oval);

22 exit(O):

23 }

Открываем дверь

8-10 Дверь задается полным именем, передаваемым в качестве аргумента командной строки. Она открывается вызовом open, Возвращаемый дескриптор называется дескриптором двери, но часто его самого и называют дверью.

Подготовка аргументов и указателя на результат

11-18 Структура arg содержит указатели на аргументы и результат. Поле data ptr указывает на первый байт аргументов, а data size содержит количество байтов в аргументах. Два поля desc ptr и desc nuni предназначены для передачи дескрипторов, о чем мы будем подробно говорить в разделе 15.8. rbuf указывает на первый байт буфера результата, а rsize задает его размер.

Вызов процедуры на сервере и вывод результата

19-21 Мы вызываем процедуру на сервере с помощью door cal 1; аргументами этого вызова являются дескриптор двери и указатель на структуру аргументов. После возвращения из этого вызова программа печатает получившийся результат.

Программа-сервер приведена в листинге 15.2. Она состоит из процедуры сервера с именем servproc и функции main.

Листинг 15.2. Сервер, возводящий длинное целое в квадрат

doors/serverl.c

1 finclude unpipch

2 void



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