Linux核心原始碼閱讀之中斷(簡)

2021-08-20 02:53:32 字數 2946 閱讀 1965

本文對linux2.4.0中中斷機制從原始碼層面進行簡要介紹,閱讀需要有一定基礎,詳細版本請參考這裡。

這裡主要介紹以下幾個部分:

主要是設定中斷向量表中中斷服務的型別,服務程式的入口位址,dpl等。

1.1 trap_init()初始化系統保留的中斷向量,從0x00到0x1f共36個;init_irq()初始化用於外設的通用中斷向量,0x20~0xff共224個,第0x80向量用於系統呼叫中斷,不包含在內。

1.2設定通用中斷向量的服務程式的入口位址interrupt[224]。

1.3對於用於外設的通用中斷向量,需要結構irq_desc[224],每個元素代表乙個中斷請求佇列,具有相同「中斷請求號(0x20~0xff)」的中斷請求需要掛到相應的irq_desc中。

某個裝置的初始化程式將其中斷服務程式通過request_irq()掛入到某個中斷請求佇列irq_desc中。

3.1以irq0x03_interrup為例,首先將其中斷請求號0x03-256壓棧,呼叫common_interrupt,主要是保護現場,將所有暫存器壓棧,將中斷返回位址ret_from_intr壓棧,呼叫主服務do_irq(struct pt_regs regs)

3.2從引數regs中獲取關鍵的中斷請求號irq,根據irq找到相應的中斷請求佇列irq_desc[irq],執行佇列中的服務程式。

軟中斷的目的是為了乙個中斷服務占用過長cpu時間,將中斷服務分成兩部分,第一部分僅僅完成一些關鍵的操作,然後就開中斷,中斷服務第二部分可能耗時比較長,就將其放在開中斷下進行。

我們知道正常的中斷處理程式是在do_irq中完成的,而軟中斷的第二部分則是在每次中斷處理完do_irq後判斷是否有軟中斷請求,進行進入軟中斷第二部分的服務程式。

這裡我們需要struct softirq_action softirq_vec[32]資料結構

struct softirq_action

;

它和irq_desc[224]類似,但是刻印看出它並不是乙個佇列,裡面僅僅儲存的是不同軟中斷的入口函式指標,這些函式指標在softirq_init()中設定。

在軟中斷初始化時,系統執行 softirq_init()

open_softirq(tasklet_softirq, tasklet_action, null);

open_softirq(hi_softirq, tasklet_hi_action, null);

open_softirq()

softirq_vec[nr].data = data;

softirq_vec[nr].action = action;

for (i=0; i將tasklet_action和tasklet_hi_action兩種軟中斷初始化到softirq_vec[32]陣列中。而且由於多處理器的原因,需要資料結構irq_cpustat_t irq_stat[nr_cpus]

typedef struct ____cacheline_aligned irq_cpustat_t;

來表示每個cpu的軟中斷請求暫存器,軟中斷遮蔽暫存器,可以看出軟中斷的中斷是以軟體的方式實現的。這樣哪個cpu發生的軟中斷由自己進行處理。open_soft_irq()中最後for迴圈就是將第tasklet_softirq和hi_softirq中斷遮蔽位置1,表明允許中斷。

對於tasklet_action和tasklet_hi_action兩種軟中斷,每個cpu需要軟中斷服務程式佇列頭,使得可以將第二部分的中斷服務程式掛到相應cpu佇列頭上。這個資料結構為tasklet_vec[nr_cpus]和tasklet_hi_vec[nr_cpus]

struct tasklet_head

__attribute__ ((__aligned__(smp_cache_bytes)));

我們說要將軟中斷服務程式掛到相應的cpu佇列頭中,這個資料結構就是tasklet_struct

struct tasklet_struct

;

當核心執行完do_irq()後,檢查是否有軟中斷請求,並通過do_softirq()執行。

具體就是先獲取當前cpu編號,通過

active = softirq_active(cpu) & mask;
檢視當前cpu是否有可執行未遮蔽的軟中斷。active的每一位對應乙個軟中斷號,與softirq_vec陣列中的每一項對應,因此通過

h = softirq_vec;

mask &= ~active;

do while (active);

依次執行未遮蔽已發出請求的軟中斷,我們知道,之前softirq_vec陣列中設定了兩個軟中斷服務型別:tasklet_action和tasklet_hi_action,h->action(h)可能就執行了其中乙個。我們以tasklet_action為例。

static void tasklet_action(struct softirq_action *a)

tasklet_unlock(t);

} local_irq_disable();

t->next = tasklet_vec[cpu].list;

tasklet_vec[cpu].list = t;

__cpu_raise_softirq(cpu, tasklet_softirq);

local_irq_enable();

}}

主要就是先獲取是哪個cpu要執行軟中斷服務,獲取相應cpu軟中斷服務佇列頭tasklet_vec[cpu].list,依次執行佇列中tasklet_struct結構中func函式指標指向的真正的中斷服務程式。

Linux核心 之 中斷

中斷處理函式所作的第一件事情是什麼?答案是遮蔽中斷,所以要遮蔽中斷,是因為新的中斷會再次呼叫中斷處理函式,導致原來中斷處理現場的破壞。因為中斷,它是把原來的上下文都存起來,如果是多級中斷的話,它需要存多級的上下文,除非linux能存多級上下文,感覺是能多存的。如果只能存一級,那必然是要遮蔽中斷,不然...

TinyThread原始碼分析之中斷

tinythread 是基於cortex m0的小型的os.知識儲備 ipsr 中斷程式狀態暫存器 ipsr包含了當前正在執行的中斷服務程式編號,用於識別當前中斷。cortex m0處理器內建中斷控制器,並且支援最多32個中斷請求 irq 和乙個不可遮蔽中斷 nmi primask置位 寫1 開啟遮...

Linux核心原始碼 閱讀方法

url 通常linux會有以下目錄 arch 子目錄包括所有和體系結構相關的核心 它還有更深的子目錄,每乙個代表一種支援的體系結構 include 子目錄包括編譯核心所需要的大部分 include 檔案。它也有更深的子目錄,每乙個支援的體系結構乙個。include asm 是這個體系結構所需要的真實...