Обробники переривань

Функція, яку виконує ядро ​​у відповідь на певне переривання, називаєтьсяобробником переривання (interrupt handler)мул іпідпрограмою обслуговування переривання (interrupt service routine) Кожному пристрою, яке генерує переривання, відповідає свій обробник переривання Наприклад, одна функція обробляє переривання від системного таймера, а інша – переривання, згенеровані клавіатурою Обробник переривання для якого-небудь пристрою є частиною драйвера цього пристрою – коду ядра, який управляє пристроєм

В операційній системі Linux обробники переривань – це звичайні функції, написані на мові програмування С Він і повинні відповідати певному прототипу, щоб ядро ​​могло стандартним чином брати інформацію про обробнику, а в іншому-це звичайні функції Єдине, що відрізняє обробники переривань від інших функцій ядра, – це те, що вони викликаються ядром у відповідь на переривання і виконуються в спеціальному контексті, іменованомуконтекстом переривання (Interrupt context), який буде розглянуто далі

Так як переривання може виникнути в будь-який момент часу, то, відповідно, і обробник переривання може бути викликаний в будь-який момент часу Вкрай важливо, щоб обробник переривання виконувався дуже швидко і відновлював управління перерваного коду по можливості швидко Тому, хоча для апаратного забезпечення і важливо, щоб переривання обслуговувалося негайно, для решти системи важливо, щоб обробник переривання виконувався протягом максимально короткого проміжку часу Мінімально можлива робота, яку повинен зробити обробник переривання, – це відправити підтвердження пристрою, що переривання отримано Проте зазвичай обробники переривань повинні виконати більшу кількість роботи Наприклад, розглянемо обробник переривання мережевого пристрою Разом з відправкою підтвердження апаратного забезпечення, обробник переривання повинен скопіювати мережні пакети з апаратного пристрою в память системи, обробити їх, відправити відповідному стеку протоколів або відповідною програмою Очевидно, що для цього потрібно багато роботи

Верхня і нижня половини

Ясно, що два зазначених вимоги про те, що обробник переривання повинен виконуватися швидко і, на додаток до цього, виконувати багато роботи, є суперечливими У звязку з конфліктними вимогами, обробник переривань розбивається на дві частини, або половини Обробник переривання єверхньою половиною (top half) – він виконується відразу після прийому переривання і виконує роботу, критичну до затримок у часі, таку як відправка підтвердження про отримання переривання або скидання апаратного пристрою Робота, яку можна виконати пізніше, відкладається до виконаннянижній (Або основний)половини (bottom half) Нижня половина обробляється пізніше, в більш зручний час, коли всі переривання дозволені Досить часто нижня половина виконується відразу ж після повернення з обробника переривання

Операційна система надає різні механізми для реалізації обробки нижніх половин, які обговорюються в главі 7, Обробка нижніх половин і відкладені дії.

Розглянемо приклад поділу обробника переривання на верхню і нижню половини на основі старої доброї мережевої плати Коли мережевий інтерфейсний адаптер отримує входять з мережі пакети, він повинен повідомити ядро ​​про те, що доступні нові дані Це необхідно зробити негайно, щоб отримати оптимальну пропускну здатність і час затримки при передачі інформації по мережі Тому негайно генерується переривання: Гей, ядро Є свіжі пакети. Ядро відповідає виконанням зареєстрованого обробника переривання від мережевого адаптера

Обробник переривання виконується, апаратного забезпечення направляється підтвердження, пакети копіюються в основну память, і після цього мережевий адаптер готовий до отримання нових пакетів Це завдання є важливою, критичною до часу виконання та специфічної для кожного типу апаратного забезпечення Інша частина обробки мережевих пакетів виконується пізніше – нижньою половиною обробника переривання У цьому розділі ми розглянемо обробку верхніх половин, а в наступній – нижніх

Реєстрація обробника переривання

Відповідальність за обробники переривань лежить на драйверах пристроїв, які управляють певним типом апаратного забезпечення З кожним пристроєм повязаний драйвер, і якщо пристрій використовує переривання (а більшість використовує), то драйвер повинен виконати реєстрацію обробника переривання

Драйвер може зареєструвати обробник переривання для обробки заданої лінії за допомогою наступної функції

/ * Request_irq: виділити задану лінію переривання * /

int request_irq(unsigned int irq,

irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags,

const char * devname,

void *dev_id)

Перший параметр, irq, вказує призначуваний номер переривання Для деяких пристроїв, таких як, наприклад, звичайні пристрої персонального компютера, таймер і клавіатура, це значення, як правило, жорстко закріплено Для більшості інших пристроїв це значення визначається шляхом перевірки (probing) або іншим динамічним способом

Другий параметр, handler, – це покажчик на функцію обробника переривання, яка обслуговує дане переривання Ця функція викликається, коли в операційну систему приходить переривання Слід звернути увагу на специфічний прототип функції-обробника Вона приймає три параметри і повертає значення типу irqreturn_t Нижче в цьому розділі ми більш детально обговоримо цю функцію

Третій параметр, irqflags, може бути рівним нулю або містити бітову маску з одним або декількома наступними прапорами

• SA_INTERRUPT Цей прапор вказує, що даний обробник переривання – це быстрыйобработчикпрерыванияІсторіческітаксложілось, чтоопераціонная система Linux розрізняє швидкі і повільні обробники переривань Передбачається, що швидкі обробники виконуються швидко, але потенційно дуже часто, тому поведінка обробника переривання змінюється, щоб забезпечити максимально можливу швидкість виконання Сьогодні існує тільки одна відмінність: при виконанні швидкого обробника переривань забороняються всі переривання на локальному процесорі Це дозволяє швидкому оброблювачу завершиться швидко, та інші переривання ніяк цьому не покидав За замовчуванням (якщо цей прапор не встановлений) дозволені всі переривання, крім тих, які маскувалися на всіх процесорах і обробники яких в даний момент виконуються Для всіх переривань, крім переривань таймера, немає необхідності встановлювати цей прапор

• SA_SAMPLE_RANDOM Цей прапор вказує, що переривання, згенеровані даним пристроєм, повинні вносити вклад в пул ентропії ядра Пул ентропії ядра забезпечує генерацію істинно випадкових чисел на основі різних випадкових подій Якщо цей прапор зазначений, то моменти часу, коли приходять переривання, будуть введені в пул ентропії Цей прапор не можна встановлювати, якщо пристрій генерує переривання в передбачувані моменти часу (як, наприклад, системний таймер) або на пристрій може вплинути зовнішній зловмисник (як, наприклад, мережевий пристрій) З іншого боку, більшість пристроїв генерують переривання в непередбачувані моменти часу і тому є хорошим джерелом ентропії Для більш докладного опису пулу ентропії ядра см. Додаток Б, Генератор випадкових чисел ядра .

• SA_SHIRQ Цей прапор вказує, що номер переривання може спільно використовуватися декількома обработчиками переривань (shared) Кожен обробник, який реєструється на одну і ту ж лінію переривання, повинен вказувати цей прапор В іншому випадку для кожної лінії може існувати тільки один обробник переривання Більш детальна інформація про спільно використовуваних обробниках переривань приведена в наступному розділі

Четвертий параметр, devname, – це ASCII-рядок, яка описує, який пристрій повязано з перериванням Наприклад, для переривання клавіатури персонального компютера це значення дорівнює keyboard. Текстові імена пристроїв застосовуються для взаємодії з користувачами за допомогою інтерфейсів

/ Proc / ir q та / proc / interrupts, які незабаром будуть розглянуті

Пятий параметр, devid, в основному, застосовується для спільно використовуваних ліній запитів на переривання Коли обробник переривання звільняється (описано нижче), параметр dev_id забезпечує унікальний ідентифікатор (cookie), який дозволяє видаляти тільки необхідний обробник лінії переривання Без цього параметра було б неможливо ядру визначити, який обробник даної лінії переривання слід видалити Якщо лінія запиту на переривання не є спільно використовуваної, то можна в якості цього параметра вказувати NULL, якщо ж номер переривання є спільно використовуваних, то необхідно вказувати унікальний ідентифікатор (cookie) (якщо пристрій не підключений до твані ISA, то, швидше за все, воно підтримує спільно використовувані номери переривань)

