Главная страница Взаимодействие нетривиальных процессов Листинг 15.4 (продолжение) 9 err quit( usage: cl1ent2 <server-pathnanie> <integer-value> ): 10 fd = Open(argv[1], 0 RDWR): /* открываем дверь */ 11 /* подготовка аргументов и указателя на результат */ 12 1val = atol(argv[2]): 13 arg.data ptr = (char *) &ival; /* аргументы-данные */ 14 arg.data size = sizeof(long): /* объем данных */ 15 arg.desc ptr = NULL; 16 arg.desc nutti = 0: 17 arg.rbuf = (char *) &oval: /* возвращаемые данные */ 18 arg.rsize = sizeof(long); /* объем возвращаемых данных */ 19 /* вызов процедуры сервера и вывод результата */ 20 Door call(fd. &arg); 21 printf( &oval = р. data ptr = р. rbuf = р, rsize = %й\п . 22 &oval, arg.data ptr, arg.rbuf, arg.rsize); 23 printfCresult: ld\n , *((long *) arg.data ptr)): 24 exit(O); 25 } 19-22 В этой версии программы на экран выводится адрес переменной oval, содержимое указателя data ptr, который должен указывать на возвращаемые функцией door cal 1 данные, и адрес и размер приемного буфера (rbuf и rsize). Запустим эту программу, не изменяя размер приемного буфера по сравнению с листингом 15,2, Мы ожидаем, что data ptr и rbuf будут указывать на переменную oval и rsize будет иметь значение 4 (4 байта в буфере), И действительно, вот что мы видим: Solaris X c1ient2 /tnip/server2 22 &oval = effff740, data ptr = effff740, rbuf = effff740, rsize = 4 result: 484 Изменим только одну строку в листинге 15,4, уменьшив размер буфера клиента до одного байта. Новый вариант строки 18 будет иметь вид: arg.rsize = sizeof(long) - 1; /* размер буфера данных */ Запустим новую программу и увидим, что библиотека автоматически выделила место под новый буфер результатов и data ptr теперь указывает на новый буфер: Solaris X clients /tmp/serverS 33 &oval = effff740, data ptr = ef620000, rbuf = ef620000, rsize = 4096 result: 1089 Размер выделенного буфера равен 4096 байт, что совпадает с размером страницы в данной системе, который мы узнали в разделе 12,6, Этот пример показывает, что следует всегда обращаться к результатам через указатель data ptr, а не через переменные, адреса которых были переданы в rbuf, В нашем примере к результату типа длинное целое следует обращаться как * (1 ong *) а гд. data ptr, а не oval (что мы делали в листинге 15,2), Новый буфер выделяется вызовом mmap и может быть возвращен системе с помощью munmap. Клиент может повторно использовать этот буфер при новых вызовах door call. Функция door cred и информация о клиенте На этот раз мы изменим нашу функцию servproc из листинга 15,3, добавив в нее вызов door cred для получения информации о пользователе, В листинге 15,5 приведен текст новой процедуры сервера; функции mai п клиента и сервера не претерпевают изменений по сравнению с листингами 15.2 и 15.3. Листинг 15.5. Процедура сервера, получающая информацию о клиенте doors/server4.c 1 finclude unpipc.h 2 void 3 servprocCvoid *cookie, char *dataptr, size t datasize, 4 door desc t *descptr, size t ndesc) 6 long arg, result: 7 door cred t info: 8 /* получение и вывод информации о клиенте */ 9 Door credC&info): 10 printfC euid = ruid = ld. pid = ld\n . 11 Clong) info.dc euid, Clong) info.dc ruid, Clong) info.dc pid); 12 arg = *CCIong *) dataptr); 13 result = arg * arg: 14 Door returnCCchar *) Sresult, sizeofCresult), NULL, 0): 15 } Сначала мы запустим программу-клиент и увидим, что действующий и реальный идентификаторы клиента совпадают, как мы и предполагали. Затем мы сменим владельца исполняемого файла на привилегированного пользователя, установим бит SUID и запустим программу снова: Solaris % c1ient4 /tnip/server4 77 первый запуск клиента result; 5929 Solaris % su вход под именем привилегированного пользователя Password: Sun Microsystems Inc. Sun OS 5.6 Generic August 1997 Solaris f cd каталог, в котором находится исполняемый файл Solaris f Is -1 c1ient4 -rwxrwxr-x 1 rstevens otherl 139328 Apr 13 06:02 client4 Solaris f chown root c1ient4 смена владельца на привилегированного пользователя Solaris f chnrod u+s c1ient4 включение бита SUID Solaris f Is -1 cTient4 проверка разрешений и владельца файла -rwsrwxr-x 1 root otherl 139328 Apr 13 06:02 client4 Solaris f exit Solaris Is -1 c1ient4 -rwsrwxr-x 1 root otherl 139328 Apr 13 06:02 client4 Solaris % c1ient4 /tnip/server4 77 и еще раз запускаем программу-клиент result: 5929 Если мы посмотрим, что в это время выводил сервер, то увидим следующую картину: Solaris % server4 /tnip/server4 euid = 224. ruid = 224, pid = 3168 euid = 0. ruid = 224. pid = 3176 Действующий идентификатор пользователя при втором запуске изменился. Значение О означает привилегированного пользователя. Автоматическое управление потоками сервера Чтобы посмотреть, как осуществляется управление потоками сервера, добавим в процедуру сервера команду вьщачи ее идентификатора потока. Добавим в нее также пятисекундную паузу, чтобы имитировать длительное выполнение. За это время мы сможем запустить несколько клиентов. В листинге 15.6 приведен текст новой процедуры сервера. Листинг 15.6. Процедура сервера, выводящая идентификатор потока doors/serverS.c 1 finclude unpipc.h 2 void 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 printfC thread id %Ы. arg = ld\n . pr threadJd(NULL), arg): 9 sleep(5); 10 result = arg * arg: 11 Door return((char *) &result. sizeof(result). NULL. 0): 12 } Здесь используется новая функция из нащей библиотеки - pr threacl icl. Она принимает один аргумент (указатель на идентификатор потока или нулевой указатель вместо идентификатора вызвавшего потока) и возвращает идентификатор этого потока (обычно небольшое целое число, но всегда в формате длинного целого). Процессу всегда можно сопоставить целое число - его идентификатор. Хотя мы и не знаем, к какому типу принадлежит идентификатор процесса (int или 1 ong), мы просто преобразуем значение, возвращаемое getpi d, к типу 1 ong и выводим значение (листинг 9.2). Однако идентификатор потока принадлежит к типу pthread t, который не обязательно является одним из целых типов. И действительно, в Solaris 2.6 идентификаторами потоков являются короткие целые, тогда как в Digital Unix используются указатели. Однако часто возникает необходимость сопоставлять потокам небольшие целые числа для задач отладки (как в данном примере). Наша библиотечная функция, текст которой приведен в листинге 15.7, решает этот вопрос. Листинг 15.7. Функция prjhreadjd: возвращает небольшой целочисленный идентификатор потока lib/wrappthread.c 245 long 246 pr thread id(pthread t *ptr) 247 { 248 #if defined(sun) 249 return((ptr == NULL) ? pthread self() : *ptr); /* Solaris */ 250 #elif defined( osf ) && defined( alpha)
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |