自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux 中斷子系統(tǒng):中斷處理知識(shí)點(diǎn)大全

系統(tǒng) Linux
cat 這個(gè)節(jié)點(diǎn),會(huì)打印系統(tǒng)中所有的中斷信息,包括每個(gè)中斷的名字、中斷號(hào) IRQ number、每個(gè)中斷的觸發(fā)次數(shù)、在哪個(gè)CPU核處理的、是邊沿觸發(fā)還是電平觸發(fā),屬于哪個(gè)中斷控制器,都會(huì)打印出來(lái)。

[[440239]]

Linux 中斷相關(guān)節(jié)點(diǎn)

/proc/interrupts

cat 這個(gè)節(jié)點(diǎn),會(huì)打印系統(tǒng)中所有的中斷信息,如果是多核CPU,每個(gè)核都會(huì)打印出來(lái)。

包括每個(gè)中斷的名字、中斷號(hào) IRQ number、每個(gè)中斷的觸發(fā)次數(shù)、在哪個(gè)CPU核處理的、是邊沿觸發(fā)還是電平觸發(fā),屬于哪個(gè)中斷控制器,都會(huì)打印出來(lái)。

/proc/irq/…

進(jìn)入這個(gè)目錄。會(huì)看到以中斷號(hào)命名的文件夾,每個(gè)中斷號(hào)文件夾下面都有幾個(gè)節(jié)點(diǎn),存儲(chǔ)了這個(gè)中斷的信息,比如 smp_affinity、affinity_hint、spurious等。smp_affinity 代表中斷號(hào)核CPU之間的親緣綁定關(guān)系,也就是如果某個(gè)中斷號(hào)綁定了一個(gè)CPU核,那么這個(gè)中斷就會(huì)一直在這個(gè)CPU上處理。

如何讓某個(gè)中斷在某個(gè)特定的 CPU 處理?

kernel 2.4 以后的版本才支持把不同的硬件中斷請(qǐng)求(IRQs)分配到特定的 CPU 上,這個(gè)綁定技術(shù)被稱為 SMP IRQ Affinity. 更多介紹請(qǐng)參看 Linux 內(nèi)核源代碼自帶的文檔:linux-4.14/Documentation/IRQ-affinity.txt

/proc/irq/{IRQ}/smp_affinity

/proc/irq/{IRQ}/smp_affinity_list

/proc/irq/{IRQ}/smp_affinity 指定給定的 irq 中斷號(hào)源允許哪些CPU執(zhí)行,它是一個(gè)掩碼位,比如是ff,代表11111111,表示這個(gè)中奪冠可以在 8 個(gè) CPU 執(zhí)行,具體在哪一個(gè) CPU 執(zhí)行,靠分配器分配。

如果這個(gè) /proc/irq/{IRQ}/smp_affinity 指定為 00000001,代表這個(gè)IRQ只能在最后一個(gè)CPU核進(jìn)行處理,其他CPU不允許處理,大家可以測(cè)試一下,博主測(cè)試是 OK 的(GIC支持,其他中斷控制器不一定)。

串口手動(dòng)賦值的重啟以后會(huì)消失,可以在代碼中調(diào)用 irq_set_affinity 函數(shù),指定中斷的掩碼,來(lái)達(dá)到某個(gè)中斷被固定CPU處理的需求。

中斷分發(fā)機(jī)制

對(duì)于 GIC-V2 而言,SPI 的分發(fā)是根據(jù) Distributor 中的 Interrupt Processor Targets Registers 來(lái)決定的。對(duì)于任何一個(gè) SPI,其都有在某個(gè) GICD_ITARGETSRn 寄存器中有 8 個(gè)bit標(biāo)識(shí)送達(dá)的 processor,如果只有一個(gè) bit 被 set,那么就很簡(jiǎn)單了,如果該中斷是當(dāng)前優(yōu)先級(jí)最高的中斷,那么 Distributor 就會(huì)送到對(duì)應(yīng)的 CPU interface,該中斷最終會(huì)送達(dá)指定的 CPU。

