參考資訊:
http://jimmychenhaha.blogspot.com/2016/09/softirq.html
https://www.cnblogs.com/wang_yb/archive/2013/04/23/3037268.html
Linux Kernel將中斷處理切成top-half和bottom-half兩部份,top-half指的就是中斷副程式本身,而bottom-half指的就是延遲處理的副程式,如果中斷要處理的事情不需太耗時,就直接在中斷副程式裡處理就可以,如果無法立即完成(如:需要等待或者傳遞大量資料),則可以安排一個延遲處理的副程式,softirq就是一種延遲處理的機制,雖然是延遲處理,不過,softirq也是執行在比較高優先級別的等級,因此,不適合處理太過耗時的事情,但是適用於快速處理的場景,因為,高優先級別的副程式,如果太耗時,將延後Context Switch的發生(單核心來說),導致系統效能出問題,softirq本身是可重複進入的(reentrant),因此,在撰寫softirq程式時,必須要考慮到這個問題,不過有了bottom-half機制,確實可以有效解決中斷阻塞問題
使用步驟:
1. open_softirq() 2. raise_softirq() 3. raise_softirq_irqoff()
由於softirq需要修改Kernel,因此,請先修改檔案(kernel/softirq.c)
const char * const softirq_to_name[NR_SOFTIRQS] = { "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL", "TASKLET", "SCHED", "HRTIMER", "RCU", "PocketBeagle" }; EXPORT_SYMBOL(open_softirq); EXPORT_SYMBOL(raise_softirq_irqoff); EXPORT_SYMBOL(raise_softirq);
include/linux/interrupt.h
enum { HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, IRQ_POLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, /* Unused, but kept as tools rely on the numbering. Sigh! */ RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ POCKETBEAGLE_SOFTIRQ, NR_SOFTIRQS };
P.S. 接著重新編譯Kernel並且更新zImage
ldd.S
.global init_module .global cleanup_module .equ BUTTON, 27 .equ IRQF_TRIGGER_RISING, 1 .equ POCKETBEAGLE_SOFTIRQ, 10 .section .modinfo, "ae" __UNIQUE_ID_0: .asciz "license=GPL" __UNIQUE_ID_1: .asciz "author=Steward Fu" __UNIQUE_ID_2: .asciz "description=Linux Driver" .section .data btn_irq: .dcb 4 irq_name: .asciz "gpio_irq" softirq_msg: .asciz "softirq_handler\n" .align 2 .section .text softirq_handler: push {lr} ldr r0, =softirq_msg bl printk pop {pc} irq_handler: push {lr} mov r0, #POCKETBEAGLE_SOFTIRQ bl raise_softirq mov r0, #1 pop {pc} init_module: push {r4, r5, lr} mov r0, #BUTTON bl gpio_to_desc bl gpiod_to_irq ldr r1, =btn_irq str r0, [r1] ldr r1, =irq_handler mov r2, #0 mov r3, #IRQF_TRIGGER_RISING ldr r4, =irq_name mov r5, #0 push {r4, r5} bl request_threaded_irq pop {r4, r5} mov r0, #POCKETBEAGLE_SOFTIRQ ldr r1, =softirq_handler bl open_softirq mov r0, #0 pop {r4, r5, pc} cleanup_module: push {lr} ldr r0, =btn_irq ldr r0, [r0] mov r1, #0 bl free_irq mov r0, #POCKETBEAGLE_SOFTIRQ bl raise_softirq_irqoff pop {pc} .end
ldd_init: 設定GPIO中斷以及softirq延遲處理副程式
irq_handler: 安排一個softirq延遲處理
softirq_handler: 列印字串
ldd_exit: 釋放中斷資源以及關閉softirq
完成
# softirq_handler