Главная страница Взаимодействие нетривиальных процессов 3 servprocCvoid *cookie, char *dataptr, size t datasize. 4 door desc t *descptr, size t ndesc) 6 long arg, result; 7 arg = *((long *) dataptr): 8 result = arg * arg: 9 Door return((char *) Sresult, sizeof(result), NULL. 0); 10 } 11 int 12 ttiain(int argc, char **argv) 13 { 14 int fd: 15 if (argc != 2) 16 err quit( usage; serverl <server-pathnattie> ); 17 /* создание двери и связывание ее с файлом */ 18 fd = Door create(servproc, NULL, 0); 19 unlink(argv[l]); 20 Close(Open(argv[l], 0 CREAT 0 RDWR, FILE MODE)); 21 Fattach(fd, argv[l]); 22 /* функция servprocO обрабатывает все запросы клиентов */ 23 for ( ; : ) 24 pauseO; 25 } Процедура сервера 2-10 Процедура сервера вызывается с пятью аргументами, но мы используем только один из них - dataptr. Он указывает на первый байт аргумента. Аргумент, представляющий собой длинное целое, передается через этот указатель и возводится в квадрат. Управление передается клиенту вместе с результатом вызовом door return. Первый аргумент указывает на результат, второй задает его размер, а оставшиеся предназначены для возврата дескрипторов. Создание дескриптора двери и связывание с ним файла 17-21 Дескриптор двери создается вызовом doorcreate. Первый аргумент является указателем на функцию, соответствующую этой двери (servproc). После получения этого дескриптора его нужно связать с некоторым именем в файловой системе, поскольку оно будет использоваться клиентом для подключения к этой двери. Делается это njrreM создания обычного файла в файловой системе (сначала мы вызываем unl i nk, на тот случай, если такой файл уже существует, причем возможная ошибка игнорируется) и вызова fattach - функции SVR4, связывающей дескриптор с полным именем файла. Главный поток сервера ничего не делает 22-24 Главный поток сервера блокируется при вызове ра use. Вся функциональность обеспечивается функцией servproc, которая будет запускаться как отдельный поток каждый раз при получении запроса клиента. Запустим сервер в отдельном окне: Solaris % serverl /tttip/serverl После этого запустим программу-клиент в другом окне, указав в качестве аргумента то же полное имя, которое было указано при вызове сервера: Solaris % cl Ientl /tttip/serverl 9 result: 81 Solaris * Is -1 /tttip/serverl Orw-r--r-- 1 rstevens otherl 0 Apr 9 10:09 /tttip/serverl Мы получили ожидаемый результат. Вызвав 1 s, мы видим, что эта программа выводит букву D в начале строки, соответствующей файлу, указывая, что этот файл является дверью. На рис. 15.2 приведена диаграмма работы данного примера. Функция doorcal 1 вызывает процедуру на сервере, которая затем вызывает doorreturn для возврата. На рис. 15.3 приведена диаграмма, показывающая, что в действительности происходит при вызове процедуры в другом процессе на том же узле. сервер клиент
servproc ( ) Г do whatever */ door retum ( ); main ( ) fd = door create ( ); fattach (fd, path); Рис. 15.2. Внешний вид вызова процедуры в другом процессе 3. 4. На рис. 15.3 выполняются следующие действия: Запускается сервер, вызывает door create, чтобы создать дескриптор для функции servproc, затем связывает этот дескриптор с именем файла в файловой системе. Запускается клиент и вызывает door cal 1. Это функция в библиотеке дверей. Библиотечная функция door call делает системный вызов. При этом указывается процедура, которая должна быть выполнена, а управление передается функции из библиотеки дверей процесса-сервера. Вызывается процедура сервера (servproc в данном примере). Процедура сервера делает все необходимое для обработки запроса клиента и вызывает door return по завершении работы. Библиотечная функция door return осуществляет системный вызов, передавая управление ядру. В этом вызове указывается процесс-клиент, которому и передается управление. сервер клиент main ( ) { fd = open (path, ); door call (fd, ); . библиотека j I дверей > servproc ( ) -<- /* do whatever */ door retum ( ); - } 4 main ( ) { fd = door create ( ); fattach (fd, path); Рис. 15.3. Что в действительности происходит при вызове процедуры в другом процессе Последующие разделы этой главы описывают интерфейс дверей (doors API) более подробно, с множеством примеров, В приложении А мы убедимся, что двери представляют собой наиболее быструю форму IPC (при измерении времени ожидания). 15.2. Функция door call Функция door call вызывается клиентом для обращения к процедуре сервера, выполняемой в адресном пространстве процесса-сервера: finclude <door.h> int door call(int fd, door arg t *argp)\ I* Возвращает 0 в случае успешного завершения, -1 - в случае ошибки */ Дескриптор fd обычно возвращается функцией open (см, листинг 15.1), Полное имя файла, открываемого клиентом, однозначно идентифицирует процедуру сервера, которая вызывается door cal 1 при передаче дескриптора. Второй аргумент - argp - указывает на структуру, описывающую аргументы и приемный буфер для возвращаемых значений: typedef struct door arg { char *data ptr: /* при вызове указывает на аргументы, при возврате - на результаты */ size t data size; /* при вызове определяет общий размер аргументов в байтах, при возврате - общий размер возвращаемых данных в байтах */
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |