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

Кёртен Роб

Шрифт:

Вот что происходит, когда мы используем InterruptAttach:

Поток управления при использовании InterruptAttach.

Выполняющийся поток («Поток 1») прерывается, и мы переключаемся в ядро. Ядро сохраняет контекст «Потока 1». Затем ядро смотрит, кто ответственен за обработку данного прерывания и решает, что это «ISR». Ядро настраивает контекст для «ISR» и передает ему управление. «ISR» опрашивает аппаратуру и решает возвратить

struct sigevent
. Ядро отмечает возвращаемое событие, выясняет, кто должен его обработать, и переводит их в состояние READY. Это может привести к планированию ядром другого потока, «Потока 2».

Теперь давайте сопоставим это с тем, что будет происходить при использовании InterruptAttachEvent:

Поток управления при использовании InterruptAttachEvent.

В этом случае путь обслуживания прерываний намного короче. Мы выполнили одно переключение контекста от выполнявшегося потока («Поток 1») в ядро. Вместо второго переключения контекста в ISR ядро просто «притворилось», что получило от ISR

struct sigevent
и среагировало на него, запланировав «Поток 2».

Теперь вы думаете: «Великолепно! Забудем про InterruptAttach и будем использовать простую функцию InterruptAttachEvent.»

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

В этом случае, особенно если бы последовательный порт принимал символы (которые вы хотели бы проигнорировать), вы бы потратили много времени впустую на перепланирование своего потока — и только ради того, чтобы он проанализировал состояние последовательного порта и принял решение, что ничего делать не надо. В данном случае все бы выглядело примерно так:

Поток управления при использовании InterruptAttachEvent с излишним перепланированием.

Происходящее по сути заключается в том, что вы вызываете переключение контекста для перехода к «Потоку 2», он опрашивает аппаратуру и понимает, что делать ничего не требуется, и это влечет за собой еще одно лишнее переключение контекста обратно в «Поток 1».

Вот что произошло бы, если бы вы применили функцию InterruptAttach, но не пожелали планировать другой поток (т.е. просто вернулись обратно):

Поток управления при использовании InterruptAttach без перепланирования потоков.

Ядро знает, что выполнялся «Поток 1», и что ISR не сказал ему что-либо сделать, поэтому после прерывания оно может смело вернуть управление «Потоку 1».

Для справки: вот что делает функция InterruptAttachEvent (это не реальный исходный текст, поскольку функция InterruptAttachEvent в действительности связывает с ядром структуру данных — она не реализована как отдельная вызываемая функция!):

// «Внутренний» обработчик

static const struct sigevent*

internalHandler(void *arg, int id) {

 struct sigevent *event = arg;

 InterruptMask(intr, id);

 return (arg);

}

int InterruptAttachEvent(int intr,

const struct sigevent *event, unsigned flags) {

 static struct sigevent static_event;

 memcpy(&static_event, event, sizeof(static_event));

 return

(InterruptAttach(intr, internalHandler, &static_event,

sizeof(*event), flags));

}

Что выбрать?

Так какую функцию применять? От редко возникающих прерываний почти всегда можно отмахнуться применением InterruptAttachEvent. Поскольку прерывания будут происходить редко, даже лишние перепланирования потоков значительного воздействия на общую производительность системы не окажут. Единственный момент, когда это проявится — это если на данном прерывании будут «сидеть» еще и другие устройства; в этом случае, поскольку функция InterruptAttachEvent маскирует источник прерывания, то это прерывание останется заблокированным до тех пор, пока источник не будет демаскирован обратно. Если при этом первое устройство требует много времени на обслуживание, остальным придется все это время ждать демаскирования. По большому счету, это проблема аппаратной организации системы — не следует размещать медленные устройства на одной линии прерывания с быстрыми.

  • Читать дальше
  • 1
  • ...
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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