Читать «Разработка ядра Linux» онлайн - страница 105

Роберт Лав

/*

* прерывания должны быть запрещены!

*/

raise_softirq_irqoff(NET_TX_SOFTIRQ);

Наиболее часто отложенные прерывания генерируются из обработчиков аппаратных прерываний. В этом случае обработчик аппаратного прерывания выполняет всю основную работу, которая касается аппаратного обеспечения, генерирует отложенное прерывание и завершается. После завершения обработки аппаратных прерываний ядро вызывает функцию do_softirq(). Обработчик отложенного прерывания выполняется и подхватывает работу с того места, где обработчик аппаратного прерывания ее отложил. В таком примере раскрывается смысл названий "верхняя половина" и "нижняя половина".

Тасклеты

Тасклеты — это механизм обработки нижних половин, построенный на основе механизма отложенных прерываний. Как уже отмечалось, они не имеют ничего общего с заданиями (task). Тасклеты по своей природе и принципу работы очень похожи на отложенные прерывания. Тем не менее они имеют более простой интерфейс и упрощенные правила блокировок.

Решение о том, стоит ли использовать тасклеты, принять достаточно просто: в большинстве случаев необходимо использовать тасклеты. Как было показано в предыдущем разделе, примеры использования отложенных прерываний можно посчитать на пальцах одной руки. Отложенные прерывания необходимо использовать только в случае, когда необходима очень большая частота выполнений и интенсивно используется многопоточная обработка. Тасклеты используются в очень большом количестве случаев — они работают достаточно хорошо и их очень просто использовать.

Реализация тасклетов

Так как тасклеты реализованы на основе отложенных прерываний, они тоже являются отложенными прерываниями (softirq). Как уже рассказывалось, тасклеты представлены двумя типами отложенных прерываний: 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 в качестве единственного аргумента при вызове.