日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

c6x Linux 内核中断分析

發布時間:2025/3/15 linux 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c6x Linux 内核中断分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

?

1. 內核中斷介紹

?

1.1 中斷簡介

?

所有支持Linux的平臺都采用了中斷(interrupt)的概念,以便(因種種原因)引入周期性的中斷。需要區分兩種類型的中斷。

?

1. 硬件中斷(hardware interrupt):由系統自身和與之連接的外設自動產生。它們用于支持更高效地實現設備驅動程序,也用于引起處理器自身對異常或錯誤的關注,這些是需要與內核代碼進行交互的。?

?

2. 軟中斷(SoftIRQ):用于有效實現內核中的延期操作。?

?

在Linux中用于處理中斷和系統調用相關部分的代碼中,匯編和C代碼交織在一起, 以解決C語言無法獨立處理的一些特殊問題。在中斷處理中涉及到許多C代碼和底層的硬件交互代碼。

?

在C6678處理器上,硬件中斷的最大數目通常是15,這個值可不怎么大,還有考慮到有些中斷編號已經永久性地分配給了標準的系統組件(鍵盤、定時器等),因而限制了可用于其他外部設備的中斷編號數目。

?

外設可共享同一個中斷號這個現象稱為中斷共享(interrupt sharing)。但必須硬件和內核同時支持才能使用共享中斷,因為必須要識別出中斷來源于哪個設備。

?

1.2 中斷處理

?

在CPU得知發生中斷后,它將進一步的處理委托給一個軟件例程,該例程可能會修復故障、提供專門的處理或將外部事件通知用戶進程。

?

由于每個中斷和異常都有唯一的編號,內核使用一個數組,數組項是指向處理程序函數的指針。相關的中斷號根據數組項在數組中的位置判斷。

?

▲圖1.1 中斷處理過程

?

因為需要C語言代碼和匯編語言代碼之間的交互,所以必須特別小心,才能正確設計在匯編語言層次和C語言層次上的數據交換。對應的代碼位于arch/arch/kernel/entry.S中,徹底利用了各個處理器的具體特性。

?

1.3 中斷處理程序

?

中斷處理程序可能會遇到困難,特別是在處理程序執行期間,發生了其他中斷。盡管可以通過在處理程序執行期間禁用中斷來防止,但這會引起其他問題,如遺漏重要的中斷。屏蔽(Masking, 這個術語用于表示選擇性地禁用一個或多個中斷)因而只能短時間使用。

?

中斷處理數據結構:IRQ相關信息管理的關鍵點是一個全局數組,每個數組項對應一個IRQ編號。因為數組位置和中斷號是相同的,很容易定位與特定的IRQ相關的數組項:IRQ 0在位置0IRQ 15在位置15,等等。IRQ最終映射到哪個處理器中斷。irq_desc存儲了中斷相關信息。

?

action鏈表提供了一個操作鏈,需要在中斷發生時執行。由中斷通知的設備驅動程序,可以將與之相關的處理程序函數放置在此處。有一個專門的數據結構用于表示這些操作。

?

chip硬件處理和芯片相關操作被封裝在chip中。為此引入了一個專門的數據結構用來處理硬件相關操作。

?

1.4 處理程序函數的表示

?

irqaction結構定義如下,每個處理程序函數都對應該結構的一個實例:

?

<code>

?

該結構中最重要的成員是處理程序函數本身,即handler成員,這是一個函數指針,位于結構的起始處。在設備請求一個系統中斷,而中斷控制器通過引發中斷將該請求轉發到處理器的時候,內核將調用該處理程序函數。

?

在考慮如何注冊處理程序函數時,我們再仔細考察其參數的語義。但請注意,處理程序的類型為irq_handler_t,與電流處理程序的類型irq_flow_handler_t顯然是不同的。

?

name和dev_id唯一地標識一個中斷處理程序。name是一個短字符串,用于標識設備(例如, 「e100」、「ncr53c8xx」等等),而dev_id是一個指針,指向在所有內核數據結構中唯一標識了該設備的數據結構實例,例如網卡的net_device實例。如果幾個設備共享一個IRQ,那么IRQ編號自身不能標識該設備,此時,在刪除處理程序函數時,將需要上述信息。

?

▲圖1.2 中斷結構體關系描述圖

?

2. 中斷向量表以及中斷子程序

?

2.1 中斷子程序實現

?

在匯編源文件arch/c6x/kernel/vectors.S 中定義了中斷子程序,使用宏IRQVEC可以實現不同的中斷子程序:

arch/c6x/kernel/vectors.S第?30 行實現了中斷處理宏定義IRQVEC

?

