Еще одним важнейшим атрибутом потока является приоритет его выполнения. Для каждого из уровней приоритетов, обслуживаемых системой (в QNX 6.2.1 таких уровней 64, в QNX 6.3 — 256), поддерживается циклическаяочередь потоков, готовых к исполнению (на деле большая часть из таких очередей оказывается пустой). Все политики диспетчеризации работают только с потоками из одной такой очереди: очереди потоков наивысшего из присутствующих в системе приоритетов. Если в системе выполняется поток высокого приоритета, то ни один поток более низкого приоритета не получит управление до тех пор, пока поток высокого приоритета не будет переведен в блокированное состояние в ожидании некоторого события (рис. 2.3).
Рис. 2.3. Диспетчеризация потоков с различными приоритетами
На рис. 2.3 представлены два процесса, каждый из которых создает внутри себя несколько потоков, но на этот раз различных приоритетов (10 и 12). Жирной пунктирной линией показан порядок, в котором потоки высокого приоритета (12) объединены в циклическую очередь диспетчеризации. Это активная очередь диспетчеризации (наивысшего приоритета). Тонкой линией показан порядок потоков в другой очереди (приоритета 10). До тех пор пока все потоки активной очереди не окажутся в силу каких-либо обстоятельств в блокированном состоянии, ни один из потоков очереди приоритета 10 не получит ни единого кванта времени.
Создание нового потока в программном коде осуществляет вызов:
int pthread_create(pthread_t* thread,
const pthread_attr_t* attr, void*(*start_routine)(void*), void* arg);
где thread
— NULL
или указатель переменной типа pthread_t
, значение которой будет загружено идентификатором созданного потока после успешного выполнения функции. Далее это значение (это и есть TID) может использоваться по тексту программы для идентификации созданного потока.
attr
— NULL
или указатель структуры типа pthread_attr_t
. Если это значение NULL
, то созданный поток будет иметь набор параметров, устанавливаемых по умолчанию. Если нет, то поток будет создан с параметрами, установленными в структуре attr
. Модификация полей attr
после создания потока (то есть после вызова функции) не оказывает никакого эффекта на параметры потока, и вообще говоря, структура attr
может быть уничтожена сразу же после вызова pthread_create()
. Документация предостерегает от прямой манипуляции значениями полей этой структуры, предлагая использовать для этого функции pthread_attr_init()
и pthread_attr_set_*()
.
start_routine
— функция типа void*()(void*)
, уже упоминавшаяся выше как функция потока; это тот код, который будет фактически выполняться в качестве отдельного потока. Если выполнение этой функции завершается по return
, то происходит нормальное завершение потока с вызовом pthread_exit()
, использующим значение, возвращаемое start_routine в качестве статуса завершения. (Исключением является поток, связанный с main()
; он при завершении выполняет вызов exit()
.)
arg
— указатель на блок данных, передаваемых start_routine
в качестве входного параметра. Этот параметр подробно рассмотрен далее.
Чаще всего (однако совершенно необязательно) функция потока start_routine
представляет собой бесконечный цикл, в котором выполняются некоторые действия с выходом из цикла в том случае, когда нужно завершить выполнение и уничтожить созданный поток. Выглядит это следующим образом:
// функция потока:
void* ThreadProc(void* data) {
while (true) {
// ... выполняется работа ...
if (...) break;
// после этого поток нам уже не нужен!
}
return NULL;
}
После успешного создания нового потока он начинает функционировать «параллельно» с породившим его потоком и другими потоками процесса (если быть совсем точными, то со всеми прочими потоками, существующими в системе, так как в QNX существует только одна стратегия диспетчеризации потоков PTHREAD_SCOPE_SYSTEM
, и существует она глобально, на уровне всей системы). При этом после точки выполнения pthread_create()
невозможно предсказать, какой поток получит управление: породивший, порожденный или вообще произвольный поток из другого процесса. Это важно учитывать при передаче новому потоку данных и других операциях начальной инициализации параметров внутри созданного потока.
Читать дальше
Конец ознакомительного отрывка
Купить книгу