Читать «Разработка ядра Linux» онлайн - страница 105
Роберт Лав
/*
* прерывания должны быть запрещены!
*/
raise_softirq_irqoff(NET_TX_SOFTIRQ);
Наиболее часто отложенные прерывания генерируются из обработчиков аппаратных прерываний. В этом случае обработчик аппаратного прерывания выполняет всю основную работу, которая касается аппаратного обеспечения, генерирует отложенное прерывание и завершается. После завершения обработки аппаратных прерываний ядро вызывает функцию do_softirq()
. Обработчик отложенного прерывания выполняется и подхватывает работу с того места, где обработчик аппаратного прерывания ее отложил. В таком примере раскрывается смысл названий "верхняя половина" и "нижняя половина".
Тасклеты
Тасклеты — это механизм обработки нижних половин, построенный на основе механизма отложенных прерываний. Как уже отмечалось, они не имеют ничего общего с заданиями (task). Тасклеты по своей природе и принципу работы очень похожи на отложенные прерывания. Тем не менее они имеют более простой интерфейс и упрощенные правила блокировок.
Решение о том, стоит ли использовать тасклеты, принять достаточно просто: в большинстве случаев необходимо использовать тасклеты. Как было показано в предыдущем разделе, примеры использования отложенных прерываний можно посчитать на пальцах одной руки. Отложенные прерывания необходимо использовать только в случае, когда необходима очень большая частота выполнений и интенсивно используется многопоточная обработка. Тасклеты используются в очень большом количестве случаев — они работают достаточно хорошо и их очень просто использовать.
Реализация тасклетов
Так как тасклеты реализованы на основе отложенных прерываний, они тоже являются HI_SOFTIRQ
и TASKLET_SOFTIRQ
. Единственная разница между ними в том, что тасклеты типа HI_SOFTIRQ
выполняются всегда раньше тасклетов типа TASKLET_SOFTIRQ
.
Структуры тасклетов
Тасклеты представлены с помощью структуры tasklet_struct
. Каждый экземпляр структуры представляет собой уникальный тасклет. Эта структура определена в заголовочном файле <linux/interrupt.h>
в следующем виде.
struct tasklet_struct {
struct tasklet_struct *next; /* указатель на следующий
тасклет в списке */
unsigned long state; /* состояние тасклета */
atomic_t count; /* счетчик ссылок */
void (*func)(unsigned long); /* функция-обработчик тасклета */
unsigned long data; /* аргумент функции-обработчика тасклета */
);
Поле func
— это функция-обработчик тасклета (эквивалент поля action
для структуры, представляющей отложенное прерывание), которая получает поле data
в качестве единственного аргумента при вызове.