Блокування між обработчиками нижніх половин

Ми ще не стосувалися питань, повязаних з блокуваннями Цій темі присвячені наступні дві глави Проте дуже важливо розуміти, що вирішальним моментом при обробці нижніх половин є захист даних загального доступу від конкурентних змін, навіть на однопроцессорной машині Слід памятати, що обробник нижньої половини переривання потенційно може виконуватися в будь-який момент часу Може знадобитися повернутися до поточного розділу, після прочитання наступних двох глав, якщо ви далекі від питань, повязаних з блокуваннями

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

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

Якщо з контексту процесу необхідно звертатися до даних, які використовуються як контекстом процесу, так і обробником нижньої половини, то необхідно заборонити обробку нижніх половин і захопити блокування перед тим, як починати роботу з даними Це дозволяє гарантувати захист спільно використовуваних даних як на локальному процесорі, так і на різних процесорах SMP системи, а також запобігти взаимоблокировки

Якщо є дані, які можуть спільно використовуватися в контексті переривання і в обробнику нижньої половини, то необхідно заборонити переривання і захопити блокування перед тим, як звертатися до цих даних Саме ці дві операції дозволяють запобігти взаємоблокування і забезпечити захист для SMP-систем

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

У главі 8 будуть розглянуті хитрості, повязані з блокуваннями У главі 9 будуть описані базові елементи ядра, які дозволяють здійснювати блокування

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

Запрещениеобработкинижнихполовин

Зазвичай тільки одного заборони обробки нижніх половин недостатньо Найбільш часто, щоб повністю захистити спільно використовувані дані, необхідно захопити блокування і заборонити обробку нижніх половин Методи, які дозволяють це зробити і які зазвичай використовуються при розробці драйверів, будуть розглянуті в розділі 9 Однак при розробці самого коду ядра іноді необхідно заборонити тільки обробку нижніх половин

Для того щоб заборонити обробку всіх типів нижніх половин (усіх відкладених переривань і, відповідно, тасклетов), необхідно викликати функцію local_bh_disabl e () Для дозволу обробки нижніх половин необхідно викликати функцію local_bh_enabl e () Так, у цих функцій неправильні назви Ніхто не потрудився перейменувати ці функції, коли інтерфейс ВН поступився місце інтерфейсу відкладених переривань У табл 74 наведені відомості про ці функції

Таблиця 74 Список функцій управління обробкою нижніх половин

Функція Опис

voi d local_bh_disabl e () Заборонити обробку всіх відкладених переривань (softirq)

і тасклетов (tasklet) на локальному процесорі

voi d local_bh_enable () Дозволити обробку всіх відкладених переривань (softirq)

і тасклетов (tasklet) на локальному процесорі

Виклики цих функцій можуть бути вкладеними – при цьому тільки останній виклик функції local_bh_enable () дозволяє обробку нижніх половин Наприклад, при першому виклику функції local_bh_disabl e () забороняється виконання відкладених переривань на поточному процесорі Якщо функція local_bh_disabl e () викликається ще три рази, то виконання відкладених переривань буде заборонено Їх виконання НЕ буде дозволено доти, поки функція local_bh_enabl e () нічого очікувати викликана чотири рази

Така функціональність реалізована за допомогою лічильника preerapt_count, який підтримується для кожного завдання (цікаво, що цей же лічильник використовується і для витіснення процесів в режимі ядра) 11 Коли значення цього лічильника досягає нуля, то можна почати обробку нижніх половин Так як при виклику функції local_bh_enabl e () обробка нижніх половин заборонена, то ця функція також перевіряє наявність очікують на обробку нижніх половин і виконує їх

1 січня Насправді це т лічил до використовується як системо ї обробки і переривань, так і системо ї обробки нижніх половин Наличи е одного лічильника для завдання дозволяє в операційно ї системі Linux реалізоіать атомарний ь завдань Ка до показала практика, тако й підхід очен ь корисний н для знаходження помилок, наприклад, повязаних з тим, що завдання переходь т в состояни е очікування в той час, коли виконує атомарні операци і (sleeping-while-atomic bug)

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

. Для цікавих нижче наведені відповідні реалізації на мові програмування С

/*

* Заборона обробки нижніх половин шляхом збільшення значення лічильника preempt_count

*/

void local_bh_disable(void)

{

struct thread_info *t = current_thread_info()

t-&gtpreempt_count += SOFTIRQ_OFFSET

}

/*

* Зменшення значення лічильника preempt_count автоматично дозволяє

* Обробку нижніх половин, якщо значення лічильника дорівнює нулю

*

* Опціонально запускає всі обробники нижніх половин, які очікують на обробку

*/

void local_bh_enable(void)

{

struct thread_info *t = current_thread_info()

t-&gtpreempt_count -= SOFTIRQ_OFFSET

/*

* Одно значення змінної preempt_count нулю і чи очікують на обробку будь обробники нижніх половин

* Якщо так, то запустити їх

/

if (unlikely(t-&gtpreempt_count &amp&amp

softirq_pending (smp_processor_id())))

do_softirq()

}

Ці функції не забороняють виконання черг дій Так як черги дій виконуються в контексті процесу, немає ніяких проблем з асинхронним виконанням і немає необхідності забороняти їх Оскільки відкладені переривання і тасклети можуть виникати асинхронно (наприклад, при поверненні з обробника апаратного переривання), то ядру може знадобитися забороняти їх У разі використання черг відкладених дій захист спільно використовуваних даних здійснюється так само, як і при роботі в контексті процесу Деталі розглянуті в главах 8 і 9

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

*

*