Linux內核中斷屏蔽的實現-世界熱推薦

2023-07-04 14:18:17 來源:嵌入式藝術

1、中斷屏蔽思想

中斷屏蔽,正如其名,屏蔽掉CPU的中斷響應功能,解決并發引起的競態問題。

在進入臨界區前屏蔽中斷,這么做有什么好處,以及有什么弊端?

好處在于


(資料圖片)

保證在執行臨界區代碼時,不被中斷所打斷同時,系統的進程調度與中斷息息相關,同時也限制了系統進程的并發,解決了系統進程并發帶來的競態問題。

弊端在于

Linux內核中,除了系統進程調度依賴中斷,還有一些異步I/O等眾多操作都依賴中斷,因此長時間屏蔽中斷是很危險的,會對系統造成嚴重影響,因此也要求臨界區代碼要簡短。關閉中斷能夠解決進程調度、中斷引發的競態,但是這些都是單CPU內部的,對于SMP對稱多處理器,仍然不可避免的會收到其他CPU的中斷。因此,并不能解決SMPCPU引發的競態

因此,單獨使用中斷屏蔽通常不是一種值得推薦的避免競態的方法

2、Linux內核中斷屏蔽的實現

2.1 Linux內核提供的API接口

關于中斷屏蔽,Linux內核所提供的接口如下:

local_irq_enable()    // 使能本CPU的中斷local_irq_disable()    // 禁止本CPU的中斷local_irq_save(flags)   // 禁止本CPU的中斷,并保存CPU中斷位的信息local_irq_restore(flags)  // 使能本CPU的中斷,并恢復CPU中斷位的信息local_bh_disable(void)   // 禁止本CPU底半部中斷local_bh_enable(void)      // 使能本CPU底半部中斷

2.2 API接口實現分析

因為中斷屏蔽與底層芯片架構有關,不同架構處理方式不同,我們以ARM為例

2.2.1 local_irq_enable

#define local_irq_enable() do { raw_local_irq_enable(); } while (0)#define raw_local_irq_enable()  arch_local_irq_enable()#define arch_local_irq_enable arch_local_irq_enablestaticinline void arch_local_irq_enable(void){ asm volatile(  " cpsie i   @ arch_local_irq_enable"  :  :  : "memory", "cc");}

函數介紹local_irq_enable函數用于將CPSR寄存器中的中斷使能位設為1,從而使得CPU能夠響應中斷。

相關實現

asm:聲明一個內聯匯編表達式

cpsie i:匯編指令,設置CPSR寄存器的I位,來允許本CPU響應中斷。

memory:向匯編說明,此處內存發生了更改,類似于內存屏障的作用

cc:表示可能會修改條件碼的標志

2.2.2 arch_local_irq_disable

#define arch_local_irq_disable arch_local_irq_disablestatic inline void arch_local_irq_disable(void){ asm volatile(  " cpsid i   @ arch_local_irq_disable"  :  :  : "memory", "cc");}

函數介紹arch_local_irq_disable函數用于將CPSR寄存器中的中斷使能位設為0,從而禁止CPU響應中斷。

相關實現:同上

cpsid:是匯編指令,用于清除CPSR寄存器的中斷標志,以禁止中斷!

2.2.3 arch_local_irq_save

#define arch_local_irq_save arch_local_irq_savestatic inline unsigned long arch_local_irq_save(void){ unsigned long flags; asm volatile(  " mrs%0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\\n"  " cpsid i"  : "=r" (flags) : : "memory", "cc"); return flags;}

函數介紹arch_local_irq_save函數,用于保存當前中斷狀態并禁用中斷。

相關實現

mrs %0 IRQMASK_REG_NAME_Rmrs指令將由IRQMASK_REG_NAME_R宏指定的IRQMASK寄存器的值移動到flags變量中。

2.2.4 arch_local_irq_restore

/* * restore saved IRQ & FIQ state */#define arch_local_irq_restore arch_local_irq_restorestatic inline void arch_local_irq_restore(unsigned long flags){ asm volatile(  " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"  :  : "r" (flags)  : "memory", "cc");}

函數介紹arch_local_irq_restore函數,用于恢復當前中斷狀態并打開中斷。

相關實現:同上

關于local_bh_disablelocal_bh_enable兩個接口,涉及到中斷底半部機制,內容較為復雜,放在后面單獨拆解

3、總結

該篇文章,主要了解以下幾點:

中斷屏蔽的思想中斷屏蔽的好處與不足Linux內核提供的中斷屏蔽接口中斷屏蔽的基本匯編實現

標簽:

上一篇:詳解Linux內核鎖的原子操作
下一篇:最后一頁