Linux中斷管理


CPU和外設之間的交互,或CPU通過輪詢機制查詢,或外設通過中斷機制主動上報。

對大部分外設中斷比輪詢效率高,但比如網卡驅動采取輪詢比中斷效率高。

這里重點關注ARM+Linux組合下中斷管理,從底層硬件GIC+CPU,到Linux內核通用部分處理,再到GIC驅動以及中斷注冊,最后是中斷下半部軟終端、tasklet、workqueue,包括線程化部分。

所以按照從硬件到軟件,軟件從底層到上層的框架去介紹。

 

0. 目錄

Linux中斷管理

Linux中斷管理 (1)Linux中斷管理機制

Linux中斷管理 (2)軟中斷和tasklet

Linux中斷管理 (3)workqueue工作隊列

 

1. 思考問答

  • 發生硬件中斷后,ARM處理器做了哪些事情?

 SoC內部中斷控制器會感知到中斷信號,中斷控制器里的仲裁單元(Distributor)會在眾多CUP核心中選擇一個,並把該中斷分發給CPU核心。

GIC控制器和CPU核心之間通過一個nIRQ信號來通知CPU。

CPU核心感知到中斷發生之后,硬件會自動做如下一些事情:

  • 保存中斷發生時CPSR寄存器的內容到SPSR_irq寄存器中
  • 修改CPSR寄存器,讓CPU進入處理器模式中的IRQ模式,即CPSR寄存器中的M域設置為IRQ Mode
  • 硬件自動關閉中斷IRQ或FIQ,即CPSR中的IRQ位或FIQ位置1
  • 保存返回地址到LR_irq寄存器中
  • 硬件自動跳轉到中斷向量表的IRQ向量中
  • 硬件中斷號和Linux內核的IRQ中斷號是如何映射的?

 硬件中斷號的映射是在系統啟動過程中接卸DTS,然后經由irq_domain_alloc_irqs()完成映射到Linux中斷號。

中斷發生后,根據硬件中斷號經由irq_find_mapping()找到Linux軟中斷號。

  • 一個硬件中斷發生后,Linux內核如何響應並處理該中斷?

一個硬件發生后,LInux軟件的起點是中斷向量表vector_irq

vector_irq根據中斷發生時狀態決定是進入用戶空間__irq_svc還是內核空間__irq_svc

兩者主要工作都交給irq_handler處理,irq_handler調用中斷控制器處理函數gic_handle_irq()。

gic_handle_irq()根據讀取到的硬件中斷號轉換成Linux中斷號,然后進行特定中斷處理。

 

從中斷返回時,還需要實現如下兩個操作:

  • 從SPSR_irq寄存器中恢復數據到CPSR中
  • 從LR_irq中回復內容到PC中,從而返回到中斷點的下一個指令處執行。
  • 為什么說中斷上下文不能執行睡眠操作?

所謂的睡眠,就是調用schedule()讓出CPU,調度器選擇另外一個進程繼續執行,這個過程涉及進程棧空間的切換。

如果中斷上下文中調用schedule(),此時獲取的struct thread_info數據結構是發生中斷是該進程棧信息,而不是中斷上下文調用schedule()時任何信息。

這就導致再也無法返回中斷上下文中調用schedule()的地方。

 

另一個原因是,中斷上下文處於關中斷中,需要發送一個EOI通知GIC中斷處理結束,GIC和CPU Interface才會進入下一次中斷處理。如果中途schedule(),那么整個系統的中斷都會被屏蔽掉。

  • 軟中斷的回調函數執行過程中是否允許響應本地中斷?

軟中斷回調函數執行處於開中斷環境下,所以允許響應本地中斷。

具體參考__do_softirq(),在執行h->action()前打開本地中斷,完成后關閉中斷。

  • 同一類型的軟中斷是否允許多個CPU並行執行?

 同一類型的軟中斷可以在多個CUP並發執行,因為軟中斷處理函數是可重入的,自身對數據進行了保護。

  • 軟中斷上下文包括哪幾種情況?

中斷上下文包括硬中斷上下文和軟中斷上下文,當然也包括NMI上下文。

軟中斷上下文包括三部分:

一是在下半部執行的軟中斷處理包括tasklet,調用過程是irq_exit()->invoke_softirq();

二是ksoftirqd內核線程執行的軟中斷,比如強制中斷線程化force_threads,或者軟中斷執行時間太長僅為喚醒ksoftirqd內核線程;

三是進程上下文中調用local_bh_enable()時也會去執行軟中斷處理,調用過程是local_bh_enable()->do_softirq()。

一屬於傳統意義的中斷上下文,二、三運行在進程上下文中,但三者統稱為軟中斷上下文。

  • 軟中斷上下文和進程上下文哪個優先級高?為什么?

軟中斷上下文優先級高於進程上下文,因此軟中斷包括tasklet總是搶占進程的運行。參見irq_exit()退出中斷時優先執行softirq。

比如當進程A在運行時發生中斷,在中斷返回時如果不處於中斷上下文且有pending的softirq時,優先執行軟中斷包括tasklet。

然后采取檢查是否有高優先級任務需要簽章中斷點的進程。

 

這樣導致的危害是:如果執行軟中斷或者tasklet事件過長,那么高優先級任務就長時間得不到運行,嚴重影響系統的實時性。

這也是RT補丁強制將softirq處理函數線程化的原因。

 

 

  • 是否允許同一個tasklet在多個CPU上並行執行?

 不允許同一個tasklet同時在多個CPU並發執行,taskelt必須固定在一個CPU上串行執行。

因為tasket被掛入到per-cpu的taskelt_vec中,並且設置TASKLET_STATE_SCHED標志位,那么只能由該CPU來執行。

直到執行完畢並清除了TASKLET_STATE_SCHED后,其它CPU才有機會執行。

  • workqueue試運行在中斷上下文,還是進程上下文?其回調函數允許睡眠嗎?

 

  • 舊版本(Linux 2.6.25)的workqueue機制在實際過程中遇到了哪些問題和挑戰?

 

  • CMWQ機制如何動態管理工作線程池的線程呢?

 

  • 如果有多個work掛入一個工作線程中執行,當某個work的回調函數執行了阻塞操作,那么剩下的work該怎么辦?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM