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

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.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)



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