如果該中斷對(duì)應(yīng)的 Interrupt Processor Targets Registers 中的那 8 個(gè) bit 有多個(gè) bit 被 set 的話,Distributor 如何處理呢?“依次輪著把產(chǎn)生的中斷給各個(gè) CPU,還是說(shuō)看哪個(gè)CPU有空就給哪個(gè)CPU來(lái)著”,讓硬件處理這么復(fù)雜的邏輯有些不合適,實(shí)際上,GIC 的硬件是不會(huì)進(jìn)行任何判斷的,也不會(huì)集成任何的算法,它就是根據(jù)Interrupt Processor Targets Registers的bit設(shè)定情況,忠實(shí)的把中斷送往指定的一個(gè)processor或者多個(gè)processors。

大家可以去看看 gic_set_affinity 這個(gè)函數(shù),這個(gè)函數(shù)確保一個(gè)中斷的 Interrupt Processor Targets Registers 中的那8個(gè)bit只有一個(gè)bit被設(shè)定。

/kernel5.15/drivers/irqchip/irq-gic-v3.c

在 1244 和 1246 行,1246 行就是在 online 的 CPU 中選中一個(gè),1263 行寫入到寄存器中,GIC 會(huì)讀取這個(gè)寄存器,是哪個(gè) CPU,然后將中斷發(fā)給這個(gè)CPU。中間的函數(shù)很簡(jiǎn)單,大家可以自己看。

中斷狀態(tài)機(jī)

對(duì)于 GIC-V2 而言,中斷的狀態(tài)機(jī)由 Distributor 維護(hù),每個(gè)中斷都有一個(gè)狀態(tài)機(jī)。

Inactive :中斷未激活(未發(fā)生)。

Pending:中斷到達(dá) GIC ,等待 CPU 的處理。

Active:中斷得到 CPU 的應(yīng)答,中斷被CPU處理。

Active and pending :某個(gè)中斷正在被 CPU 處理,這時(shí)候該中斷又來(lái)了。

來(lái)看一個(gè)例子:

(a)N 和 M 用來(lái)標(biāo)識(shí)兩個(gè)外設(shè)中斷,N 的優(yōu)先級(jí)大于 M

(b)兩個(gè)中斷都是 SPI 類型,level trigger,active-high

(c)兩個(gè)中斷被配置為去同一個(gè) CPU

(d)都被配置成 group 0,通過(guò) FIQ 觸發(fā)中斷

