Кто делает Напи планирование
У меня были сомнения при чтении планирования NAPI в драйверах сети.
Как правило, весь код сетевой обработки выполняется в контексте softirq. А с механизмом опроса NAPI драйвер будет опрашивать пакеты после получения прерывания.
Итак, если код NAPI также выполняется в контексте softirq, как можно запланировать его. (Поскольку контекстный код прерывания не может быть запланирован).
И что такое использование рабочих очередей в сетевых драйверах.
1 ответ
Планирование в смысле NAPI просто означает пометку его как нужного для запуска. Другими словами, вы просто вызываете функцию, говоря "запланируйте мне запускаться в NAPI softirq". Это приводит к тому, что функция опроса вашего драйвера добавляется в список "нужных для опроса" устройств, а также вызывает активацию NAPI softirq "на выходе".
Так что обычно это работает так. Ваш драйвер настраивает ваше устройство так, чтобы оно прерывало работу в какой-то момент в будущем, когда некоторые пакеты (в идеале более одного, чтобы амортизировать накладные расходы) готовы к обработке. А пока ядро планирует обычные процессы в пользовательском пространстве...
Когда ваше устройство прерывает:
- прерывание вызывает переход в режим ядра, если он еще не находится в режиме ядра
- код обработки прерываний linux находит подпрограмму обработки прерываний вашего драйвера и вызывает ее.
- Ваш обработчик прерываний звонит
napi_schedule
(поместив свою функцию опроса в список и запустив программу Softirq. - Ваш обработчик прерываний возвращается.
- Непосредственно перед возвратом в пользовательский режим (или что бы процессор ни делал до прерывания), код обработки прерываний видит, что сетевой софттирк должен работать, и активирует его.
- Softirq вызывает функцию опроса для обработки входящих пакетов до тех пор, пока у вас не останется больше пакетов или пока не будет исчерпан "бюджет" NAPI. (В последнем случае, softirq позже повторно вызывается
ksoftirqd
нить [думаю].) - После этого ваш драйвер снова включит прерывания на вашем устройстве, если он завершит обработку всех готовых к обработке пакетов.
По моему опыту, рабочие очереди обычно используются только для определенных длительных операций, которые должны выполняться в планируемом контексте (т. Е. В реальном контексте задачи, который может блокировать [sleep] в ожидании завершения чего-либо).
Например, в драйвере intel ixgbe, если драйвер обнаруживает необходимость сброса сетевого адаптера, запускается запись рабочей очереди для повторной инициализации сетевого адаптера. Некоторые операции требуют относительно длительного сна, и вы не хотите связывать процессор в более мягком контексте, если вы можете позволить выполнить какое-то другое задание. Также могут быть и другие причины - например, вам нужно выделить большие объемы памяти, что может потребовать выполнения вызова выделения в контексте задачи.