Linux中斷處理體系結構分析(一)

2021-07-29 17:38:43 字數 4968 閱讀 2000

異常,就是可以打斷cpu正常執行流程的一些事情,比如外部中斷、未定義指令、試圖修改唯讀的資料、執行swi指令(software interrupt instruction ,軟體中斷指令)等。當這些事情發生時,cpu暫停當前的程式,先處理異常事件,然後再繼續執行被中斷的程式。作業系統中經常通過異常來完成一些特定的功能。其中的中斷也占有很大的一部分。例如下面的這幾種情況:

在原先的核心版本中,核心在start_kernel函式(原始碼在init/main.c中)中呼叫trap_init、init_irq兩個函式來設定異常和處理函式。在linux2.6.32.2的核心版本中(也許在之前的版本就有變化),trap_init函式的內容發生了變化,在trap.c中,

void __init trap_init(

void

)

在這個檔案中還有乙個函式,

void __init early_trap_init(

void

)

這個函式才是真正要用到的,在init/mian.c中可以找到,呼叫了trap_init(),而early_trap_init()函式在setup_arch(&command_line)函式中呼叫。在

linux

/arch

/arm

/kernel

/setup.c

698void __init setup_arch(

char

**cmdline_p)

699

這樣我們就明白了trap_init()函式的具體呼叫過程了。下面我們具體來看一下這個trap_init()函式,確切的說是earl_trap_init()函式。

earl_tarp_init函式(**在arch/arm/kernel/traps.c中)被用來設定各種異常的處理向量,包括中斷向量。所謂「向量」,就是一些被安放在固定位置的**,當發生異常時,cpu會自動執行這些固定位置上的指令。arm架構的cpu的異常向量基址可以是0x00000000,也可以是0xffff0000,linux核心使用後者。

earl_trap_init函式將異常向量複製到0xffff0000處,我們可以在該函式中看到下面的兩行**。

memcpy((

void

*)vectors, __vectors_start, __vectors_end- __vectors_start)

;memcpy((

void

*)vectors + 0x200, __stubs_start, __stubs_end- __stubs_start)

;

vectors等於0xffff0000。位址__vectors_start ~ __vectors_end之間的**就是異常向量,在arch/arm/kernel/entry-armv.s中定義,它們複製到位址0xffff0000處。異常向量的**很簡單,它們只是一些跳轉指令。發生異常時,cpu自動執行這些指令,跳轉去執行更複雜的**,比如儲存被中斷程式的執行環境,呼叫異常處理函式,恢復被中斷程式的執行環境並重新執行。這些「更複雜的**」在位址__stubs_start ~__stubs_end之間,它們在arch/arm/kernel/entry-armv.s中定義。將它們複製到位址0xffff0000+0x200處。

異常向量、異常向量跳去執行的**都是使用彙編寫的,它們在arch/arm/kernel/entry-armv.s中。異常向量的**如下,其中的「stubs_offset」用來重新定位跳轉的位置(向量被複製到位址0xffff0000

處,跳轉的目的**被複製到位址0xffff0000+0x200處)。

.

equ    stubs_offset, __vectors_start+ 0x200 - __stubs_start

.globl    __vectors_start

__vectors_start:

arm(    swi    sys_error0    ) //復位是,cpu將執行這條指令