時(shí)刻 事件
T0時(shí)刻 Distributor檢測(cè)到M這個(gè)interrupt source的有效觸發(fā)電平
T2時(shí)刻 Distributor將M這個(gè)interrupt source的狀態(tài)設(shè)定為pending
T17時(shí)刻 大約15個(gè)clock之后,CPU interface拉低nFIQCPU信號(hào)線,向CPU報(bào)告M外設(shè)的中斷請(qǐng)求。這時(shí)候,CPU interface的ack寄存器(GICC_IAR)的內(nèi)容會(huì)修改成M interrupt source對(duì)應(yīng)的ID
T42時(shí)刻 Distributor檢測(cè)到N這個(gè)優(yōu)先級(jí)更高的interrupt source的觸發(fā)事件
T43時(shí)刻 Distributor將N這個(gè)interrupt source的狀態(tài)設(shè)定為pending。同時(shí),由于N的優(yōu)先級(jí)更高,因此Distributor會(huì)標(biāo)記當(dāng)前優(yōu)先級(jí)最高的中斷
T58時(shí)刻 大約15個(gè)clock之后,CPU interface拉低nFIQCPU信號(hào)線,向CPU報(bào)告N外設(shè)的中斷請(qǐng)求。當(dāng)然,由于T17時(shí)刻已經(jīng)assert CPU了,因此實(shí)際的電平信號(hào)仍然保持asserted。這時(shí)候,CPU interface的ack寄存器(GICC_IAR)的內(nèi)容會(huì)被更新成N interrupt source的ID
T61時(shí)刻 軟件通過(guò)讀取 ack 寄存器的內(nèi)容,獲取了當(dāng)前優(yōu)先級(jí)最高的,并且狀態(tài)是pending的interrupt ID(也就是N interrupt source對(duì)應(yīng)的ID),通過(guò)讀該寄存器,CPU也就ack了該interrupt source N。這時(shí)候,Distributor將N這個(gè)interrupt source的狀態(tài)設(shè)定為pending and active(因?yàn)槭请娖接|發(fā),只要外部仍然有asserted的電平信號(hào),那么一定就是pending的,而該中斷是正在被CPU處理的中斷,因此狀態(tài)是pending and active)注意:T61標(biāo)識(shí)CPU開始服務(wù)該中斷
T64時(shí)刻 3個(gè)clock之后,由于CPU已經(jīng)ack了中斷,因此GIC中CPU interface模塊 deassert nFIQCPU信號(hào)線,解除發(fā)向該CPU的中斷請(qǐng)求
T126時(shí)刻 由于中斷服務(wù)程序操作了N外設(shè)的控制寄存器(ack外設(shè)的中斷),因此N外設(shè)deassert了其interrupt request signal
T128時(shí)刻 Distributor解除N外設(shè)的pending狀態(tài),因此N這個(gè)interrupt source的狀態(tài)設(shè)定為active
T131時(shí)刻 軟件操作End of Interrupt寄存器(向GICC_EOIR寄存器寫入N對(duì)應(yīng)的interrupt ID),標(biāo)識(shí)中斷處理結(jié)束。Distributor將N這個(gè)interrupt source的狀態(tài)修改為idle,注意:T61~T131是CPU服務(wù)N外設(shè)中斷的的時(shí)間區(qū)域,這個(gè)期間,如果有高優(yōu)先級(jí)的中斷pending,會(huì)發(fā)生中斷的搶占(硬件意義的),這時(shí)候CPU interface會(huì)向CPU assert 新的中斷。
T146時(shí)刻 大約15個(gè)clock之后,Distributor向CPU interface報(bào)告當(dāng)前pending且優(yōu)先級(jí)最高的interrupt source,也就是M了。漫長(zhǎng)的pending之后,M終于迎來(lái)了春天。CPU interface拉低nFIQCPU信號(hào)線,向CPU報(bào)告M外設(shè)的中斷請(qǐng)求。這時(shí)候,CPU interface的ack寄存器(GICC_IAR)的內(nèi)容會(huì)修改成M interrupt source對(duì)應(yīng)的ID
T211時(shí)刻 CPU ack M中斷(通過(guò)讀GICC_IAR寄存器),開始處理低優(yōu)先級(jí)的中斷

Linux 搶占機(jī)制

GIC 中斷控制器支持中斷優(yōu)先級(jí)搶占,一個(gè)高優(yōu)先級(jí)中斷可以搶占一個(gè)低優(yōu)先級(jí)且處于active狀態(tài)的中斷,即GIC仲裁單元會(huì)記錄和比較當(dāng)前優(yōu)先級(jí)最高的pending狀態(tài),然后去搶占當(dāng)前中斷,并且發(fā)送這個(gè)最高優(yōu)先級(jí)的中斷請(qǐng)求給CPU。

從GIC角度看,GIC 會(huì)發(fā)送高優(yōu)先級(jí)中斷請(qǐng)求給CPU。但是CPU不一定響應(yīng)!!!因?yàn)樵谥袛嗵幚磉^(guò)程中,CPU處于關(guān)中斷狀態(tài)(關(guān)閉本CPU),需要等低優(yōu)先級(jí)中斷處理完畢,直到發(fā)送 EOI 給GIC,然后CPU才會(huì)響應(yīng)pending狀態(tài)中優(yōu)先級(jí)最高的中斷進(jìn)行處理。所以 Linux 下:

