Вход/Регистрация
Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
вернуться

Кёртен Роб

Шрифт:

printf("ND узла magenta — %d\n", magenta_nd);

remote_nd = netmgr_remote_nd(magenta_nd, ND_LOCAL_NODE);

printf("С точки зрения узла magenta, наш ND — %d\n",

 remote_nd);

Это программа могла бы вывести что-то вроде следующего:

ND узла magenta - 7

С точки зрения узла magenta, наш ND — 4

Это говорит о том, что на узле

magenta
нашему узлу соответствует дескриптор «4». (Обратите внимание на использование специальной константы ND_LOCAL_NODE, которая в действительности равна нулю, для указания на «локальный узел»).

Теперь вернемся к тому, о чем мы говорили в разделе «Кто послал сообщение?»). Параметр

struct _msg_info
содержит, среди всего прочего, два дескриптора узлов:

struct _msg_info {

 int nd;

 int srcnd;

 ...

};

Мы определили в описании для этих двух полей, что:

• nd — дескриптор принимающего узла с точки зрения передающего;

• srcnd — дескриптор передающего узла с точки зрения принимающего.

Так, для приведенного выше примера, где узел

wintermute
— локальный, а узел
magenta
— удаленный, когда узел
magenta
посылает нам (узлу
wintermute
) сообщение, эти поля заполняются следующим образом:

• nd равен 7;

• srcnd равен 4.

Наследование приоритетов

Одним из интересных моментов в операционных системах реального времени является феномен инверсии приоритетов.

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

Вы, наверное, сейчас думаете: «Минуточку! Вы утверждали ранее, что поток с более высоким приоритетом будет всегда вытеснять поток с более низким приоритетом! Как же такое может быть?»

Вы абсолютно правы. Поток с более высоким приоритетом всегда будет вытеснять поток с более низким приоритетом. Но при этом все-таки может произойти кое-что интересное. Давайте рассмотрим сценарий с тремя потоками (в трех различных процессах, для простоты рассмотрения), где «L» — поток с низким приоритетом, «Н» — поток с высоким приоритетом, и «S» — сервер. На рисунке показаны все три потока со своими приоритетами.

Три потока с различными приоритетами.

В данный момент выполняется поток Н. Потоку сервера S, имеющему наивысший приоритет, пока делать нечего, так что он находится в режиме ожидания и блокирован на функции MsgReceive. Поток L и хотел бы работать, но его приоритет ниже, чем у потока Н, который выполняется в данный момент. Все как вы и предполагали, да?

А теперь представьте себе, что поток Н принял решение «прикорнуть» на 100 миллисекунд — возможно, чтобы подождать медленное оборудование. Теперь выполняется поток L.

Вот тут-то все интересное и начинается.

В пределах своего нормального функционирования поток L посылает сообщение потоку сервера S, принуждая этим сервер S перейти в состояние READY и (поскольку поток S имеет высший приоритет из всех готовых к выполнению потоков) начать выполняться. К великому сожалению, сообщение, которое поток L направил к потоку сервера S, было сформулировано так: «Вычислить значение Пи с точностью до 50 знаков после запятой».

Очевидно, это займет более чем 100 миллисекунд. Поэтому, когда 100 миллисекунд сна потока Н истекут, поток Н перейдет в состояние READY — угадайте, что дальше? Поток Н не активизируется, постольку в состоянии READY находится поток S, имеющий более высокий приоритет!

Что здесь произошло? Произошло то, что поток с низким приоритетом «отстранил» от работы поток с более высоким приоритетом путем передачи процессора потоку с еще более высоким приоритетом. Это явление называется инверсией приоритетов.

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

Блокированные потоки.

При таком сценарии по истечении 100-миллисекундного интервала бездействия потока Н этот поток переходит в состояние READY и немедленно ставится на выполнение как имеющий наивысший приоритет.

Неплохо; однако, здесь есть еще один тонкий момент.

Предположим, что потоку Н вдруг становится нужно выполнить какие-то вычисления — например, найти 5034-е по порядку простое число. Он посылает сообщение потоку сервера S и блокируется.

Однако, в данный момент S по-прежнему вычисляет значение Пи, находясь на приоритете 5! В нашей выбранной для примера системе наверняка достаточно других потоков, имеющих приоритет выше, чем 5, которым тоже нужен процессор. Это автоматически значит, что процессорного времени на вычисление значения Пи у S остается не так уж и много.

  • Читать дальше
  • 1
  • ...
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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