Механизм обработчиков | Состояние |
---|---|
BH | Изъято в серии 2.5 |
Очереди заданий | Изъято в серии 2.5 |
Отложенные прерывания | Доступно начиная с серии 2.3 |
Тасклеты | Доступно начиная с серии 2.3 |
Очереди отложенных действий | Доступно начиная с серии 2.3 |
Давайте продолжим рассмотрение каждого из механизмов в отдельности, пользуясь этой устойчивой путаницей в названиях.
Механизм отложенных прерываний (softirq)
Обсуждение существующих методов обработки нижних половин начнем с механизма softirq. Обработчики на основе механизма отложенных прерываний используются редко. Тасклеты — это более часто используемая форма обработчика нижних половин. Поскольку тасклеты построены на основе механизма softirq, с механизма softirq и стоит начать. Код, который касается обработчиков отложенных прерываний, описан в файле kernel/softirq.c
.
Реализация отложенных прерываний
Отложенные прерывания определяются статически во время компиляции. В отличие от тасклетов, нельзя динамически создать или освободить отложенное прерывание. Отложенные прерывания представлены с помощью структур softirq_action
, определенных в файле
в следующем виде.
/*
* структура, представляющая одно отложенное прерывание
*/
struct softirq_action {
void (*action)(struct softirq_action*);
/* функция, которая должна выполниться */
void *data; /* данные для передачи в функцию */
};
Массив из 32 экземпляров этой структуры определен в файле kernel/softirq.с
в следующем виде.
static struct softirq_action softirq_vec[32];
Каждое зарегистрированное отложенное прерывание соответствует одному элементу этого массива. Следовательно, имеется возможность создать 32 обработчика softirq. Заметим, что это количество фиксировано. Максимальное число обработчиков softirq не может быть динамически изменено. В текущей версии ядра из 32 элементов используется только шесть[37].
Прототип обработчика отложенного прерывания, поля action
, выглядит следующим образом.
void softirq_handler(struct softirg_action*);
Когда ядро выполняет обработчик отложенного прерывания, то функция action
вызывается С указателем на соответствующую структуру softirq_action
в качестве аргумента. Например, если переменная my_softirq
содержит указатель на элемент массива softirq_vec
, то ядро вызовет функцию-обработчик соответствующего отложенного прерывания в следующем виде.
my_softirq->action(my_softirq);
Может быть, несколько удивляет, что ядро передает в обработчик указатель на всю структуру, а не только на поле data. Этот прием позволяет в будущем вводить дополнительные поля в структуру без необходимости внесения изменений в существующие обработчики. Обработчик может получить доступ к значению ноля data
простым разыменованием указателя на структуру и чтением ее поля data
.
Обработчик одного отложенного прерывания никогда не вытесняет другой обработчик softirq. Б действительности, единственное событие, которое может вытеснить обработчик softirq, — это аппаратное прерывание. Однако на другом процессоре одновременно с обработчиком отложенного прерывания может выполняться другой (и даже этот же) обработчик отложенного прерывания.
Зарегистрированное отложенное прерывание должно быть отмечено для того, чтобы его можно было выполнить. Это называется
• После обработки аппаратного прерывания.
• В контексте потока пространства ядра ksoftirqd
.
• В любом коде ядра, который явно проверяет и выполняет ожидающие обработчики отложенных прерываний, как, например, это делает сетевая подсистема.
Независимо от того, каким способом выполняется отложенное прерывание, его выполнение осуществляется в функции do_softirq
. Эта функция по-настоящему проста. Если есть ожидающие отложенные прерывания, то функция do_softirq
в цикле проверяет их все и вызывает ожидающие обработчики. Давайте рассмотрим упрощенный вариант наиболее важной части функции do_softirq
.
u32 pending = softirq_pending(cpu);