中斷屏蔽,正如其名,屏蔽掉CPU
的中斷響應(yīng)功能,解決并發(fā)引起的競(jìng)態(tài)問題。
在進(jìn)入臨界區(qū)前屏蔽中斷,這么做有什么好處,以及有什么弊端?
好處在于:
(資料圖片)
保證在執(zhí)行臨界區(qū)代碼時(shí),不被中斷所打斷同時(shí),系統(tǒng)的進(jìn)程調(diào)度與中斷息息相關(guān),同時(shí)也限制了系統(tǒng)進(jìn)程的并發(fā),解決了系統(tǒng)進(jìn)程并發(fā)帶來的競(jìng)態(tài)問題。弊端在于:
Linux
內(nèi)核中,除了系統(tǒng)進(jìn)程調(diào)度依賴中斷,還有一些異步I/O
等眾多操作都依賴中斷,因此長(zhǎng)時(shí)間屏蔽中斷是很危險(xiǎn)的,會(huì)對(duì)系統(tǒng)造成嚴(yán)重影響,因此也要求臨界區(qū)代碼要簡(jiǎn)短。關(guān)閉中斷能夠解決進(jìn)程調(diào)度、中斷引發(fā)的競(jìng)態(tài),但是這些都是單CPU
內(nèi)部的,對(duì)于SMP
對(duì)稱多處理器,仍然不可避免的會(huì)收到其他CPU
的中斷。因此,并不能解決SMP
多CPU
引發(fā)的競(jìng)態(tài)因此,單獨(dú)使用中斷屏蔽通常不是一種值得推薦的避免競(jìng)態(tài)的方法
關(guān)于中斷屏蔽,
Linux
內(nèi)核所提供的接口如下:
local_irq_enable() // 使能本CPU的中斷l(xiāng)ocal_irq_disable() // 禁止本CPU的中斷l(xiāng)ocal_irq_save(flags) // 禁止本CPU的中斷,并保存CPU中斷位的信息local_irq_restore(flags) // 使能本CPU的中斷,并恢復(fù)CPU中斷位的信息local_bh_disable(void) // 禁止本CPU底半部中斷l(xiāng)ocal_bh_enable(void) // 使能本CPU底半部中斷
因?yàn)橹袛嗥帘闻c底層芯片架構(gòu)有關(guān),不同架構(gòu)處理方式不同,我們以
ARM
為例
#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");}
函數(shù)介紹:local_irq_enable
函數(shù)用于將CPSR
寄存器中的中斷使能位設(shè)為1,從而使得CPU
能夠響應(yīng)中斷。
相關(guān)實(shí)現(xiàn):
asm
:聲明一個(gè)內(nèi)聯(lián)匯編表達(dá)式
cpsie i
:匯編指令,設(shè)置CPSR
寄存器的I
位,來允許本CPU
響應(yīng)中斷。
memory
:向匯編說明,此處內(nèi)存發(fā)生了更改,類似于內(nèi)存屏障的作用
cc
:表示可能會(huì)修改條件碼的標(biāo)志
#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");}
函數(shù)介紹:arch_local_irq_disable
函數(shù)用于將CPSR
寄存器中的中斷使能位設(shè)為0,從而禁止CPU
響應(yīng)中斷。
相關(guān)實(shí)現(xiàn):同上
cpsid
:是匯編指令,用于清除CPSR
寄存器的中斷標(biāo)志,以禁止中斷!#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;}
函數(shù)介紹:arch_local_irq_save
函數(shù),用于保存當(dāng)前中斷狀態(tài)并禁用中斷。
相關(guān)實(shí)現(xiàn):
mrs %0 IRQMASK_REG_NAME_R
:mrs
指令將由IRQMASK_REG_NAME_R
宏指定的IRQMASK
寄存器的值移動(dòng)到flags
變量中。
/* * 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");}
函數(shù)介紹:arch_local_irq_restore
函數(shù),用于恢復(fù)當(dāng)前中斷狀態(tài)并打開中斷。
相關(guān)實(shí)現(xiàn):同上
關(guān)于
local_bh_disable
和local_bh_enable
兩個(gè)接口,涉及到中斷底半部機(jī)制,內(nèi)容較為復(fù)雜,放在后面單獨(dú)拆解!
該篇文章,主要了解以下幾點(diǎn):
中斷屏蔽的思想中斷屏蔽的好處與不足Linux
內(nèi)核提供的中斷屏蔽接口中斷屏蔽的基本匯編實(shí)現(xiàn) 標(biāo)簽: