Механізм відкладених переривань (softirq) – ЧАСТИНА 1

Обговорення існуючих методів обробки нижніх половин почнемо з механізму softirq Оброблювачі на основі механізму відкладених переривань використовуються рідко Тасклети – це більш часто використовувана форма обробника нижніх половин Оскільки тасклети побудовані на основі механізму softirq, з механізму softirq і варто почати Код, який стосується обробників відкладених переривань, описаний у файлі kernel / softirqс

Реалізація відкладених переривань

Відкладені переривання визначаються статично під час компіляції На відміну від тасклетов, не можна динамічно створити або звільнити відкладене переривання Відкладені переривання представлені за допомогою структур softirq_action, визначених у файлі в наступному вигляді

/*

* Структура, що представляє одна відкладена переривання

*/

struct softirq_action

{

void (*action)(struct softirq_action *)

/ * Функція, яка повинна виконатися * /

void * data / * Дані для передачі у функцію * /

}

Масив з 32 екземплярів цієї структури визначений у файлі kernel / so f tirq с в наступному вигляді

static struct softirq_action softirq_vec[32]

Кожна зареєстрована відкладене переривання відповідає одному елементу цього масиву Отже, є можливість створити 32 обробника softirq Зауважимо, що ця кількість фіксовано Максимальне число обробників softirq не може бути динамічно змінено У поточній версії ядра з 32 елементів використовується тільки шесть4

Оброблювач softirq

Прототип обробника відкладеного переривання, поля action, виглядає наступним чином

void softirq_handler(struct softirg_action *)

Коли ядро ​​виконує обробник відкладеного переривання, то функція actio n викликається З покажчиком на відповідну структуру softirq_actio n як аргумент Наприклад, якщо змінна rny_softirq містить покажчик на елемент масиву softirq_vec, то ядро ​​викличе функцію-обробник відповідного відкладеного переривання в наступному вигляді

my_softirq-&gtaction(my_softirq)

Може бути, трохи дивує, що ядро ​​передає в обробник покажчик на всю структуру, а не тільки на полі data Цей прийом дозволяє в майбутньому вводити додаткові поля в структуру без необхідності внесення змін в існуючі обробники Оброблювач може отримати доступ до значення нуля dat a простим разименованія покажчика на структуру і читанням її поля data

Оброблювач одного відкладеного переривання ніколи не витісняє інший обробник softirq Б Насправді, єдине подія, яка може витіснити обробник softirq, – це апаратне переривання Однак на іншому процесорі одночасноз обробником відкладеного переривання може виконуватися інший (і навіть цей же) обробник відкладеного переривання

Виконання відкладених переривань

Зареєстроване відкладене переривання повинно бути зазначено для того, чтобыегоможнобыловыполнитьЭтоназываетсягенерациейотложенногопрерывания (rise softirq) Зазвичай обробник апаратного переривання перед поверненням відзначає свої обробники відкладених переривань Потім у відповідний момент часу відкладене переривання виконується Очікують виконання обробники відкладених переривань перевіряються і виконуються в наступних ситуаціях

4 Більшість про драйвери в використовує для обробки і своїх ніжні х полови н механізм тасклетов, Тасклети побудований и на механізмі softirq, як це буде покапать нижче

• Після обробки апаратного переривання

• У контексті потоку простору ядра ksoftirqd

• У будь-якому коді ядра, який явно перевіряє і виконує очікують обробники відкладених переривань, як, наприклад, це робить мережева підсистема

Незалежно від того, яким способом виконується відкладене переривання, його виконання здійснюється у функції do_softir q () Ця функція по-справжньому проста Якщо є які очікують відкладені переривання, то функція do_softirq () у циклі перевіряє їх все і викликає очікують обробники Давайте розглянемо спрощений варіант найбільш важливої ​​частини функції do_sof tir q ()

u32 pending = softirq_pending(cpu)

if (pending) {

struct softirq_action *h = softirq_vec

softirq_pending(cpu) = 0

do {

if (pending &amp 1) h-&gtaction (h) h++

pending »= 1

} while (pending)

}

Цей фрагмент коду є серцем обробника відкладених переривань Він перевіряє і виконує всі очікують відкладені переривання

• Привласнює локальної змінної pending значення, що повертається макро сом softirq_pendin g () Це значення – 32-х розрядна бітова маска очікують на виконання відкладених переривань Якщо встановлений біт з номером n, то відкладене переривання з цим номером очікує на виконання

• Коли значення бітової маски відкладених переривань збережено, оригиналь ная бітова маска очіщается5

• Перемінної h присвоюється вказівник на перший елемент масиву softirq_vec

• Якщо перший біт маски, яка зберігається в змінної pending, встановлений, то викликається функція h-> action (h)

• Покажчик h збільшується на одиницю, і тепер він вказує на другий елемент масиву softirq_vec

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

5 Насправді ця операци я виполняетс я при всіх заборонені х на локальному процесор е переривання, що не показане в спрощено й версії Якби переривання я не були заборонені , То в період часів і між збереженням та очищення й маски могло б бути згенерований про нове відкладений е переривання е (которо е б чекало на виконання), що привів про б до невірно ї очищенн е біта відповідного відкладеного переривання

• Покажчик h тепер вказує на другий елемент масиву, а в бітовій масці – другий біт став першим Тепер необхідно повторити всі раніше пророблені кроки

• Послідовне повторення проводиться доти, поки бітова маска не стане рівною нулю У цей момент більше немає очікують відкладених переривань, і наша робота виконана Зауважимо, що такий перевірки достатньо для того, щоб гарантувати, що покажчик h завжди вказує на законну запис в масиві softirq_vec, так як бітова маска pending має 32 біт і цикл не може виконатися більше 32 разів

Использованиеотложенныхпрерываний

Відкладені переривання зарезервовані для найбільш важливих і критичних до часу виконання обробників нижніх половин в системі Зараз тільки дві підсистеми – підсистема SCSI і мережева підсистема – Безпосередньо використовують механізм softirq На додаток до цього, таймери ядра і тасклети побудовані на базі відкладених переривань Якщо є бажання додати нове відкладене переривання, то варто себе запитати, чому буде недостатньо використання тасклетов Тасклети можуть створюватися динамічно, а також їх легше використовувати в звязку з більш простими вимогами до блокувань Крім того, їх продуктивність все ще залишається дуже гарною Проте для завдань, критичних до часу виконання, які здатні самі забезпечувати ефективні блокування, використання механізму softirq – Буде правильним рішенням

Призначення індексів

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

Створення нового відкладеного переривання полягає в додаванні нового запису в цей перелік (enum) Однак потрібно не просто додати нову сходинку в кінець списку, як в інших місцях Замість цього потрібно вставити рядок у відповідності з пріоритетом, який дається цьому перериванню Історично, HI_SOFTIRQ-має найбільший пріоритет, a TASKLET_SOFTIRQ – найменший Новий запис, швидше за все, повинна бути десь нижче записів для мережевих пристроїв і вище записи для TASKLET_SOFTIRQ У табл 72 показаний список всіх типів відкладених переривань

Таблиця 72 Список відкладених переривань

Відкладене переривання

HI_SOFTIR Q

TIMER_SOFTIRQ

Пріоритет

1

Опис

Високопріоритетні тасклети

Оброблювач нижніх половин таймерів

NET_TX_S0FTIR Q

2

Відправка мережевих пакетів

NET_RX_SOFTIRQ

3

Прийом мережевих пакетів

SCSI_SOFTIR Q

4

Оброблювач нижніх половин підсистеми SCSI

TASKLET_SOFTIRQ

5

Тасклети

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

Далі під час виконання повинен бути зареєстрований обробник відкладеного переривання за допомогою виклику open_softirq (), який приймає три параметри: індекс відкладеного переривання, функція-обробник і значення поля data Для мережевої підсистеми це робиться, наприклад, наступним чином

open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL)

open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL)

Оброблювач відкладеного переривання виконується при дозволених переривання і не може переходити в стан очікування (sleep) Під час виконання обробника відкладені переривання на даному процесорі забороняються Однак на іншому процесорі обробники відкладених переривань можуть виконуватися Насправді, якщо раптом генерується відкладене переривання в той момент, коли виконується його обробник, то такий же обробник може бути запущений на іншому процесорі одночасно з першим обробником Це означає, що будь-які спільно використовувані дані, які використовуються в обробнику відкладеного переривання, і навіть глобальні дані, які використовуються тільки в самому обробнику, повинні відповідним чином блокуватися (як показано в наступних двох розділах) Це дуже важливий момент, і саме з цієї причини використання тасклетов зазвичай переважніше Просте запобігання конкурентному виконання обробників – це далеко не ідеал Якщо обробник відкладеного переривання просто захопить блокування, яка запобігає його виконання паралельно самому собі, то для використання відкладених прерипаній не залишається майже ніякого сенсу Отже, більшість обробників відкладених переривань використовують дані, унікальні для кожного процесора (і отже, не потребують блокувань), або які-небудь інші хитрощі, щоб уникнути явного використання блокувань і забезпечити відмінну масштабованість

Джерело: Лав, Роберт Розробка ядра 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>

*

*