res = pthread_create(&a_thread, &thread_attr, thread_function, (void*)message);
и для завершенности уничтожение атрибутов после их использования:
pthread_attr_destroy(&thread_attr);
Атрибуты планирования потока
Давайте рассмотрим второй атрибут потока, который вам, возможно, захочется изменить, — атрибут планирования. Изменение этого атрибута очень похоже на установку отсоединенного состояния потока, но есть дополнительные функции, которые можно применять для подбора допустимых уровней приоритета, sched_get_priority_max
и sched_get_priority_min
.
Выполните упражнение 12.6.
Упражнение 12.6. Планирование
Поскольку данная программа thread6.c очень похожа на программу предыдущего упражнения, мы рассмотрим только отличия.
1. Прежде всего, вам понадобится несколько дополнительных переменных:
int max_priority;
int min_priority;
struct sched_param scheduling_value;
2. После того как установлен атрибут отсоединения, вы задаете политику планирования:
res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER);
if (res != 0) {
perror("Setting scheduling policy failed");
exit(EXIT_FAILURE);
}
3. Далее находите диапазон допустимых приоритетов
max_priority = sched_get_priority_max(SCHED_OTHER);
min_priority = sched_get_priority_min(SCHED_OTHER);
и задаете один из них:
scheduling_value.sched_priority = min_priority;
res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);
if (res != 0) {
perror("Setting scheduling priority failed");
exit(EXIT_FAILURE);
}
Когда вы запустите программу, то получите следующий вывод:
$ ./thread6
Waiting for thread to say it's finished...
thread_function is running. Argument was Hello World
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Second thread setting finished flag, and exiting now
Other thread finished, bye!
Как это работает
Этот пример очень похож на установку атрибута отсоединенного состояния за исключением того, что вы задаете вместо него способ планирования.
Иногда требуется, чтобы один поток попросил другой завершиться досрочно способом, очень похожим на отправку ему сигнала. Сделать это можно с помощью потоков и параллельно с помощью обработки сигнала; у потоков появляется возможность изменить свое поведение, когда их просят завершиться.
Давайте сначала рассмотрим функцию для создания запроса на завершение потока.
#include
int pthread_cancel(pthread_t thread);
Она достаточно проста: имея идентификатор потока, вы можете запросить его аннулирование. На приемном конце запроса на отмену все немного сложнее, но не слишком. Поток может установить состояние отмены с помощью функции pthread_setcancelstate
.
#include
int pthread_setcancelstate(int state, int *oldstate);
Первый параметр равен либо значению PHTREAD_CANCEL_ENABLE
, позволяющему получать запросы на отмену, либо PTHREAD_CANCEL_DISABLE
, заставляющему игнорировать подобные запросы. Указатель oldstate
дает возможность получить предыдущее состояние. Если оно вас не интересует, можно просто передать в этом параметре NULL
. Если запросы на отмену принимаются, есть второй уровень управления, принимаемый потоком, — тип отмены, который задается функцией pthread_setcanceltype
.
#include
int pthread_setcanceltype(int type, int *oldtype);
Тип отмены может принимать одно из следующих значений: PTHREAD_CANCEL_ASYNCHRONOUS
, заставляющее обрабатывать запросы на отмену немедленно, и PTHREAD_CANCEL_DEFERRED
, заставляющее запросы на отмену ждать, пока поток не выполнит одну из следующих функций: pthread_join
, pthread_cond_wait
, pthread_cond_timedwait
, pthread_testcancel
, sem_wait
или sigwait
.
Мы не описываем все эти функции в данной главе, поскольку, как правило, не все они нужны. Когда они понадобятся, вы сможете найти дополнительную информацию на страницах интерактивного справочного руководства.
Примечание
В соответствии со стандартом POSIX системные вызовы, способные задерживать выполнение, такие как read
, wait
и т.д., должны также быть точками отмены потока. Во время написания книги поддержка этого стандарта в ОС Linux представлялась незавершенной. Но кое-какая работа была проделана, скажем, некоторые задерживающие вызовы, такие как sleep
, на самом деле допускают отмену. Для того чтобы обезопасить себя, добавляйте вызовы pthread_testcancel
в программный код, который по вашим расчетам может быть отменен.
Читать дальше