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

Кёртен Роб

Шрифт:

Подключение обработчиков прерываний

Для подключения к источнику прерывания воспользуйтесь функцией InterruptAttach или InterruptAttachEvent.

#include <sys/neutrino.h>

int InterruptAttachEvent(int intr,

 const struct sigevent *event, unsigned flags);

int InterruptAttach(int intr,

 const struct sigevent* (*handler)(void *area, int id),

 const void *area, int size, unsigned flags);

Параметр intr определяет, к какому прерыванию вы хотите подключить обработчик.

Передаваемые значения определяются стартовым кодом, который перед запуском QNX/Neutrino, среди прочего, инициализирует контроллер обработки прерываний. (В документации по QNX/ Neutrino приводится подробная информация о стартовом коде; см. Справочник по утилитам, главы

startup-*
, например,
startup-p5064
.)

Уже здесь функции InterruptAttach и InterruptAttachEvent различаются. Рассмотрим сначала функцию InterruptAttachEvent, как более простую. Затем вернемся к рассмотрению функции InterruptAttach.

Подключение с помощью функции InterruptAttachEvent

Функция InterruptAttachEvent принимает два дополнительных аргумента: event, который является указателем на структуру

struct sigevent
, описывающую генерируемое событие, а также flags. Функция InterruptAttachEvent сообщает ядру, что при обнаружении прерывания должно быть сгенерировано событие event, после чего данный уровень прерываний должен быть демаскирован. Отметьте, что за то, как интерпретировать событие и какой поток перевести в состояние READY, отвечает ядро, при обнаружении прерывания.

Подключение с помощью функции InterruptAttach

При использовании функции InterruptAttach мы определяем другой набор параметров. Параметр handler — это адрес функции, которую надо вызвать. Как видно из прототипа, функция handler возвращает структуру

struct sigevent
(указывающую на тип события, которое следует сгенерировать) и принимает два параметра. Первый передаваемый параметр — area, тот самый, который передается функции InterruptAttach. Второй параметр, id, — идентификатор прерывания, его также возвращает InterruptAttach. Он применяется для идентификации прерывания, а также для маскирования, демаскирования, блокировки и деблокировки прерывания. Четвертый параметр InterruptAttach, size, указывает размер (в байтах) области данных, которая передается в параметре area. И, наконец, пятый параметр — flags — тот же самый параметр flags, что и у InterruptAttachEvent; мы скоро к нему вернемся.

Теперь, когда вы подключились к прерыванию

Допустим, что вы уже вызвали функцию InterruptAttachEvent или InterruptAttach.

Поскольку подключение к прерываниям — не та вещь, которую вы хотели бы позволять кому попало, QNX/Neutrino позволяет делать это только потокам, у которых есть право «привилегированного ввода/вывода» («I/O privity») (см. функцию ThreadCtl в справочном руководстве по Си-библиотеке QNX/Neutrino). Получить это право могут только потоки, которые выполняются под идентификатором пользователя root или которые установили свой идентификатор пользователя в root при помощи setuid. Следовательно, реально эти права есть только у root. (Что, кстати, вполне логично — зачем несуперпользовательскому процессу привилегированный ввод/вывод? — прим. ред.)

Ниже приведен фрагмент программы, в котором реализовано подключение ISR к вектору аппаратного прерывания, идентифицируемого константой HW_SERIAL_IRQ:

#include <sys/neutrino.h>

int InterruptID;

const struct sigevent* intHandler(void *arg, int id) {

 ...

}

int main (int argc, char **argv) {

 interruptID =

InterruptAttach(HW_SERIAL_IRQ, intHandler, sevent,

sizeof(event), 0);

 if (interruptID == -1 {

fprintf(stderr, "%s: ошибка подключения к IRQ %d\n",

progname, W_SERIAL_IRQ);

perror(NULL);

exit(EXIT_FAILURE);

 }

 ...

 return (EXIT_SUCCESS);

}

Теперь, если по данному вектору произойдет прерывание, наш обработчик будет подвергнут диспетчеризации. При вызове функции InterruptAttach ядро демаскирует указанный источник прерываний на уровне контроллера (если это прерывание еще не демаскировано, что имело бы место в случае многочисленных обработчиков одного и то же прерывания).

Отключение обработчика прерывания

Когда вы закончили с обработчиком прерывания, вы можете пожелать уничтожить связь между ним и вектором:

int InterruptDetach(int id);

Я сказал «можете», потому что обрабатывающие прерывания потоки, как правило, используются в серверах, а серверы обычно не завершаются. Это часто ведет к предрассудку, что хорошо организованному серверу никогда не понадобится самостоятельно вызывать InterruptDetach. К тому же, при смерти потока или процесса ОС автоматически отключит все связанные с ним обработчики прерываний. Таким образом, если программа просто дойдет до конца main, вызовет exit или завершится по SIGSEGV, все ее ISR будут автоматически отключены от соответствующих векторов прерываний. (Впрочем, вы, вероятно, пожелаете сделать это несколько изящнее, запретив соответствующему устройству генерацию прерываний. Если же прерывание разделяемое, и его используют другие устройства, то здесь двух вариантов быть не может вообще — вы просто обязаны «убрать за собой», иначе у вас либо больше не будет прерываний (в режиме чувствительности по фронту), либо пойдет постоянный поток запросов на прерывание (в режиме чувствительности по уровню).

  • Читать дальше
  • 1
  • ...
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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