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

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

29 }

30 void

31 my_create(door info_t *iptr)

32 {

33  pthread_t tid;

34  pthread_attr_t attr;

35  Pthread_attr_init(&attr);

36  Pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

37  Pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

38  Pthread_create(&tid, &attr, my_thread, (void *)iptr);

39  Pthread_attr_destroy(&attr);

40  printf("my_thread: created server thread %ld\n", pr_thread_id(&tid)):

41 }

Процедура создания сервера

30-41 Каждый раз при вызове my_create создается новый поток. Перед вызовом pthread_create атрибуты потока инициализируются, область потока устанавливается равной PTHREAD_SCOPE_SYSTEM и поток определяется как неприсоединенный (detached). Созданный поток вызывает функцию my_thread. Аргументом этой функции является указатель на структуру типа door_info_t. Если у нас имеется сервер с несколькими дверьми и мы указываем процедуру создания сервера, эта процедура создания сервера будет вызываться при необходимости создания потока для любой из дверей. Единственный способ, которым эта процедура может определить тип сервера, соответствующий нужной двери, заключается в изучении указателя di_proc в структуре типа door_info_t.

ПРИМЕЧАНИЕ

Установка области выполнения PTHREAD_SCOPE_SYSTEM означает, что поток будет конкурировать в распределении ресурсов процессора с другими потоками системы. Альтернативой является указание PTHREAD_SCOPE_PROCESS; при этом поток будет конкурировать только с другими потоками данного процесса. Последнее не будет работать с дверьми, поскольку библиотека дверей требует, чтобы тот процесс ядра, который привел к вызову данного потока, выполнял и door_return. Поток с PTHREAD_SCOPE_PROCESS может сменить поток ядра во время выполнения процедуры сервера.

Причина, по которой поток должен создаваться как неприсоединенный, заключается в том, что нужно предотвратить сохранение в системе информации о потоке после его завершения, потому что отсутствует поток, вызывающий pthread_join.

Функция, запускающая поток

15-20 При создании потока запускается функция my_thread, указанная в вызове pthread_create. Аргументом является указатель на структуру типа door_info_t, передаваемый my_create. В данном примере есть только одна процедура сервера — servproc, и мы просто проверяем, что аргумент указывает на эту процедуру.

Ожидание присваивания дескриптору правильного значения

21-22 Процедура создания сервера вызывается в первый раз при вызове door_create для создания первого потока сервера. Этот вызов осуществляется из библиотеки дверей до завершения работы door_create. Однако переменная fd не примет значения дескриптора двери до тех пор, пока не произойдет возврата из функции door_create (проблема курицы и яйца). Поскольку мы знаем, что my_thread выполняется отдельно от основного потока, решение состоит в том, чтобы использовать взаимное исключение fdlock следующим образом: основной поток блокирует взаимное исключение перед вызовом door_create и разблокирует после возврата из door_create (когда дескриптору fd уже присвоено некоторое значение). Функция my_thread делает попытку заблокировать взаимное исключение (ее выполнение приостанавливается до тех пор, пока основной поток не разблокирует это взаимное исключение), а затем разблокирует его. Мы могли бы добавить условную переменную и передавать по ней уведомление, но здесь это не нужно, поскольку мы заранее знаем, в каком порядке будут происходить вызовы.