Читать «UNIX: взаимодействие процессов» онлайн - страница 243

Уильям Ричард Стивенс

solaris # ls –l client4

-rwxrwxr-x 1 rstevens other1 139328 Apr 13 06:02 client4

solaris # chown root client4     смена владельца на привилегированного пользователя

solaris # chmod u+s client4      включение бита SUID

solaris # ls -l client4           проверка разрешений и владельца файла

-rwsrwxr-x 1 root     other1 139328 Apr 13 06:02 client4

solaris # exit

solaris % ls -l client4

-rwsrwxr-x 1 root     other1 139328 Apr 13 06:02 client4

solaris % client4 /tmp/server477 и еще раз запускаем программу-клиент

result: 5929

Если мы посмотрим, что в это время выводил сервер, то увидим следующую картину:

solaris % server4 /tmp/server4

euid = 224, ruid = 224, pid = 3168

euid = 0, ruid = 224, pid = 3176

Действующий идентификатор пользователя при втором запуске изменился. Значение 0 означает привилегированного пользователя.

Автоматическое управление потоками сервера

Чтобы посмотреть, как осуществляется управление потоками сервера, добавим в процедуру сервера команду выдачи ее идентификатора потока. Добавим в нее также пятисекундную паузу, чтобы имитировать длительное выполнение. За это время мы сможем запустить несколько клиентов. В листинге 15.6 приведен текст новой процедуры сервера.

Листинг 15.6. Процедура сервера, выводящая идентификатор потока

//doors/server5.c

1  #include "unpipc.h"

2  void

3  servproc(void *cookie, char *dataptr, size_t datasize,

4   door_desc_t *descptr, size_t ndesc)

5  {

6   long arg, result;

7   arg = *((long *) dataptr);

8   printf("thread id %ld, arg = %ld\n", pr_thread_id(NULL), arg);

9   sleep(5);

10  result = arg * arg;

11  Door_return((char*)&result, sizeof(result), NULL, 0);

12 }

Здесь используется новая функция из нашей библиотеки — pr_thread_id. Она принимает один аргумент (указатель на идентификатор потока или нулевой указатель вместо идентификатора вызвавшего потока) и возвращает идентификатор этого потока (обычно небольшое целое число, но всегда в формате длинного целого). Процессу всегда можно сопоставить целое число — его идентификатор. Хотя мы и не знаем, к какому типу принадлежит идентификатор процесса (int или long), мы просто преобразуем значение, возвращаемое getpid, к типу long и выводим значение (листинг 9.2). Однако идентификатор потока принадлежит к типу pthread_t, который не обязательно является одним из целых типов. И действительно, в Solaris 2.6 идентификаторами потоков являются короткие целые, тогда как в Digital Unix используются указатели. Однако часто возникает необходимость сопоставлять потокам небольшие целые числа для задач отладки (как в данном примере). Наша библиотечная функция, текст которой приведен в листинге 15.7, решает этот вопрос.

Листинг 15.7. Функция pr_thread_id: возвращает небольшой целочисленный идентификатор потока

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

251  pthread_t tid;

252  tid = (ptr == NULL) ? pthread_self() : *ptr; /* Digital Unix */