Планирование нитей

В библиотеке нитей предусмотрен набор функций для планирования нитей и управления планированием.

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

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

С помощью библиотеки нитей программист может управлять планированием обработки нитей следующими способами:
  • Настройка атрибутов планирования при создании нити
  • Динамическое изменение атрибутов планирования уже созданной нити
  • Определение влияния взаимной блокировки на планирование нитей при создании взаимной блокировки (планирование синхронизации).
  • Динамическое изменение атрибутов планирования нити в ходе синхронизации (планирование синхронизации).

Параметры планирования

У нити есть следующие параметры планирования:

Параметр Описание
область действия Область действия нити определяется моделью обработки нитей, используемой библиотекой.
стратегия Стратегия планирования нити определяет, как планировщик работает с нитью после передачи ей управления.
приоритет Приоритет планирования нити определяет относительную степень важности ее выполнения.

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

Работа с атрибутом inheritsched

Атрибут inheritsched объекта атрибутов нити указывает способ определения атрибутов планирования нити. Возможны следующие значения:

Значения Описание
PTHREAD_INHERIT_SCHED Означает, что новая нить наследует набор атрибутов планирования (атрибуты schedpolicy и schedparam) от породившей ее нити. Атрибуты планирования, указанные в объекте атрибутов, игнорируются.
PTHREAD_EXPLICIT_SCHED Означает, что атрибуты планирования вновь созданной нити берутся из соответствующего объекта атрибутов.

Значение атрибута inheritsched по умолчанию равно PTHREAD_INHERIT_SCHED. Значение атрибута изменяется с помощью функции pthread_attr_setinheritsched. Функция pthread_attr_getinheritsched возвращает текущее значение атрибута.

Для установки значений атрибутов планирования в объекте атрибутов нити следует сначала установить значение inheritsched равным PTHREAD_EXPLICIT_SCHED. В противном случае значения атрибутов планирования из объекта атрибутов будут проигнорированы.

Стратегия и приоритеты планирования

В библиотеке нитей реализованы следующие стратегии планирования:

Библиотека Описание
SCHED_FIFO Планирование по принципу простой очереди "первый вошел, первый вышел" (FIFO). Каждой нити присваивается постоянный приоритет; если несколько нитей имеют один и тот же приоритет, они выполняются в порядке FIFO.
SCHED_RR Планирование по принципу "карусели" (RR). Каждой нити присваивается постоянный приоритет; если несколько нитей имеют один и тот же приоритет, им в порядке FIFO выделяются равные значения времени процессора.
SCHED_OTHER Способ планирования, принятый в AIX по умолчанию. Каждой нити присваивается приоритет, который планировщик может динамически изменять в соответствии с уровнем ее активности; каждой нити выделяется определенное число квантов времени. В других системах могут применяться другие стратегии планирования.

До AIX версии 5.3 изменение приоритета нити при указании стратегии планирования SCHED_OTHER недопустимо. В этом случае ядро напрямую управляет приоритетом и функции pthread_setschedparam можно передать только значение DEFAULT_PRIO. Значение DEFAULT_PRIO определено в файле pthread.h в качестве 1. Прочие значения игнорируются.

Начиная с AIX 5.3, вы можете изменить приоритет нити при указании стратегии планирования SCHED_OTHER. Функции pthread_setschedparam можно передавать значение от 40 до 80, однако значения, превышающие 60, могут указывать только привилегированные пользователи. Приоритет в диапазоне от 1 до 39 соответствует приоритету 40, а приоритет от 81 до 127 - приоритету 80.

Прим.: Ядро AIX инвертирует значения уровня приоритета. В ядре AIX возможные значения приоритета - от 0 до 127, причем 0 означает наивысший приоритет, а 127 - низший. Команда ps и подобные ей возвращают значения приоритета ядра.
В библиотеке нитей для управления приоритетами предусмотрена структура sched_param, определенная в файле заголовка sys/sched.h. Эта структура содержит следующие поля:
Поля Описание
sched_priority Задает приоритет.
sched_policy Это поле игнорируется библиотекой нитей. Не используйте его.

Установка стратегии планирования и приоритета при создании нити

Для задания стратегии планирования при создании нити следует установить соответствующее значение атрибута schedpolicy в объекте атрибутов нити. С помощью функции pthread_attr_setschedpolicy можно присвоить атрибуту schedpolicy любое из определенных ранее значений. Текущее значение атрибута schedpolicy для данной нити можно узнать с помощью функции pthread_attr_getschedpolicy.

Для задания приоритета планирования при создании нити следует установить соответствующее значение атрибута schedparam в объекте атрибутов нити. Функция pthread_attr_setschedparam устанавливает значение атрибута schedparam, копируя его из указанной структуры. Функция pthread_attr_getschedparam возвращает текущее значение атрибута schedparam.

В приведенном ниже фрагменте кода описывается создание нити со стратегией планирования "карусель" и уровнем приоритета 3:

sched_param schedparam;

schedparam.sched_priority = 3;

pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &schedparam);

pthread_create(&thread, &attr, &start_routine, &args);
pthread_attr_destroy(&attr);
Атрибут inheritsched подробно описан в разделе Работа с атрибутом inheritsched.

Установка атрибутов планирования во время выполнения

Функция pthread_getschedparam возвращает значения атрибутов нити schedpolicy и schedparam. Установить эти атрибуты можно с помощью функции pthread_setschedparam. При изменении стратегии и приоритета нити, которая в этот момент обрабатывается процессором, новые значения вступят в силу при следующей обработке нити. Если нить в данный момент не обрабатывается, она может быть запущена сразу после вызова функции установки атрибутов.

Допустим, например, для нити Т применяется стратегия планирования round-robin, и во время обработки этой нити значение ее атрибута schedpolicy изменяется на FIFO. Нить T будет выполняться до конца выделенного ей времени, после чего вступят в силу новые атрибуты планирования. Если нити с более высоким приоритетом отсутствуют, Т будет запущена еще раз, даже есть другие нити с тем же приоритетом, что и Т. Другой пример: пусть нить имеет низкий приоритет и в данный момент не обрабатывается. Если другая нить повысит ее приоритет с помощью функции pthread_setschedparam, то при отсутствии нитей с более высоким приоритетом исходная нить будет запущена сразу же.

Прим.: В обеих рассмотренных функциях применяются два параметра: параметр policy и структура sched_param. Хотя в этой структуре и есть поле sched_policy, программы не должны работать с ним. Рассмотренные функции передают информацию о стратегии планирования в параметре policy, игнорируя поле sched_policy.

Сведения о стратегии планирования

В приложениях следует применять стратегию планирования по умолчанию, кроме специальных приложений, для которых необходимо применять постоянные приоритеты. При работе со стратегиями, отличными от стратегии по умолчанию, учтите следующее:
  • При применении стратегии round-robin все нити с одинаковым приоритетом, независимо от уровня их активности, находятся в равном положении. Это может оказаться полезным при написании программ, в которых необходимо опрашивать датчики или периодически записывать информацию на внешние устройства.
  • Стратегию FIFO следует применять с большой осторожностью. Нить, для которой применяется стратегия FIFO, будет выполняться без перерывов до самого завершения, если она не блокирована вызовом такой операции, как ввод или вывод. Прервать выполнение нити со стратегией FIFO и высоким приоритетом нельзя, и такая нить может значительно снизить общую производительность системы. Никогда не задавайте стратегию FIFO для нитей с большим объемом вычислений (например, обращение большой матрицы) и им подобных.

Стратегия планирования и приоритет нити зависят также и от ее области действия. Применять стратегии FIFO и round-robin можно не всегда.

sched_yield, функция

Функция sched_yield - это эквивалент функции yield для нитей. Функция sched_yield принудительно освобождает процессор и предоставляет возможность планирования других нитей. Следующая запланированная нить может относиться к тому же или к другому процессу. Функцию yield не следует использовать в программах с несколькими нитями.

Интерфейс функции pthread_yield недоступен в спецификации Single UNIX Specification версии 2.