Студопедия — Теоретические положения
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Теоретические положения






Несмотря на то, что обработка прерываний является ключевой особенностью ОСРВ, во многих традиционных операционных системах обработка прерываний реализована очень неуклюже. Но только не в QNX. Как будет показано ниже, обработка прерываний в QNX тривиальна: из-за быстрого времени переключения состояния процессора в QNX большая часть работы по обработки прерываний, обычно проводимая обработчиком прерываний, производится внутри потока.

Рассмотрим функции QNX по обработке прерываний.

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

Чтобы установить обработчик прерываний, основная программа должна сообщить ОС о том, что требуется связать обработчик прерываний с некоторым источником прерываний. На платформе x86 обычно существуют 16 аппаратных линий запросов на прерывания (IRQ) и несколько источников программных прерываний. На платформах MIPS и PPC фактическое число прерываний зависит от конфигурации аппаратного обеспечения, поставляемого производителем материнской платы. В любом случае, поток определяет, какой источник прерывания ему требуется связать с каким обработчиком прерываний, используя вызовы к функциям InterruptAttach() или InterruptAttachEvent().

Когда программа желает отключить обработчик прерываний от источника прерываний, она может вызвать InterruptDetach():

#define IRQ3 3

// прототип обработчика прерываний:

extern const sigevent *serint (void *, int);

...

/* связать обработчик прерываний "serint"

* с IRQ 3, т.е. с COM2: */

ThreadCtl(_NTO_TCTL_IO, 0);

id = InterruptAttach (IRQ3, serint, NULL, 0, 0);

...

// сделав работу, отключиться от источника прерываний:

InterruptDetach (id);

Так как обработчик прерываний может потенциально получить контроль над ЭВМ, то связывать источник прерывания с обработчиком позволено не каждому потоку. Поток должен иметь флаг I/O Privity для того, чтобы иметь возможность манипулировать портами ввода/вывода и изменять флаг разрешения прерываний процессором (т.е. следующими командами платформы x86: in, ins, out, outs, cli, и sti).

На текущий момент только пользователь «root» может получить привилегию I/O Privity.

2. Обработчик прерываний.

В приведенном выше примере, функция serint() является обработчиком прерываний. Обычно обработчик прерываний отвечает за:

§ определение аппаратного обеспечения, требующего обслуживания, если такое имеется;

§ проведение некоторого обслуживание данной аппаратуры (что обычно делается просто чтением и/или записью в аппаратные регистры);

§ обновление некоторых структур, общих между обработчиком прерываний и некоторыми потоками функционирующего приложения;

§ сообщение приложению того, что некоторое событие произошло.

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

Рассмотрим данные пункты подробнее.

3. Определение источника прерываний

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

Многие программируемые контроллеры прерываний (ПКП, PIC) могут быть запрограммированы на отработку прерываний в режиме, чувствительном только к фронту сигнала, или в режиме прерываний по уровню сигнала. В зависимости от этого, прерывания могут быть совместными (см. рис.2).

Рис.2 – Обработка прерываний от нескольких источников

В показанном на рис.2 случае, если ПКП функционирует в режиме прерываний по уровню сигнала, активным является тот запрос на прерывание (IRQ), который имеет наивысший уровень. Тогда второй запрос на прерывание (см. шаг 2 на рис.2) не вызовет нового прерывания. Прерывание будет активным, даже после того, как оригинальное прерывание убрано (шаг 3), до тех пор, пока последний запрос не убран (шаг 4).

В режиме, чувствительном только к фронту сигнала, прерывание запрашивается только один раз – на шаге 1. Только после того, как линия запроса на прерывание освободится, и появится новый запрос, ПКП будет считать, что появилось новое прерывание.

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

4. Обслуживание аппаратного обеспечения

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

В режиме, чувствительном только к фронту сигнала, нет таких ограничений.

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

Такой подход рекомендуется по следующим причинам:

· время переключения между обработчиком прерываний и потоком очень мало – обычно порядка нескольких микросекунд;

· из тела функции – обработчика прерываний – возможно вызвать только 7 функций ядра QNX;

· обработчик прерываний выполняется со значительно более высоким приоритетом, чем любая другая программы в ОС, таким образом, обработчик прерываний потребляет значительную часть процессорного времени, что отрицательно сказывается на работе ОС в реальном времени.

5. Функции, вызываемые из обработчика прерываний

Из тела функции – обработчика прерываний – невозможно вызывать ни одну функцию, кроме следующих 7 функций ядра QNX и функций str*() и mem*() (таких как strcpy() и memcpy()), кроме strdup():

· InterruptEnable()

· InterruptDisable()

· InterruptLock()

· InterruptUnlock()

· InterruptMask()

· InterruptUnmask()

Для предотвращения прерывания друг друга потоком и обработчиком прерывания, необходимо сообщить ядру об отключении на это время прерываний. На однопроцессорной системе для этого необходимо вызвать функцию InterruptDisable(). Но на многопроцессорной системе необходимо вызвать InterruptLock() (и для включения прерываний – InterruptUnlock()).

Для расширения портируемости кода рекомендуется и на однопроцессорных системах пользоваться функциями InterruptLock() и InterruptUnlock().

Функции InterruptMask() и InterruptUnmask() отключают и включают распознавание указанной линии запроса на прерывание в ПКП.

Пример реализации обработчика прерываний:

main ()

