Мы приступаем к рассмотрению
Списки равноприоритетных потоков упорядочены, от первого элемента
(
С каждой
Реализация, удовлетворяющая стандарту POSIX, должна выбирать для
выполнения
Другие действия (предыдущие и последующие) специфичны для
установленной
SCHED_FIFO (
sched_setscheduler(), sched_setparam(), pthread_setschedparam(), policy и param.pthread_setschedprio(), prio.pthread_setschedprio(),
является выполняемым или готовым к выполнению, он помещается в pthread_setschedprio(), является выполняемым или готовым к
выполнению, воздействие на его позицию в списке определяется
направлением изменения, а именно:sched_yield(),
он помещается в Допустимый диапазон sched_get_priority_min() и sched_get_priority_max() с
аргументом SCHED_FIFO.
SCHED_FIFO называют "выполнением до
завершения" или "выполнением до блокирования". В
многопользовательских системах с разделением времени подобная
политика, разумеется, выглядела бы недружественной, но для систем
реального времени она хороша прежде всего своей детерминированностью.
SCHED_RR
( SCHED_FIFO с одним
исключением: когда время, в течение которого sched_rr_get_interval(), он перемещается в
Если
Несмотря на кажущуюся простоту, применение SCHED_RR будут справедливы следующие
утверждения:
Q, где Q – величина N наиболее приоритетных (N – 1) * Q единиц
времени (или, что почти то же, будет получать N * Q ).Если накладными и непредвиденными расходами процессорного времени
пренебречь нельзя, встает вопрос, на кого их списывать. От ответа на
этот вопрос зависит, какое из сформулированных выше утверждений
станет ложным. Если списывать расходы "на систему" и честно выделять
каждому Q единиц процессорного времени, поток может
возобновить свое выполнение существенно позднее, чем через (N – 1) *
Q единиц времени. Обычно для Q единиц процессорного времени, что делает ложным первое
утверждение, но гарантирует истинность второго. Разумеется, взрывная
активность периферийных устройств, "отвлекающих" SCHED_RR: ни один
Отметим, что стандарт POSIX-2001 не предоставляет средств для
установки размера
SCHED_FIFO и SCHED_RR, политика SCHED_SPORADIC
( sched_ss_repl_period описанной ранее структуры типа sched_param.
Доступный бюджет вычислительных ресурсов инициализируется значением
элемента sched_ss_init_budget той же структуры.
sched_priority
и sched_ss_low_priority структуры типа sched_param.
sched_ss_max_repl
структуры типа sched_param, sched_priority, в противном случае - sched_ss_low_priority. Если
значение sched_priority не больше, чем sched_ss_low_priority,
Когда поток, находящийся в sched_priority,
получает
sched_priority (из-за того, что он перестал быть блокированным и стал
готовым к выполнению, или из-за осуществления sched_priority,
вытесняется с sched_priority,
блокируется, израсходованное им процессорное время вычитается из
sched_priority,
исчерпывает отведенное ему процессорное время, он помещается в sched_ss_low_priority, израсходованное им процессорное время
вычитается из sched_ss_repl_period структуры типа sched_param. Число sched_ss_max_repl.sched_ss_initial_budget. Кроме того, если sched_ss_low_priority, он помещается в sched_priority Приведенное описание выглядит довольно замысловатым, хотя основная
идея относительно проста. Определенные вычислительные ресурсы
резервируются для обработки непериодических событий с высоким sched_priority ). Если отведенного времени не хватило,
остальные события обрабатываются в фоновом режиме с (низким) sched_ss_low_priority. Истраченное "приоритетное" время
возвращается в бюджет в результате выполнения
По стандарту реализация должна допускать не менее _POSIX_SS_REPL_MAX
ждущих
В целом стандартизованная SCHED_SPORADIC
представляет собой разумный компромисс между эффективностью обработки
непериодических событий, детерминированностью выполнения
периодических
SCHED_OTHER ). Она необходима, чтобы мобильные приложения могли
заявить, что они больше не нуждаются в
Используемые в приложении
Вообще говоря, установки и изменения атрибутов pthread_setschedprio(), или массово, в результате вызова одной
функции с несколькими аргументами или одним структурным аргументом
(такой, например, как pthread_setschedparam() ). При начальной
установке второй подход предпочтительнее. Из соображений
Интуитивно очевидно, что планировщик должен запускаться тогда, когда
происходят события, способные вызвать передачу
Стандарт детально и точно формулирует правила манипулирования
очередями потоков, готовых к выполнению, а также правила
Подчеркнем концептуальную экономность и целостность стандарта
POSIX-2001 применительно к
Естественно, стандарт не может регламентировать все. Некоторые
аспекты
Есть проблемы, трудные для текущего периода стандартизации. К таковым
относится
Наконец, у
Несмотря на то, что в стандарте POSIX-2001 приняты определенные меры
для ограничения
Мы приступаем к рассмотрению функций для
Стандарт POSIX-2001 предусматривает следующие функции управления sched_getscheduler() ( sched_getparam() ( sched_setscheduler() ( sched_setparam() (
#include <sched.h>
int sched_getscheduler (pid_t pid);
int sched_getparam (pid_t pid,
struct sched_param *param);
int sched_setscheduler (pid_t pid,
int policy,
const struct sched_param *param);
int sched_setparam (pid_t pid,
const struct sched_param *param);
Функция sched_getscheduler() возвращает в качестве (нормального)
результата -1 ). Если значение аргумента pid
равно нулю, имеется в виду вызывающий
Функция sched_getparam() записывает sched_param ; ее
нормальный результат равен нулю. (Напомним, что, согласно стандарту
POSIX-2001, у структуры типа sched_param только одно обязательное
поле – sched_priority.)
Весьма мощной является функция sched_setscheduler(). Она позволяет
установить новые
Вызов sched_setscheduler() не влияет впрямую на PTHREAD_SCOPE_PROCESS (из-за того, что меняются атрибуты
Любопытно отметить, что стандарт POSIX-2001 не требует атомарности
вызова sched_setscheduler() с точки зрения выполняющихся
Функция sched_setparam(), в отличие от sched_setscheduler(), изменяет
только
В общем случае заданный
Если новый
Если вызывающий
Стандарт POSIX-2001 предоставляет средства для опроса характеристик sched_get_priority_min() ) и
максимального ( sched_get_priority_max() ) среди допустимых sched_rr_get_interval() ) (см. листинг 6.2).
#include <sched.h>
int sched_get_priority_min (int policy);
int sched_get_priority_max (int policy);
int sched_rr_get_interval (pid_t pid,
struct timespec *q_ptr);
Функция sched_rr_get_interval() записывает по указателю q_ptr в
структуру типа timespec величину sched_get_priority_min() и sched_get_priority_max(), разумеется,
служат, соответственно,
Несколько особняком стоит альтруистическая функция sched_yield() (см.
листинг 6.3), позволяющая вызывающему
#include <sched.h> int sched_yield (void);
Следующая программа (см. листинг 6.4) иллюстрирует применение описанных функций. Возможные результаты ее выполнения для ОС Linux и операционной системы реального времени oc2000 показаны на листингах 6.5 и 6.6.
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Программа опрашивает характеристики политик планирования, */
/* а также атрибуты планирования текущего процесса */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <sched.h>
int main (void) {
struct sched_param shdprm; /* Значения параметров */
/* планирования */
struct timespec qp; /* Величина кванта */
/* процессорного времени */
printf ("Допустимые диапазоны приоритетов для разных "
"политик планирования\n");
printf ("SCHED_FIFO : от %d до %d\n",
sched_get_priority_min (SCHED_FIFO),
sched_get_priority_max (SCHED_FIFO));
printf ("SCHED_RR : от %d до %d\n",
sched_get_priority_min (SCHED_RR),
sched_get_priority_max (SCHED_RR));
printf ("SCHED_OTHER: от %d до %d\n",
sched_get_priority_min (SCHED_OTHER),
sched_get_priority_max (SCHED_OTHER));
printf ("Текущая политика планирования для текущего "
"процесса: ");
switch (sched_getscheduler (0)) {
case SCHED_FIFO:
printf ("SCHED_FIFO\n");
break;
case SCHED_RR:
printf ("SCHED_RR\n");
break;
case SCHED_OTHER:
printf ("SCHED_OTHER\n");
break;
case -1:
perror ("SCHED_GETSCHEDULER");
break;
default:
printf ("Неизвестная политика планирования\n");
}
if (sched_getparam (0, shdprm) == 0) {
printf ("Текущий приоритет текущего процесса: %d\n",
shdprm.sched_priority);
} else {
perror ("SCHED_GETPARAM");
}
shdprm.sched_priority = 50;
if (sched_setscheduler (0, SCHED_RR, shdprm) == -1) {
perror ("SCHED_SETSCHEDULER");
}
if (sched_rr_get_interval (0, qp) == 0) {
printf ("Квант процессорного времени при "
"циклическом планировании: %g сек\n",
qp.tv_sec + qp.tv_nsec / 1000000000.0);
} else {
perror ("SCHED_RR_GET_INTERVAL");
}
return 0;
}
Допустимые диапазоны приоритетов для разных политик планирования SCHED_FIFO : от 1 до 99 SCHED_RR : от 1 до 99 SCHED_OTHER : от 0 до 0 Текущая политика планирования для текущего процесса: SCHED_OTHER Текущий приоритет текущего процесса: 0 Квант процессорного времени при циклическом планировании: 0.15 сек
Допустимые диапазоны приоритетов для разных политик планирования SCHED_FIFO : от 1 до 255 SCHED_RR : от 1 до 255 SCHED_OTHER : от 0 до 255 Текущая политика планирования для текущего процесса: SCHED_FIFO Текущий приоритет текущего процесса: 100 Квант процессорного времени при циклическом планировании: 0.08 сек
Проиллюстрируем теперь ситуацию с
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Программа моделирует ситуацию инверсии приоритетов. */
/* Идея состоит в том, что имеется три потока */
/* управления с низким, средним */
/* и высоким приоритетами. */
/* Поток с низким приоритетом захватывает семафор, */
/* когда на него никто больше не претендует, */
/* но не может освободить его, */
/* потому что его вытесняет с процессора */
/* поток со средним приоритетом. */
/* В это время поток с высоким приоритетом хочет */
/* захватить тот же семафор, */
/* но он занят и неизвестно когда освободится... */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <assert.h>
static sem_t sem_mi; /* Семафор для потока со средним */
/* приоритетом */
static sem_t sem_hi; /* Семафор для потока с высоким */
/* приоритетом */
static double s = 0;
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Стартовая функция потока с высоким приоритетом */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
void *start_hi (void *dummy) {
printf ("Поток с высоким приоритетом перед захватом "
"семафора\n");
assert (sem_wait (sem_hi) == 0);
printf ("Поток с высоким приоритетом после захвата "
"семафора\n");
assert (sem_post (sem_hi) == 0);
return (NULL);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Стартовая функция потока со средним приоритетом */
/* * * * * * * * * * * * * * * * * * * * * * * * * */
void *start_mi (void *dummy) {
int i;
double d = 1;
printf ("Поток со средним приоритетом перед захватом "
"семафора\n");
assert (sem_wait (sem_mi) == 0);
/* Займем процессор вычислениями */
for (i = 1; i < 100000000; i++) {
s += d/i;
d = -d;
}
printf ("Поток со средним приоритетом перед "
"освобождением семафора\n");
assert (sem_post (sem_mi) == 0);
return (s);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Стартовая функция потока с низким приоритетом */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
int main (void) {
pthread_attr_t attrob; /* Атрибутный объект */
/* создаваемых потоков */
struct sched_param shdprm; /* Значения параметров */
/* планирования */
int shdplc; /* Политика планирования */
pthread_t pt_mi; /* Идентификатор потока */
/* со средним приоритетом */
pthread_t pt_hi; /* Идентификатор потока */
/* с высоким приоритетом */
/* Создадим два семафора в захваченном состоянии */
assert (sem_init (sem_mi, 0, 0) == 0);
assert (sem_init (sem_hi, 0, 0) == 0);
/* Установим политику планирования и сделаем */
/* текущий поток управления низкоприоритетным */
shdprm.sched_priority = sched_get_priority_max
(SCHED_FIFO) – 31;
assert (pthread_setschedparam (pthread_self (),
SCHED_FIFO, shdprm) == 0);
/* Инициализируем атрибутный объект */
/* для создаваемых потоков управления */
assert (pthread_attr_init (attrob) == 0);
/* Установим атрибуты планирования */
assert (pthread_attr_setinheritsched (attrob,
PTHREAD_EXPLICIT_SCHED) == 0);
assert (pthread_attr_setschedpolicy (attrob,
SCHED_FIFO) == 0);
shdprm.sched_priority += 15;
assert (pthread_attr_setschedparam
(attrob, shdprm) == 0);
/* Создадим поток управления со средним приоритетом */
assert (pthread_create (pt_mi, attrob,
start_mi, NULL) == 0);
/* Подправим атрибутный объект и создадим */
/* поток управления с высоким приоритетом */
shdprm.sched_priority += 15;
assert (pthread_attr_setschedparam
(attrob, shdprm) == 0);
assert (pthread_create (pt_hi, attrob,
start_hi, NULL) == 0);
/* Опросим параметры планирования потоков управления */
assert (pthread_getschedparam (pthread_self (),
shdplc, shdprm) == 0);
assert (shdplc == SCHED_FIFO);
printf ("Низкий приоритет: %d\n",
shdprm.sched_priority);
assert (pthread_getschedparam
(pt_mi, shdplc, shdprm) == 0);
assert (shdplc == SCHED_FIFO);
printf (quot;Средний приоритет: %d\n",
shdprm.sched_priority);
assert (pthread_getschedparam
(pt_hi, shdplc, shdprm) == 0);
assert (shdplc == SCHED_FIFO);
printf ("Высокий приоритет: %d\n", shdprm.sched_priority);
/* Создадим ситуацию инверсии приоритетов */
printf ("Поток с низким приоритетом\n"
"перед освобождением семафора для потока "
"со средним приоритетом\n");
assert (sem_post (sem_mi) == 0);
printf ("Поток с низким приоритетом\n"
"перед освобождением семафора для потока "
"с высоким приоритетом\n");
assert (sem_post (sem_hi) == 0);
(void) pthread_join (pt_mi, NULL);
(void) pthread_join (pt_hi, NULL);
assert (sem_destroy (sem_mi) == 0);
assert (sem_destroy (sem_hi) == 0);
return 0;
}
Идея приведенной программы состоит в том, что у потоков управления с
низким и высоким приоритетами имеется общий семафор, охраняющий вход
в
Из технических деталей обратим внимание на использование значения PTHREAD_EXPLICIT_SCHED аргумента inheritsched функции pthread_attr_setinheritsched(). Оно предписывает извлекать
характеристики планирования создаваемых потоков управления из
атрибутного объекта, а не наследовать их у создающего потока. В
данном случае это важно, так как потоки управления необходимо
создавать с разными приоритетами.
Возможные результаты выполнения приведенной программы под управлением операционной системы реального времени oc2000 показаны на листинге 6.8.
Поток со средним приоритетом перед захватом семафора Поток с высоким приоритетом перед захватом семафора Низкий приоритет: 224 Средний приоритет: 239 Высокий приоритет: 254 Поток с низким приоритетом перед освобождением семафора для потока со средним приоритетом Поток со средним приоритетом перед освобождением семафора Поток с низким приоритетом перед освобождением семафора для потока с высоким приоритетом Поток с высоким приоритетом после захвата семафора
Мы приступаем к рассмотрению
Списки равноприоритетных потоков упорядочены, от первого элемента
(
С каждой
Реализация, удовлетворяющая стандарту POSIX, должна выбирать для
выполнения
Другие действия (предыдущие и последующие) специфичны для
установленной
SCHED_FIFO (
sched_setscheduler(), sched_setparam(), pthread_setschedparam(), policy и param.pthread_setschedprio(), prio.pthread_setschedprio(),
является выполняемым или готовым к выполнению, он помещается в pthread_setschedprio(), является выполняемым или готовым к
выполнению, воздействие на его позицию в списке определяется
направлением изменения, а именно:sched_yield(),
он помещается в Допустимый диапазон sched_get_priority_min() и sched_get_priority_max() с
аргументом SCHED_FIFO.
SCHED_FIFO называют "выполнением до
завершения" или "выполнением до блокирования". В
многопользовательских системах с разделением времени подобная
политика, разумеется, выглядела бы недружественной, но для систем
реального времени она хороша прежде всего своей детерминированностью.
SCHED_RR
( SCHED_FIFO с одним
исключением: когда время, в течение которого sched_rr_get_interval(), он перемещается в
Если
Несмотря на кажущуюся простоту, применение SCHED_RR будут справедливы следующие
утверждения:
Q, где Q – величина N наиболее приоритетных (N – 1) * Q единиц
времени (или, что почти то же, будет получать N * Q ).Если накладными и непредвиденными расходами процессорного времени
пренебречь нельзя, встает вопрос, на кого их списывать. От ответа на
этот вопрос зависит, какое из сформулированных выше утверждений
станет ложным. Если списывать расходы "на систему" и честно выделять
каждому Q единиц процессорного времени, поток может
возобновить свое выполнение существенно позднее, чем через (N – 1) *
Q единиц времени. Обычно для Q единиц процессорного времени, что делает ложным первое
утверждение, но гарантирует истинность второго. Разумеется, взрывная
активность периферийных устройств, "отвлекающих" SCHED_RR: ни один
Отметим, что стандарт POSIX-2001 не предоставляет средств для
установки размера
SCHED_FIFO и SCHED_RR, политика SCHED_SPORADIC
( sched_ss_repl_period описанной ранее структуры типа sched_param.
Доступный бюджет вычислительных ресурсов инициализируется значением
элемента sched_ss_init_budget той же структуры.
sched_priority
и sched_ss_low_priority структуры типа sched_param.
sched_ss_max_repl
структуры типа sched_param, sched_priority, в противном случае - sched_ss_low_priority. Если
значение sched_priority не больше, чем sched_ss_low_priority,
Когда поток, находящийся в sched_priority,
получает
sched_priority (из-за того, что он перестал быть блокированным и стал
готовым к выполнению, или из-за осуществления sched_priority,
вытесняется с sched_priority,
блокируется, израсходованное им процессорное время вычитается из
sched_priority,
исчерпывает отведенное ему процессорное время, он помещается в sched_ss_low_priority, израсходованное им процессорное время
вычитается из sched_ss_repl_period структуры типа sched_param. Число sched_ss_max_repl.sched_ss_initial_budget. Кроме того, если sched_ss_low_priority, он помещается в sched_priority Приведенное описание выглядит довольно замысловатым, хотя основная
идея относительно проста. Определенные вычислительные ресурсы
резервируются для обработки непериодических событий с высоким sched_priority ). Если отведенного времени не хватило,
остальные события обрабатываются в фоновом режиме с (низким) sched_ss_low_priority. Истраченное "приоритетное" время
возвращается в бюджет в результате выполнения
По стандарту реализация должна допускать не менее _POSIX_SS_REPL_MAX
ждущих
В целом стандартизованная SCHED_SPORADIC
представляет собой разумный компромисс между эффективностью обработки
непериодических событий, детерминированностью выполнения
периодических
SCHED_OTHER ). Она необходима, чтобы мобильные приложения могли
заявить, что они больше не нуждаются в
Используемые в приложении
Вообще говоря, установки и изменения атрибутов pthread_setschedprio(), или массово, в результате вызова одной
функции с несколькими аргументами или одним структурным аргументом
(такой, например, как pthread_setschedparam() ). При начальной
установке второй подход предпочтительнее. Из соображений
Интуитивно очевидно, что планировщик должен запускаться тогда, когда
происходят события, способные вызвать передачу
Стандарт детально и точно формулирует правила манипулирования
очередями потоков, готовых к выполнению, а также правила
Подчеркнем концептуальную экономность и целостность стандарта
POSIX-2001 применительно к
Естественно, стандарт не может регламентировать все. Некоторые
аспекты
Есть проблемы, трудные для текущего периода стандартизации. К таковым
относится
Наконец, у
Несмотря на то, что в стандарте POSIX-2001 приняты определенные меры
для ограничения
Мы приступаем к рассмотрению функций для
Стандарт POSIX-2001 предусматривает следующие функции управления sched_getscheduler() ( sched_getparam() ( sched_setscheduler() ( sched_setparam() (
#include <sched.h>
int sched_getscheduler (pid_t pid);
int sched_getparam (pid_t pid,
struct sched_param *param);
int sched_setscheduler (pid_t pid,
int policy,
const struct sched_param *param);
int sched_setparam (pid_t pid,
const struct sched_param *param);
Функция sched_getscheduler() возвращает в качестве (нормального)
результата -1 ). Если значение аргумента pid
равно нулю, имеется в виду вызывающий
Функция sched_getparam() записывает sched_param ; ее
нормальный результат равен нулю. (Напомним, что, согласно стандарту
POSIX-2001, у структуры типа sched_param только одно обязательное
поле – sched_priority.)
Весьма мощной является функция sched_setscheduler(). Она позволяет
установить новые
Вызов sched_setscheduler() не влияет впрямую на PTHREAD_SCOPE_PROCESS (из-за того, что меняются атрибуты
Любопытно отметить, что стандарт POSIX-2001 не требует атомарности
вызова sched_setscheduler() с точки зрения выполняющихся
Функция sched_setparam(), в отличие от sched_setscheduler(), изменяет
только
В общем случае заданный
Если новый
Если вызывающий
Стандарт POSIX-2001 предоставляет средства для опроса характеристик sched_get_priority_min() ) и
максимального ( sched_get_priority_max() ) среди допустимых sched_rr_get_interval() ) (см. листинг 6.2).
#include <sched.h>
int sched_get_priority_min (int policy);
int sched_get_priority_max (int policy);
int sched_rr_get_interval (pid_t pid,
struct timespec *q_ptr);
Функция sched_rr_get_interval() записывает по указателю q_ptr в
структуру типа timespec величину sched_get_priority_min() и sched_get_priority_max(), разумеется,
служат, соответственно,
Несколько особняком стоит альтруистическая функция sched_yield() (см.
листинг 6.3), позволяющая вызывающему
#include <sched.h> int sched_yield (void);
Следующая программа (см. листинг 6.4) иллюстрирует применение описанных функций. Возможные результаты ее выполнения для ОС Linux и операционной системы реального времени oc2000 показаны на листингах 6.5 и 6.6.
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Программа опрашивает характеристики политик планирования, */
/* а также атрибуты планирования текущего процесса */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <sched.h>
int main (void) {
struct sched_param shdprm; /* Значения параметров */
/* планирования */
struct timespec qp; /* Величина кванта */
/* процессорного времени */
printf ("Допустимые диапазоны приоритетов для разных "
"политик планирования\n");
printf ("SCHED_FIFO : от %d до %d\n",
sched_get_priority_min (SCHED_FIFO),
sched_get_priority_max (SCHED_FIFO));
printf ("SCHED_RR : от %d до %d\n",
sched_get_priority_min (SCHED_RR),
sched_get_priority_max (SCHED_RR));
printf ("SCHED_OTHER: от %d до %d\n",
sched_get_priority_min (SCHED_OTHER),
sched_get_priority_max (SCHED_OTHER));
printf ("Текущая политика планирования для текущего "
"процесса: ");
switch (sched_getscheduler (0)) {
case SCHED_FIFO:
printf ("SCHED_FIFO\n");
break;
case SCHED_RR:
printf ("SCHED_RR\n");
break;
case SCHED_OTHER:
printf ("SCHED_OTHER\n");
break;
case -1:
perror ("SCHED_GETSCHEDULER");
break;
default:
printf ("Неизвестная политика планирования\n");
}
if (sched_getparam (0, shdprm) == 0) {
printf ("Текущий приоритет текущего процесса: %d\n",
shdprm.sched_priority);
} else {
perror ("SCHED_GETPARAM");
}
shdprm.sched_priority = 50;
if (sched_setscheduler (0, SCHED_RR, shdprm) == -1) {
perror ("SCHED_SETSCHEDULER");
}
if (sched_rr_get_interval (0, qp) == 0) {
printf ("Квант процессорного времени при "
"циклическом планировании: %g сек\n",
qp.tv_sec + qp.tv_nsec / 1000000000.0);
} else {
perror ("SCHED_RR_GET_INTERVAL");
}
return 0;
}
Допустимые диапазоны приоритетов для разных политик планирования SCHED_FIFO : от 1 до 99 SCHED_RR : от 1 до 99 SCHED_OTHER : от 0 до 0 Текущая политика планирования для текущего процесса: SCHED_OTHER Текущий приоритет текущего процесса: 0 Квант процессорного времени при циклическом планировании: 0.15 сек
Допустимые диапазоны приоритетов для разных политик планирования SCHED_FIFO : от 1 до 255 SCHED_RR : от 1 до 255 SCHED_OTHER : от 0 до 255 Текущая политика планирования для текущего процесса: SCHED_FIFO Текущий приоритет текущего процесса: 100 Квант процессорного времени при циклическом планировании: 0.08 сек
Проиллюстрируем теперь ситуацию с
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Программа моделирует ситуацию инверсии приоритетов. */
/* Идея состоит в том, что имеется три потока */
/* управления с низким, средним */
/* и высоким приоритетами. */
/* Поток с низким приоритетом захватывает семафор, */
/* когда на него никто больше не претендует, */
/* но не может освободить его, */
/* потому что его вытесняет с процессора */
/* поток со средним приоритетом. */
/* В это время поток с высоким приоритетом хочет */
/* захватить тот же семафор, */
/* но он занят и неизвестно когда освободится... */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <assert.h>
static sem_t sem_mi; /* Семафор для потока со средним */
/* приоритетом */
static sem_t sem_hi; /* Семафор для потока с высоким */
/* приоритетом */
static double s = 0;
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Стартовая функция потока с высоким приоритетом */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
void *start_hi (void *dummy) {
printf ("Поток с высоким приоритетом перед захватом "
"семафора\n");
assert (sem_wait (sem_hi) == 0);
printf ("Поток с высоким приоритетом после захвата "
"семафора\n");
assert (sem_post (sem_hi) == 0);
return (NULL);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Стартовая функция потока со средним приоритетом */
/* * * * * * * * * * * * * * * * * * * * * * * * * */
void *start_mi (void *dummy) {
int i;
double d = 1;
printf ("Поток со средним приоритетом перед захватом "
"семафора\n");
assert (sem_wait (sem_mi) == 0);
/* Займем процессор вычислениями */
for (i = 1; i < 100000000; i++) {
s += d/i;
d = -d;
}
printf ("Поток со средним приоритетом перед "
"освобождением семафора\n");
assert (sem_post (sem_mi) == 0);
return (s);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Стартовая функция потока с низким приоритетом */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
int main (void) {
pthread_attr_t attrob; /* Атрибутный объект */
/* создаваемых потоков */
struct sched_param shdprm; /* Значения параметров */
/* планирования */
int shdplc; /* Политика планирования */
pthread_t pt_mi; /* Идентификатор потока */
/* со средним приоритетом */
pthread_t pt_hi; /* Идентификатор потока */
/* с высоким приоритетом */
/* Создадим два семафора в захваченном состоянии */
assert (sem_init (sem_mi, 0, 0) == 0);
assert (sem_init (sem_hi, 0, 0) == 0);
/* Установим политику планирования и сделаем */
/* текущий поток управления низкоприоритетным */
shdprm.sched_priority = sched_get_priority_max
(SCHED_FIFO) – 31;
assert (pthread_setschedparam (pthread_self (),
SCHED_FIFO, shdprm) == 0);
/* Инициализируем атрибутный объект */
/* для создаваемых потоков управления */
assert (pthread_attr_init (attrob) == 0);
/* Установим атрибуты планирования */
assert (pthread_attr_setinheritsched (attrob,
PTHREAD_EXPLICIT_SCHED) == 0);
assert (pthread_attr_setschedpolicy (attrob,
SCHED_FIFO) == 0);
shdprm.sched_priority += 15;
assert (pthread_attr_setschedparam
(attrob, shdprm) == 0);
/* Создадим поток управления со средним приоритетом */
assert (pthread_create (pt_mi, attrob,
start_mi, NULL) == 0);
/* Подправим атрибутный объект и создадим */
/* поток управления с высоким приоритетом */
shdprm.sched_priority += 15;
assert (pthread_attr_setschedparam
(attrob, shdprm) == 0);
assert (pthread_create (pt_hi, attrob,
start_hi, NULL) == 0);
/* Опросим параметры планирования потоков управления */
assert (pthread_getschedparam (pthread_self (),
shdplc, shdprm) == 0);
assert (shdplc == SCHED_FIFO);
printf ("Низкий приоритет: %d\n",
shdprm.sched_priority);
assert (pthread_getschedparam
(pt_mi, shdplc, shdprm) == 0);
assert (shdplc == SCHED_FIFO);
printf (quot;Средний приоритет: %d\n",
shdprm.sched_priority);
assert (pthread_getschedparam
(pt_hi, shdplc, shdprm) == 0);
assert (shdplc == SCHED_FIFO);
printf ("Высокий приоритет: %d\n", shdprm.sched_priority);
/* Создадим ситуацию инверсии приоритетов */
printf ("Поток с низким приоритетом\n"
"перед освобождением семафора для потока "
"со средним приоритетом\n");
assert (sem_post (sem_mi) == 0);
printf ("Поток с низким приоритетом\n"
"перед освобождением семафора для потока "
"с высоким приоритетом\n");
assert (sem_post (sem_hi) == 0);
(void) pthread_join (pt_mi, NULL);
(void) pthread_join (pt_hi, NULL);
assert (sem_destroy (sem_mi) == 0);
assert (sem_destroy (sem_hi) == 0);
return 0;
}
Идея приведенной программы состоит в том, что у потоков управления с
низким и высоким приоритетами имеется общий семафор, охраняющий вход
в
Из технических деталей обратим внимание на использование значения PTHREAD_EXPLICIT_SCHED аргумента inheritsched функции pthread_attr_setinheritsched(). Оно предписывает извлекать
характеристики планирования создаваемых потоков управления из
атрибутного объекта, а не наследовать их у создающего потока. В
данном случае это важно, так как потоки управления необходимо
создавать с разными приоритетами.
Возможные результаты выполнения приведенной программы под управлением операционной системы реального времени oc2000 показаны на листинге 6.8.
Поток со средним приоритетом перед захватом семафора Поток с высоким приоритетом перед захватом семафора Низкий приоритет: 224 Средний приоритет: 239 Высокий приоритет: 254 Поток с низким приоритетом перед освобождением семафора для потока со средним приоритетом Поток со средним приоритетом перед освобождением семафора Поток с низким приоритетом перед освобождением семафора для потока с высоким приоритетом Поток с высоким приоритетом после захвата семафора
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.