thumb(    svc    #0        )

thumb(

nop)

w(b)    vector_und+ stubs_offset//未定義異常時,cpu將執行這條指令

w(ldr)    pc,

.lcvswi + stubs_offset//swi異常

w(b)    vector_pabt+ stubs_offset//指令預取中止

w(b)    vector_dabt+ stubs_offset//資料訪問中止

w(b)    vector_addrexcptn+ stubs_offset//沒有用到

w(b)    vector_irq+ stubs_offset//irq異常

w(b)    vector_fiq+ stubs_offset// fiq 異常

.globl    __vectors_end

__vectors_end:

其中,vector_und、vector_pabt等表示要跳轉去執行的**。以vector_und為例,它仍在arch/arm/kernel/entry-armv.s中,通過vector_stub巨集來定義,

vector_stub    und, und_mode

.long    __und_usr      @ 0 (usr_26 / usr_32) 在使用者模式執行了未定

義指令.long    __und_invalid   @ 1 (fiq_26 / fiq_32)在fiq模式執行了未定義指令

.long    __und_invalid   @ 2 (irq_26 / irq_32)在irq模式下執行了未定義指令

.long    __und_svc       @ 3 (svc_26 / svc_32)在管理模式下執行了未定義指令

.long    __und_invalid            @ 4

.long    __und_invalid            @ 5

.long    __und_invalid            @ 6

.long    __und_invalid            @ 7

.long    __und_invalid            @ 8

.long    __und_invalid            @ 9

.long    __und_invalid            @ a

.long    __und_invalid            @ b

.long    __und_invalid            @ c

.long    __und_invalid            @ d

.long    __und_invalid            @ e

.long    __und_invalid            @ f

vector_stub是乙個巨集,它根據後面的引數"und,und_mode"定義了以「vector_und」為標號的一段**。

後進行管理模式,最後根據被中斷的工作模式呼叫下面的某個跳轉分支。當發生異常時,cpu會根據異常

的型別進入某個工作模式,但是很快vector_stub巨集又會強制cpu進行管理模式,在管理模式下進行後續處

理,這種方法簡化了程式的設計,使得異常發生前的工作模式根毛是使用者模式,要麼是管理模式。

**表示在各個工作模式下執行未定義指令時,發生異常的處理分支。比如__und_usr表示在使用者模式下

執行未定義指令時,所發生的未定義異常將由它來處理;__und_svc表示在管理模式下執行未定義指令時,

所發生的未定義異常將由它來處理。在其他工作模式下不可能發生未定義指令異常,否則使用

「__und_invalid」來處理錯誤。arm架構cpu中使用4位資料來表示工作模式,所以共有16個跳轉分支,目

前只有7個工作模式。

不同的跳轉分支只是在它們的入口下(比如儲存被中斷程式的暫存器)稍有差別,後續的處理大體相同,都在呼叫相應的c函式,比如未定義指令異常發生時,最終會呼叫c函式do_undefinstr來進行處理。各種異常c處理函式可以分為5類,它們分布在不同的檔案中

(1)在arch/arm/kernel/traps.c中

未定義指令異常的c處理函式在這個檔案中定義,總入口函式為do_undefinstr

(2)在arch/arm/mm/fault.c中

與記憶體訪問相關的異常c處理函式在這個檔案中定義,比如資料訪問中止異常、指令預取中止異常。總入口函式為do_dataabort、do_prefetchabort。

(3)在arch/arm/mm/irq.c中

中斷處理函式的在這個檔案中定義,總入口函式為asm_do_irq,它呼叫其他檔案註冊的中斷處理函式

(4)在arch/arm/kernel/calls.s

在這個檔案中,swi異常的處理函式指標被組織成乙個**;swi指令機器碼的位[23:0]被用來作為索引。這樣,通過不同的swi index指令就可以呼叫不同的swi異常處理函式,它們被稱為系統呼叫,比如sys_open、sys_read等。

(5)沒有使用的異常

沒有使用fiq異常

trap_init函式搭建了各類異常的處理框架。當發生異常時,各種c處理函式會被呼叫。這些c函式還要進

一步細分異常發生的情況,分別呼叫更具體的處理函式。

2.init_irq函式分析

中斷也是一種異常,之所以把它單獨的列出來,是因為中斷的處理與具體的開發板密切相關,除一些必須

、共用的中斷(比如系統時鐘中斷、片內外設uart中斷)外,必須由驅動開發者提供處理函式。核心提煉

出中斷處理的共性,搭建乙個非常容易擴充的中斷處理體系。

init_irq函式(**在arch/arm/kernel/irq.c中)被用來初始化中斷和處理框架,設定各種中斷的預設

處理函式。當發生中斷時,中斷總入口函式asm_do_irq就可以呼叫這些函式進行下一步處理。

ClearQuest體系結構分析

關鍵字clearquest 體系結構分析 clearquest是按照標準的三層結構設計的,包括資料層 功能層 業務層 表示層。下面分別說明三層的構造和相互的關係。clearquest的根本在資料庫,所有的內容都儲存在資料庫中。在使用cq資料庫的時候,一定要記住一點 必須先建立空白的資料庫再進行cq的...

ARM學習之中斷體系結構

今天下午和晚上研究了一直在研究s3c2410中斷體系結構,雖然以前老師上課也接觸過,考試也考過,但仔細研究起來,還是有不少收穫的。現記述如下 1.什麼是中斷?答 中斷是cpu保證併發程式的一種機制。它使得cpu在執行程式的時候能夠響應異常的情況發生。其實,在cpu在執行的過程中,如何知道各類外設發生...

ARM學習之中斷體系結構

1.什麼是中斷?答 中斷是cpu保證併發程式的一種機制。它使得cpu在執行程式的時候能夠響應異常的情況發生。其實,在cpu在執行的過程中,如何知道各類外設發生了某些沒預期的事,比如說串列埠接受到了資料 usb介面中插入了裝置 按下了某個按鍵。有兩種方法,乙個是前面所說的中斷 另乙個就是輪詢方式。就是...