最近在閱讀linux核心原始碼,把自己的一些理解發上來,一方面看到的朋友可以幫我指正我理解偏差的地方,別一方面也算是做乙個簡單的總結。
首先呼叫open_softirq()函式來初始化軟體中斷處理函式,將軟體中斷處理函式根據軟中斷的下標號插入到softirq_vec陣列中,實現過程很簡單如下:
1234
voidopen_softirq(
int nr,
void(*
action)
(struct
softirq_action *))
softirq_vec資料有32個元素,對應的是可以有32個軟體中斷,但實際上linux只是使用了其中的6個軟中斷,相應的每乙個cpu都會 有乙個對應的32位的掩碼__softirq_pending描述掛起的軟中斷,每一位對應乙個軟體中斷,__soctirq_penging在 irq_cpustat_t中定義,如下:
@include/asm/hardirq.h
123456
typedefstruct
____cacheline_aligned irq_cpustat_t;
其中local_softirq_pending()巨集用於選擇當前cpu所對應的__softirq_penging掩碼。相關的巨集如下:
@include/linux/irq_cpustat.h
1234
#define local_softirq_pending() /__irq_stat(smp_processor_id() , __softirq_pending)
#define __irq_stat(cpu , member) (irq_stat[cpu].member)
接著呼叫raise_softirq()函式來啟用軟中斷,函式如下:
@kernel/softirq.c
1234567
89
voidraise_softirq(
unsigned
int nr)
raise_softirq_irqoff()函式必須是在禁止中斷的情況下執行的,它首先呼叫__raise_softirq_irqoff() 巨集啟用軟體中斷,其實也就是設定當前cpu所對應的__softirq_pending所對應的軟中斷的位,以表示該軟中斷已啟用。如果當前正處於中斷或 者軟中斷當中,那麼raise_softirq_irqoff執行結束,否則的話就呼叫wakeup_softirqd()函式啟用 ksoftirqd/n核心執行緒來處理軟中斷。
@kernel/softirq.c
1234567
inlinevoid
raise_softirq_irqoff(
unsigned
int nr)
__rarse_softirq_irqoff()巨集在/include/linux/interput.h中定義:
1234
#defome __raise_softirq_irqoff(nr) /do while(0)
#define or_softirq_pending(x) (local_softirq_pending() |= (x))
其中local_softirq_pending()巨集已經在上面列出來了,我不太明白的是__raise_softirq_irqoff()這個巨集為什麼要放到乙個迴圈裡面,它也只是執行了一次,不過linux既然這樣寫就一定有它的道理,慢慢再去研究吧。
這樣軟中斷已經啟用,其處理函式已經加入到了softirq_sec陣列中,並且相應的標誌位已經合適地設定,系統會周期性地檢查已經掛起的軟中斷,當在 local_softirq_pending()中的某個位檢測到掛起的軟中斷的時候,就會呼叫do_softirq()函式對軟中斷進行處理。
do_softirq()函式定義如下:
@ kernel/softirq.h
1234567
891011
1213
1415
1617
asmlinkage voiddo_softirq(
void
)
如果在中斷上下文中呼叫了do_softirq函式或者禁用了軟體中斷,那麼in_interrupt函式返回1,這時候do_softirq() 不做任何事情,否則,它會把eflags暫存器if標誌儲存在flags中並禁用中斷,然後將local_softirq_pending()的值儲存在 pending變數中,檢測pending的值,如果pending不為0,則表示pending的某一位被設定,當前cpu就有對應的掛起的軟中斷需要 進行處理,呼叫__do_softirq()對掛起的軟中斷進行處理,處理完成之後再根據flags變數的值恢復eflags暫存器並開啟中斷。
接下來看__do_softirq()函式:
1234567
891011
1213
1415
1617
1819
2021
2223
2425
2627
2829
3031
3233
3435
3637
3839
4041
4243
4445
4647
4849
5051
asmlinkage void__do_softirq(
void)}
h++;
pending >>=1;
}while
(pending)
;/* 禁用本地軟中斷 */
local_irq_disable();
pending =
local_softirq_pending();
if(pending &&
--max_restart)
goto
restart;if(
pending)
wakeup_softirqd();
_local_bh_enable();
}
核心迴圈地檢測每乙個pending的位,以處理當前位掛機的軟體中斷,為了防止核心在執行__do_softirq()的過程中不停地有新的 softirq產生,以導致核心無暇顧及其它,__do_softirq()在迴圈檢測的時候設定了外層迴圈的最大次數為10次,對pending的每一 位檢測10次之後如果pending的值仍不為0,則表示當前cpu仍有未處理的掛起的軟體中斷,這時候__do_softirq不再對它進行處理,而是 喚醒核心執行緒ksoftirqd/n對它進行處理。
在函式開始的時候,先將軟體中斷的點陣圖__softirq_pending儲存在pending區域性變數中,然後呼叫set_softirq_pending(0)以清空軟中斷位圖,從而允許新的軟中斷的到來。接著呼叫local_irq_enable()來啟用軟中斷。
Linux 核心中斷體系 初探
還是要先理解整個中斷的體系,首先要理解對中斷的含義 如果這是涉及到的軟體的除錯的話,沒有接觸過硬體的同學會對,gdb的除錯中的中斷有一定的認知 但是,這兩個中斷指的意思是不相同的,gdb的除錯中的中斷 指的是程式執行到某個節點的的時候就跳出程式,這個 節點指的是提前設定好的中斷點,而這個linux ...
常用核心中斷符號解釋 linux
在列舉型別irqreturn定義在include linux irqreturn.h檔案中。unsigned long flags 中斷處理的屬性,與中斷管理有關的位掩碼選項,有一下幾組值 define irqf disabled 0x00000020 中斷禁止 define irqf sample...
Linux1 0核心中斷體系的建立
head.s中設定了idt的指標,共256項,都指向ignore int函式 ignore int cldpushl eax pushl ecx pushl edx push dspush espush fs movl kernel ds eax mov ax,ds mov ax,es mov ax...