Цей параметр також передається обробнику переривання при кожному виклику Звичайна практика – це передача покажчика на структуру пристрою (контекст пристрою), так як цей параметр є унікальним, і, крім того, в обробнику переривання може бути корисним мати покажчик на цю структуру

У разі успіху функція request_ir q () повертає нуль Повернення ненульового значення вказує на те, що сталася помилка і зазначений обробник переривання не була зареєстрована Найбільш часто зустрічається код помилки – це значення-EBUSY, що вказує на те, що дана лінія запиту на переривання вже зайнята (і чи при поточному виклику, або при першому виклику не було зазначено прапор SA_SHIRQ)

Слід звернути увагу, що функція request_ir q () може переходити в стан очікування (sleep) і, відповідно, не може викликатися з контексту переривання, або в інших ситуаціях, коли код не може блокуватися Поширеною помилкою є думка, що функцію request_irq () можна безпечно викликати у випадках, коли не можна переходити в стан очікування Це відбувається почасти від того, що дійсно відразу незрозуміло, чому функція request_irq () повинна чогось очікувати Справа в тому що при реєстрації відбувається додавання інформації про лінії переривання в каталозі / proc / irq Функція proc_mkdir () використовується для створення нових елементів на файлової системі procfs Ця функція викликає функцію proc_creat e () для створення нових елементів файлової системи procfs, яка в свою чергу викликає функцію kmalloc () для виділення памяті Як буде показано в главі 11, Управління памяттю, функція kmalloc () може переходити в стан очікування Ось так от

Для реєстрації лінії переривання та інсталяції обробника в коді драйвера можна використовувати наступний виклик

if (request_irq(irqn, my_interrupt, SA_SHIRQ, &quotmy_device&quot, dev)){

printk(KERN_ERR &quotmy_device: cannot register IRQ %d\n&quot, irqn)

return -EIO

}

У цьому прикладі параметр irq n – це запитаний номер лінії запиту на переривання, параметр my_interrup t – це обробник цієї лінії переривання, лінія запиту на переривання може бути спільно використовуваної, імя пристрою – my_device, dev – значення параметра dev_id У випадку помилки код друкує повідомлення, що сталася помилка, і повертається з виконуваної функції Якщо функція реєстрації повертає нульове значення, то обробник переривання інстальований успішно З цього моменту обробник переривання буде викликатися у відповідь на надходять переривання Важливо призвести ініціалізацію обладнання та реєстрацію обробника переривання в правильній послідовності, щоб запобігти можливості виклику обробника до того моменту, поки устаткування не ініціалізувати

Звільнення обробника переривання

Для звільнення лінії переривання необхідно викликати функцію

void free_irq(unsigned int irq, void *dev_id)

Якщо зазначена лінія не є спільно використовуваної, то ця функція видаляє обробник і забороняє лінію переривання Якщо лінія запиту на переривання є спільно використовуваної, то віддаляється обробник, відповідний параметру dev_id Лінія запиту на переривання також забороняється, коли видаляється останній обробник Тепер зрозуміло, чому важливо передавати унікальне значення параметра dev_id При використанні спільно використовуваних переривань вимагається унікальний ідентифікатор для того, щоб відрізняти один від одного різні обробники, повязані з одним номером переривання, і дозволити функції free_irq () видаляти правильний обробник У кожному разі, якщо параметр devoid НЕ дорівнює значенню NULL, то він повинен відповідати тому оброблювачу, який видаляється

Виклик функції free_irq () повинен проводитися з контексту процесу

Таблиця 61 Список функцій управління реєстрацією переривань

Функція Опис

request_ir q () Зареєструвати заданий обробник переривання для заданої лінії переривання

f ree_ir q () Звільнити вказаний обробник переривання Якщо з лінією переривання більше не повязаний ні один обробник, то заборонити зазначену лінію переривання

Джерело: Лав, Роберт Розробка ядра Linux, 2-е видання : Пер з англ – М: ТОВ «ІД Вільямс »2006 – 448 с : Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*