Вход/Регистрация
QNX/UNIX: Анатомия параллелизма
вернуться

Цилюрик Олег Иванович

Шрифт:

Еще одним важнейшим атрибутом потока является приоритет его выполнения. Для каждого из уровней приоритетов, обслуживаемых системой (в 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
невозможно предсказать, какой поток получит управление: породивший, порожденный или вообще произвольный поток из другого процесса. Это важно учитывать при передаче новому потоку данных и других операциях начальной инициализации параметров внутри созданного потока.

В отличие от создаваемых параллельных процессов, рассмотренных ранее, все потоки, создаваемые в рамках одного процесса, разделяют единое адресное пространство процесса, и поэтому все переменные процесса, находящиеся в области видимости любого потока, доступны этому потоку.

Атрибуты потока

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

pthread_create(NULL, NULL, &thread_func, NULL);

  • Читать дальше
  • 1
  • ...
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: