[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]

Программирование: Разработка и отладка программ


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

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

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

Основные средства планирования

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

Атрибут 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 по умолчанию. Каждой нити присваивается приоритет, который планировщик может динамически изменять в соответствии с уровнем ее активности; каждой нити выделяется определенное число квантов времени. В других системах могут применяться другие стратегии планирования.

По умолчанию применяется стратегия планирования SCHED_OTHER.

Приоритет - это целое число в диапазоне от 1 до 127. 1 означает самый маленький приоритет, 127 - самый большой. Уровень приоритета 0 зарезервирован для системных целей, и его использовать нельзя. Заметим, что ядро 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. При изменении стратегии и приоритета нити, которая в этот момент обрабатывается процессором, новые значения вступят в силу при следующей обработке нити. Если нить в данный момент не обрабатывается, она может быть запущена сразу после вызова функции установки атрибутов.

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

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

Особенности стратегий планирования

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

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

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

Стратегия планирования и приоритет нити зависят также и от ее области действия. Применять стратегии FIFO и RR можно не всегда. Дополнительная информация по этому вопросу приведена в разделе Влияние области действия на планирование.

Область действия

В библиотеке нитей определены две возможных области действия:

PTHREAD_SCOPE_PROCESS Область действия - процесс (локальная нить). Это означает, что при запуске нити учитываются все остальные нити процесса с локальной областью действия.
PTHREAD_SCOPE_SYSTEM Область действия - система (глобальная нить). Это означает, что при запуске нити учитываются все остальные нити в системе.

Дополнительная информация об областях действия приведена в разделе Реализация нитей.

Задание области действия

Область действия нити можно задать только до ее создания. Для этого следует установить соответствующее значение атрибута contention-scope в объекте атрибутов нити. Функция pthread_attr_setscope устанавливает значение этого атрибута, а функция pthread_attr_getscope возвращает его текущее значение.

Область действия нитей имеет значение только в реализации библиотеки для смешанной модели обработки нитей M:N. В реализации библиотеки для модели 1:1, как в AIX более ранних версий, чем 4.3, попытка установить значение атрибута contention-scope равным PTHREAD_SCOPE_PROCESS всегда вызывает ошибку, так как областью действия всех нитей является система. Это простейший способ узнать, какая реализация библиотеки нитей установлена в системе. Процедура TestImplementation может выглядеть так:

int TestImplementation()
{
        pthread_attr_t a;
        int result;

        pthread_attr_init(&a);
        switch (pthread_attr_setscope(&a, PTHREAD_SCOPE_PROCESS))
        {
                case 0:          result = LIB_MN; break;
                case ENOTSUP:    result = LIB_11; break;
                case ENOSYS:     result = NO_PRIO_OPTION; break;
                default:         result = ERROR; break;
        }

        pthread_attr_destroy(&a);
        return result;
}

В версиях AIX, предшествующих 4.3, эта процедура должна возвращать LIB_11.

В AIX версии 4.3 она возвращает LIB_MN.

Влияние области действия на планирование

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

В AIX стратегии планирования с постоянным приоритетом (FIFO и RR) могут применяться только для нитей ядра с правами root. При попытке выполнить следующий фрагмент программы:

schedparam.sched_priority = 3;
pthread_setschedparam(pthread_self(), SCHED_FIFO, schedparam);

будет возвращен код ошибки EPERM (при условии, что вызывающая нить относится к системной области, но не имеет прав доступа root). Если же область действия вызывающей нити - процесс, то ошибка не возникнет. Для управления параметрами планирования пользовательских нитей уровня процесса права доступа root не требуются.

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

Функция sched_yield

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

Интерфейс функции pthread_yield недоступен в XOPEN версии 5.

Связанная информация

Рекомендации по созданию программ с нитями

Планирование - Обзор

Планирование при синхронизации

"Список функций планирования" .

Необязательные компоненты библиотеки работы с нитями


[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]