{

// произвести инициализацию и проч.

...

// запустить выделенный поток обработки прерываний:

pthread_create (NULL, NULL, int_thread, NULL);

...

// произвести дальнейшие действия

...

}

 

// выделенный поток обработки прерываний:

void *int_thread (void *arg)

{

// включить доступ к регистрам аппаратуры:

ThreadCtl (_NTO_TCTL_IO, NULL);

...

// инициализировать аппаратуру:

...

// связать обработчик прерываний с IRQ 3:

InterruptAttach (IRQ3, isr_handler, NULL, 0, 0);

...

// возможно, увеличить приоритет потока здесь

...

// произвести обслуживание аппаратуры, когда

// обработчик прерываний нам об этом сообщаит:

while (1)

{

InterruptWait (NULL, NULL);

// здесь обработчик прерываний сообщил о том,

// что оборудование вызвало прерывание и требует

// обслуживания

...

// произвести обслуживание

...

// Если в обработчике прерываний isr_handler

// была вызвана функция InterruptMask, то

// вызвать InterruptUnmask

}

}

// обработчик прерываний

const struct sigevent * isr_handler (void *arg, int id)

{

// проверяет, вызвало ли оборудование прерывание,

// если нет, то просто возвращает (NULL);

...

// в режиме прерываний по уровню сигнала следует

// очистить источник прерываний или вызвать

// InterruptMask

...

// возвратить указатель на структуру event,

// инициализированную в main значением SIGEV_INTR,

// это позволит функции InterruptWait в

// "int_thread" разблокироваться:

return (&event);

}

Функция InterruptAttach:

int InterruptAttach(int intr,

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

const void * area,

int size,

unsigned flags);

Аргументы:

intr – линия запроса на прерывание, с которой связывается обработчик прерываний;

handler – указатель на функцию – обработчик прерываний;

area – указатель на область обмена данных с основным процессов (если такая существует) или NULL иначе.

size – размер области обмена данных.

flags – флаги, определяющие как следует связать обработчик прерываний.

Функция InterruptMask:

int InterruptMask(int intr, int id);

Аргументы:

intr – маскируемое прерывание.

id – значение, возвращенное InterruptAttach() или InterruptAttachEvent(), или -1, если вы не хотите, чтобы ядро ОС отслеживало маскирование прерываний для каждого обработчика.

Значения аргумента id игнорируется, если вы при связывании обработчика прерываний с прерыванием не указали флаг _NTO_INTR_FLAGS_TRK_MSK.

Функция InterruptUnmask.

int InterruptUnmask(int intr, int id);

Аргументы:

intr – маскируемое прерывание.

id – значение, возвращенное InterruptAttach() или InterruptAttachEvent(), или -1, если вы не хотите, чтобы ядро ОС отслеживало маскирование прерываний для каждого обработчика. Значения аргумента id игнорируется, если вы при связывании обработчика прерываний с прерыванием не указали флаг _NTO_INTR_FLAGS_TRK_MSK.

Функция mmap_device_io – получить доступ к аппаратным регистрам устройства.

uintptr_t mmap_device_io(size_t len, uint64_t io);

Аргументы:

len – число байт памяти ввода/вывода устройства, доступ к которому необходимо получить.

io – адрес области памяти к которой необходимо получить доступ.

Функция out8 – записать 8-битовое значение в порт.

void out8(uintptr_t port, uint8_t val);

Аргументы:

port – порт ввода/вывода, в который необходимо осуществить запись.

val – значение, которое необходимо записать.

Функция clock() – получить время от начала выполнения приложения (его следует поделить на CLOCKS_PER_SEC для получения времени в секундах).

clock_t clock(void);







Дата добавления: 2015-08-31; просмотров: 880. Нарушение авторских прав; Мы поможем в написании вашей работы!



Вычисление основной дактилоскопической формулы Вычислением основной дактоформулы обычно занимается следователь. Для этого все десять пальцев разбиваются на пять пар...

Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

Кардиналистский и ординалистский подходы Кардиналистский (количественный подход) к анализу полезности основан на представлении о возможности измерения различных благ в условных единицах полезности...

Обзор компонентов Multisim Компоненты – это основа любой схемы, это все элементы, из которых она состоит. Multisim оперирует с двумя категориями...

Потенциометрия. Потенциометрическое определение рН растворов Потенциометрия - это электрохимический метод иссле­дования и анализа веществ, основанный на зависимости равновесного электродного потенциала Е от активности (концентрации) определяемого вещества в исследуемом рас­творе...

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

Сущность, виды и функции маркетинга персонала Перснал-маркетинг является новым понятием. В мировой практике маркетинга и управления персоналом он выделился в отдельное направление лишь в начале 90-х гг.XX века...

Признаки классификации безопасности Можно выделить следующие признаки классификации безопасности. 1. По признаку масштабности принято различать следующие относительно самостоятельные геополитические уровни и виды безопасности. 1.1. Международная безопасность (глобальная и...

Прием и регистрация больных Пути госпитализации больных в стационар могут быть различны. В цен­тральное приемное отделение больные могут быть доставлены: 1) машиной скорой медицинской помощи в случае возникновения остро­го или обострения хронического заболевания...

ПУНКЦИЯ И КАТЕТЕРИЗАЦИЯ ПОДКЛЮЧИЧНОЙ ВЕНЫ   Пункцию и катетеризацию подключичной вены обычно производит хирург или анестезиолог, иногда — специально обученный терапевт...

Studopedia.info - Студопедия - 2014-2024 год . (0.012 сек.) русская версия | украинская версия