▲圖2.1 中斷處理向量宏定義

?

根據如上IRQVEC宏定義結合實際代碼使用情況可以生成不同的中斷子程序。

?

▲圖2.2 生成中斷向量

?

例如:

79行?IRQVEC INT4,_int4_handler可生成如下中斷子程序。

?

<code>

?

當中斷發生時,進入到匯編代碼中的中斷子程序,首先保存寄存器A0的值保存在棧中,然后拷貝相應的中斷子程序入口地址到A0寄存器中,然后跳轉到相應的中斷子程序,中斷子程序執行完畢后從棧中恢復寄存器A0的值。

?

在中斷子程序_int4_handler中執行如下指令

?

<code>

?

SAVE_ALL_INT此行作用為保存所有的寄存器到棧中,然后調用MASK_SYSCALL關閉系統調用,使用CALL_INT 4先將中斷號存入A4,然后調用kernel?中的?c6x_do_IRQ 中斷處理函數。調用結束后將返回結果存入寄存器B3。

?

▲圖2.3 CALL_INT宏定義

?

在arch/c6x/kernel/entry.S 中定義了諸多?_DEFINE_MACRO 匯編宏定義。

1. 220行?_DEFINE_MACRO(SAVE_ALL_INT)??中斷保存所有寄存器。

2. 325行?_DEFINE_MACRO(MASK_SYSCALL) 屏蔽系統調用。

?

2.1 c6x_do_IRQ處理流程

?

c6x_do_IRQ函數的是實現在arch/c6x/kernel/irq.c文件中

64行?asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs)

?

▲圖2.4 c6x_do_IRQ中斷函數

?

獲取kernel中斷號:

?

c6x_do_IRQ 獲取中斷號prio,將中斷號通過hw_to_kernel_irq將硬件中斷號轉換為kernel中斷號,轉換后傳入kernel的中斷處理函數generic_handle_irq。

?

在代碼中hw_to_kernel_irq如何將硬件中斷號轉換為kernel中斷號?

?

在中斷初始化的過程中構建prio_to_irq的中斷對應數組,將硬件中斷號和kernel中斷號產生對應關系。當使用hw_to_kernel_irq的時候,hw_to_kernel_irq從中斷對應數組?prio_to_irq[(hw)] 中取出kernel中斷號。

?

常規內核處理函數generic_handle_irq?處理中斷流程:

?

在include/linux/irq.h 頭文件中實現了generic_handle_irq和

generic_handle_irq_desc兩個內聯函數。

?

generic_handle_irq 使用kernel中斷號irq獲取irq中斷號相對應的irq_to_desc,既irq_desc結構體數組,然后調用generic_handle_irq_desc將中斷號,和獲取的irq_desc結構體數組傳給generic_handle_irq_desc。

?

▲圖2.5 generic_handle_irq_desc

?

在generic_handle_irq_desc函數中檢測irq對應的irq_desc結構體中是否有中斷處理函數handle_irq。

?

如果有handle_irq就執行此中斷的中斷處理函數,這里執行的是handle_level_irq函數,在irq_desc->handle_irq中我們無法直接看到其對應的中斷處理函數,可以通過init_IRQ?初始化函數中獲得此處填入的中斷處理函數名稱。

?

▲圖2.6 init_IRQ 中斷初始化函數

?

handle_level_irq函數中執行的流程如下:

1. lock中斷。

2. 檢測中斷是否為處理中狀態:IRQ_INPROGRESS。

3.?如果中斷為正在處理的狀態直接跳到結尾處unlock中斷并推出函數。

4.?如果中斷為觸發狀態,將中斷設置為正在處理的狀態,并且調用handle_IRQ_event執行相應中斷處理函數。

?

如果沒有handle_irq就說明此中斷為共享中斷(IRQ線)執行__do_IRQ(irq)。

__do_IRQ 處理所有普通設備的中斷,每一個設備都有其特定的中斷處理函數,存在放action列表中。

?

在kernel/irq/handler.c文件中實現了__do_IRQ函數。__do_IRQ函數主要遍歷irq_desc 結構體中的action鏈表處理中斷。

?

449行?unsigned int __do_IRQ(unsigned int irq)

接下來使用共享中斷處理函數:handle_IRQ_event?來遍歷irq_desc 里的?action共享中斷鏈表。

?

handle_IRQ_event函數:

?

在kernel/irq/handle.c?368行irqreturn_t handle_IRQ_event( unsigned int irq,struct irqaction *action)Handle_IRQ_event?用來處理irq實際的action鏈表。

?

?

總結

以上是生活随笔為你收集整理的c6x Linux 内核中断分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。