參考資訊:
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