Чтение онлайн

на главную - закладки

Жанры

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

Кёртен Роб

Шрифт:

Происходящее по сути заключается в том, что вы вызываете переключение контекста для перехода к «Потоку 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 маскирует источник прерывания, то это прерывание останется заблокированным до тех пор, пока источник не будет демаскирован обратно. Если при этом первое устройство требует много времени на обслуживание, остальным придется все это время ждать демаскирования. По большому счету, это проблема аппаратной организации системы — не следует размещать медленные устройства на одной линии прерывания с быстрыми.

При выборе функции для более часто возникающих прерываний требуется учесть множество факторов:

• Ненужные прерывания — если их число будет существенным, лучше применять InterruptAttach и отфильтровывать их прямо в ISR, Возьмем, например, тот же случай с последовательным устройством. Поток может выдать команду: «Дай мне 64 байта». Если ISR запрограммирован с учетом того, что пока не будут приняты все 64 байта, ничего полезного не произойдет, все возникающие в процессе приема прерывания будут отфильтрованы. ISR возвратит событие только после окончания приема всех 64 байт.

• Время реакции — если ваши аппаратные

средства чувствительны к интервалу времени от момента выставления запроса на прерывание до отработки ISR, вам следует использовать InterruptAttach, чтобы свести это время к минимуму. Это сработает, потому что диспетчеризация ISR в ядре выполняется очень быстро.

• Буферизация — если ваша аппаратура имеет встроенные средства буферизации, вы можете обойтись функцией InterruptAttachEvent и очередью из единственного события, как в случае с комбинацией SIGEV_INTR и InterruptWait. Этот метод позволяет прерываниям возникать с такой частотой, как им захочется» при этом позволяя вашему потоку выбирать значения из буфера с такой скоростью, с какой он сможет. Поскольку данные буферизуются на аппаратном уровне, никаких проблем со временем реакции на прерывание не будет.

Функции, которые может вызывать ISR

Следующий вопрос, за который следует взяться, — это список функций, которые может вызывать ISR.

Небольшое отступление. Исторически, причина основных затруднений при написании обработчиков прерываний заключалась (и в большинстве других операционных систем до сих пор заключается) в том, что ISR работают в особом окружении.

Одна из конкретных причин, усложняющих написание ISR, состоит в том, что с точки зрения ядра ISR на самом деле не является «полноправным» потоком. С позиции ядра это, если хотите, такой таинственный «аппаратный» поток. Это означает, что ISR не имеет права делать никаких манипуляций «на уровне потока» — таких как, например, обмен сообщениями, синхронизация, системные вызовы, дисковый ввод/вывод, и т.д.

Не усложняет ли это написание ISR? Конечно. И поэтому решение заключается в том, чтобы в самом теле обработчика выполнять минимум работы, а все остальное делать уже на уровне потока, где есть доступ ко всем сервисам.

Ваши цели при написании ISR должны заключаться в следующем:

• считать переменчивую (в оригинале было «transient» — прим. ред.) информацию;

• очистить источник прерывания;

• возможно, запланировать поток, который сделает реальную работу.

Такая «архитектура « держится на том, что QNX/Neutrino обеспечивает очень быстрые времена переключения контекста. Вы знаете, что сможете быстро переключиться в ваш обработчик для выполнения работы, критичной по времени. Вы также знаете, что когда обработчик возвратит событие для запуска потока, то поток тоже активизируется очень быстро. И именно эта философия «ничего не делайте в теле ISR» делает обработчики прерываний в QNX/Neutrino столь простыми!

Итак, какие же вызовы можно использовать в теле ISR? Вот официальный список:

• функции семейства atomic_* (например, atomic_set);

• функции семейства mem* (типа memcpy);

• большинство функций семейства str* (типа strcmp). Остерегайтесь, однако, потому что не все эти функции являются безопасными — например, strdup вызывает malloc, в которой используется мутекс, а это запрещено.

Вообще, что касательно строковых функций, перед их использованием надо индивидуально смотреть их описание в руководстве по Си-библиотеке;

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

Газлайтер. Том 5

Володин Григорий
5. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 5

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...

Оживший камень

Кас Маркус
1. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Оживший камень

Архонт

Прокофьев Роман Юрьевич
5. Стеллар
Фантастика:
боевая фантастика
рпг
7.80
рейтинг книги
Архонт

Идеальный мир для Лекаря 18

Сапфир Олег
18. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 18

Возвращение

Жгулёв Пётр Николаевич
5. Real-Rpg
Фантастика:
боевая фантастика
рпг
альтернативная история
6.80
рейтинг книги
Возвращение

Золушка вне правил

Шах Ольга
Любовные романы:
любовно-фантастические романы
6.83
рейтинг книги
Золушка вне правил

Para bellum

Ланцов Михаил Алексеевич
4. Фрунзе
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Para bellum

Жандарм

Семин Никита
1. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
4.11
рейтинг книги
Жандарм

Провинциал. Книга 2

Лопарев Игорь Викторович
2. Провинциал
Фантастика:
космическая фантастика
рпг
аниме
5.00
рейтинг книги
Провинциал. Книга 2

Совок

Агарев Вадим
1. Совок
Фантастика:
фэнтези
детективная фантастика
попаданцы
8.13
рейтинг книги
Совок

ВоенТур 3

АЗК
3. Антиблицкриг
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
ВоенТур 3

Младший сын князя

Ткачев Андрей Сергеевич
1. Аналитик
Фантастика:
фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Младший сын князя

Новые горизонты

Лисина Александра
5. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Новые горизонты