1、高優(yōu)先級(jí)中斷無(wú)法搶占正在執(zhí)行的低優(yōu)先級(jí)中斷。

2、同處于 pending 狀態(tài)的中斷,優(yōu)先響應(yīng)高優(yōu)先級(jí)中斷進(jìn)行處理。

3、同優(yōu)先級(jí)同是 pending 狀態(tài)的中斷,選擇硬件中斷號(hào) ID 最小的一個(gè)發(fā)給CPU。

這樣是可以理解的,如果萬(wàn)一中斷大量爆發(fā),中斷如果允許嵌套的話,棧會(huì)越來(lái)越大,會(huì)爆掉,所以為了防止這種情況發(fā)生,Linux中中斷不允許嵌套,單CPU中,在一個(gè)中斷處理完之前,不會(huì)相應(yīng)另外一個(gè)中斷,哪怕優(yōu)先級(jí)比它高。

FreeRTOS 中是允許高優(yōu)先級(jí)中斷搶占正在執(zhí)行的低優(yōu)先級(jí)中斷,不同系統(tǒng)設(shè)定不一樣。

中斷與進(jìn)程

進(jìn)程調(diào)度是一個(gè)復(fù)雜的機(jī)制, 根據(jù)需求的不同,在不同時(shí)刻會(huì)切換調(diào)度機(jī)制,CPU會(huì)根據(jù)進(jìn)程優(yōu)先級(jí)、時(shí)間片等信息,對(duì)不同進(jìn)程進(jìn)行調(diào)度。

中斷可以打斷進(jìn)程的運(yùn)行,任意一個(gè)中斷的優(yōu)先級(jí)都比所有的進(jìn)程高。

在中斷處理過(guò)程中,主要是 GIC 和 CPU 的交互,即便 GIC 支持高優(yōu)先級(jí)中斷搶占正在執(zhí)行的低優(yōu)先級(jí)中斷,發(fā)信號(hào)給 CPU core,但是 CPU core 可以不處理,因?yàn)?Linux 中當(dāng) CPU core 執(zhí)行中斷處理時(shí),是關(guān)中斷和關(guān)搶占的狀態(tài),不再相應(yīng)中斷信號(hào)。

也就意味著,在中斷優(yōu)先級(jí)這個(gè)概念中,只有當(dāng) GIC 同時(shí)存在多個(gè) pending 的中斷,這時(shí)候會(huì)選擇優(yōu)先級(jí)最高的去執(zhí)行,高優(yōu)先級(jí)會(huì)搶占低優(yōu)先級(jí)中斷(哪怕低優(yōu)先級(jí)先來(lái))。如果低優(yōu)先級(jí)中斷處于 active 狀態(tài),是不可以被搶占的,這是前后關(guān)系。搶占只存在于同時(shí)是pending 狀態(tài)的時(shí)候。

Linux 為什么中斷不允許休眠?

所謂的睡眠,就是調(diào)用 schedule 讓出 CPU,調(diào)度器選擇另外個(gè)進(jìn)程繼續(xù)執(zhí)行,這個(gè)過(guò)程涉及進(jìn)程??臻g的切換。

1、假如中斷上下文中調(diào)用 schedule ,此時(shí)獲取的 struct thread info 數(shù)據(jù)結(jié)構(gòu)是發(fā)生中斷時(shí)該進(jìn)程棧信息,而不是中斷上下文調(diào)用 schedule 時(shí)任何信息。這就導(dǎo)致再也無(wú)法返回中斷上下文中調(diào)用 schedule 的地方。

2、中斷上下文處于關(guān)中斷中,需要發(fā)送個(gè) EOI 通知 GIC 中斷處理結(jié)束,GIC 和CPUinterface 才會(huì)進(jìn)入下一次中斷處理。如果中途 schedule,那么整個(gè)系統(tǒng)的中斷都會(huì)被屏蔽掉。

