將可延遲的處理從硬中斷處理程序中分離,使其在開啟中斷狀態下執行,即為軟中斷。這大幅縮短硬中斷響應時間,對即時應用至關重要。本文基於 Linux Kernel 4.0 深入剖析軟中斷流程細節。
目前有 10 種軟中斷(由 NR_SOFTIRQS 定義),透過 softirq_vec[NR_SOFTIRQS] 陣列管理,全 CPU 共用。
使用 open_softirq() 將處理函數與編號綁定。網路子系統註冊收發封包處理函數:
open_softirq(NET_TX_SOFTIRQ, net_tx_action); open_softirq(NET_RX_SOFTIRQ, net_rx_action);
每個 CPU 擁有 32-bit 位圖 __softirq_pending 維護本 CPU 的軟中斷啟用狀態:
typedef struct {
unsigned int __softirq_pending;
#ifdef CONFIG_SMP
unsigned int ipi_irqs[NR_IPI];
#endif
} ____cacheline_aligned irq_cpustat_t;
irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
在 irq_exit 中可能啟用軟中斷,條件為:
if (!in_interrupt() && local_softirq_pending())
invoke_softirq();
條件含義:不在硬中斷中、不在軟中斷中、本 CPU 位圖有置位。體現硬中斷優先、軟中斷不嵌套原則。invoke_softirq 會喚醒 ksoftirqd 執行緒處理,或直接呼叫 __do_softirq 即時處理(區分當前堆疊或獨立軟中斷堆疊)。即時處理期間禁止搶佔。
網卡從非 NAPI 演進到 NAPI,展現軟中斷優勢:將收封包任務最大程度移至軟中斷,極大簡化硬中斷。raise_softirq 呼叫 __raise_softirq_irqoff 在指定 CPU 位圖置位。置位操作需在關中斷下完成以避免競爭。
每個 CPU 有一個 ksoftirqd 執行緒專門處理大量軟中斷:
DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
核心函數 run_ksoftirqd 循環:關中斷檢查位圖、有則執行 __do_softirq、開中斷。執行前可被搶佔,執行後不可搶佔,與硬中斷處理哲學一致:執行期間不允許排程。
執行 do_softirq 前關搶佔,確保軟中斷執行期間不被排程。
if (unlikely(!in_interrupt() && local_softirq_pending()))
do_softirq();
異常處理與軟中斷共享資料時,進入臨界區關軟中斷,離開時開啟,此即為一個啟用時機。
「啟用」而非「呼叫」:外圍僅修改本 CPU 位圖,最終由核心機制(ksoftirqd、通過 in_interrupt 檢查的處理)真正處理。原則:誰啟用誰處理,哪個 CPU 的硬中斷帶來的軟中斷由哪個 CPU 處理,充分發揮 SMP 優勢。多 CPU 平行處理同類型軟中斷時,需自行保護共享資料結構(可重入代價)。
檢查重入條件(不在硬/軟中斷中),符合則處理:
pending = local_softirq_pending(); if (pending) __do_softirq();
在關中斷保護下完成。局部變數 pending 未傳入 __do_softirq,僅判斷非使用,判斷值與實際使用值可能有差異。此檢查達到:同 CPU 軟中斷不嵌套、嵌套硬中斷中不處理軟中斷。同 CPU 上 __do_softirq 序列化,多 CPU 間平行,故同類型軟中斷仍需保護共享資料。
三階段分析:
MAX_SOFTIRQ_RESTART),因使用使用者進程堆疊不可久佔。退出條件:總時間超限、被搶佔(開中斷後)、達 10 次。若 10 次循環仍未清空位圖(期間大量硬中斷帶來新軟中斷),交給 ksoftirqd 處理。循環意義:處理期間可能進入新硬中斷帶來新軟中斷(僅在本 CPU 位圖置位),需反覆處理直到位圖清空。
防嵌套流程:關軟中斷包含原子性加 1。若路徑 A 在原子操作前被 B 打斷,B 處理完硬/軟中斷返回 A,A 接著執行原子操作,後續軟中斷處理空轉(已被 B 處理)。若在原子操作後被打斷,B 執行硬中斷但不執行軟中斷(嵌套檢查失敗),返回 A,A 額外處理 B 的軟中斷。
preempt_count 中的軟中斷位雙重作用:防單 CPU 嵌套、保證執行期間不被搶佔。
中斷時序雖複雜,皆逃不出兩原則:硬中斷可打斷硬中斷(不同類型);硬中斷可打斷軟中斷(軟中斷不打斷硬中斷,亦不打斷軟中斷)。所有複雜時序皆為這兩者疊加。