一般進(jìn)入中斷后,需要關(guān)中斷,也會(huì)關(guān)搶占,同時(shí)注意不可以調(diào)用schedule。

unhandled interrupt 和 spurious interrupt

未處理中斷和虛假中斷

在中斷處理的最后,總會(huì)有一段代碼如下:

  1. irqreturn_t 
  2. handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action
  3.  
  4. …… 
  5.  
  6.     if (!noirqdebug) 
  7.         note_interrupt(irq, desc, retval); 
  8.     return retval; 

note_interrupt就是進(jìn)行unhandled interrupt和spurious interrupt處理的。對(duì)于這類中斷,linux kernel有一套復(fù)雜的機(jī)制來(lái)處理,你可以通過(guò)command line參數(shù)(noirqdebug)來(lái)控制開關(guān)該功能。

當(dāng)發(fā)生了一個(gè)中斷,但是沒有被處理(有兩種可能,一種是根本沒有注冊(cè)的 specific handler,第二種是有 handler,但是 handler 否認(rèn)是自己對(duì)應(yīng)的設(shè)備觸發(fā)的中斷),怎么辦?毫無(wú)疑問(wèn)這是一個(gè)異常狀況,那么 kernel 是否要立刻采取措施將該 IRQ disable 呢?也不太合適,畢竟 interrupt request 信號(hào)線是允許共享的,直接 disable 該 IRQ 有可能會(huì)下手太狠,kernel 采取了這樣的策略:如果該 IRQ 觸發(fā)了 100,000 次,但是 99,900 次沒有處理,在這種條件下,我們就是 disable 這個(gè) interrupt request line。

中斷線和中斷號(hào)是一個(gè)意思。

相關(guān)的控制數(shù)據(jù)在中斷描述符中,如下:

  1. struct irq_desc { 
  2. …… 
  3.     unsigned int        irq_count;--------記錄發(fā)生的中斷的次數(shù),每100,000則回滾 
  4.     unsigned long        last_unhandled;-----上一次沒有處理的IRQ的時(shí)間點(diǎn) 
  5.     unsigned int        irqs_unhandled;------沒有處理的次數(shù) 
  6. …… 

中斷的生命周期

 

責(zé)任編輯:姜華 來(lái)源: 嵌入式Linux系統(tǒng)開發(fā)
相關(guān)推薦

2021-12-10 08:45:45

Linux GIC Linux 系統(tǒng)

2021-12-08 08:41:31

Linux 中斷子系統(tǒng)Linux 系統(tǒng)

2021-08-03 15:10:26

Linux代碼驅(qū)動(dòng)

2021-08-10 11:30:30

Linux代碼中斷控制器

2017-07-14 14:35:27

Linux中斷系統(tǒng)

2017-07-17 10:34:53

Linux系統(tǒng)休眠設(shè)備中斷

2020-12-29 09:11:33

LinuxLinux內(nèi)核

2009-12-23 16:35:12

Linux系統(tǒng)光驅(qū)軟

2023-09-27 15:41:32

Linux系統(tǒng)

2021-11-02 10:53:56

Linux機(jī)制CPU

2010-08-18 10:52:46

Linux筆試

2021-01-11 12:53:28

線程Java管理

2020-02-18 08:01:55

在家辦公Kakfa知識(shí)點(diǎn)大全

2021-11-30 07:02:10

虛擬化Linux 中斷

2021-12-01 07:02:16

虛擬化LinuxCPU

2023-03-21 18:16:54

2023-05-12 14:14:00

Java線程中斷

2016-05-30 17:31:34

Spring框架

2010-03-09 17:30:08

Linux新手知識(shí)點(diǎn)

2010-08-17 14:56:00

HCNE認(rèn)證
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)