1 / 40

中斷處置

中斷處置. Interrupts. 當周邊裝置事件發生時,為了要通知處理器所發出的一種特殊電子信號,稱為「中斷」 (interrupts). 註冊 ( 告知 ). Device. Driver. Kernel. CPU. 處理程序 (handler). 驅動程式註冊中斷示意圖. PART1. 安裝 ISR. ISR(interrupt service routine). 稱為中斷服務常式或中斷處理程式 (interrupt handler) 當裝置中斷被觸發時, ISR 便會執行,而工作就是回應該中斷的請求 (request) 。

lieu
Download Presentation

中斷處置

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 中斷處置

  2. Interrupts • 當周邊裝置事件發生時,為了要通知處理器所發出的一種特殊電子信號,稱為「中斷」(interrupts) 註冊(告知) Device Driver Kernel CPU 處理程序(handler) 驅動程式註冊中斷示意圖

  3. PART1.安裝ISR

  4. ISR(interrupt service routine) • 稱為中斷服務常式或中斷處理程式(interrupt handler) • 當裝置中斷被觸發時,ISR便會執行,而工作就是回應該中斷的請求(request)。 • 一般而言,裝置產生中斷時,都是與資料讀寫有關的請求。 • ISR便根據中斷的特性,判斷此中斷式要求驅動程式將資料寫入裝置,或是由裝置讀取資料。 Ref:http://www.jollen.org/blog/2008/03/interrupt_handling_semaphore.html

  5. IRQ(interrupt request) • 又稱中斷線路「interrupt channel」 • 針對每個周邊裝置配置其對應的IRQ • 借由IQR來判別周邊裝置所發出的訊號該由哪個ISR進行處理 中斷 信號 Device Kernel CPU Interrupt vector table Interrupt channel IRQ與ISR對應表 驅動程式查找IVT示意圖

  6. 註冊、釋放ISR intrequest_irq(unsigned intirq, irqreturn_t (*handler)(int,void *,structpt_regs *), unsigned long flags, const char *dev_name, void *dev_id); • 回傳值 • 0– 核心同意配置irq通道給裝置 • 負值 – 錯誤碼(例如常見的-EBUSY,表示要求的IRQ已被其他驅動程式佔用) void free_irq(unsigned intirq, void *dev_id)’ • 註:宣告於linux/interrupt.h 補充

  7. request_irq • request_irq() 引數 unsigned intirq 索取的中斷通道之編號 void (*handler)(int, void *,structpt_regs*) 要被安裝ISR之函式指標 unsigned long flags 中斷管理選項之位元遮罩 const char *dev_name 代表ISR之字串(/proc/interrupts) void *dev_id 「共享IRQ」時,釋放IRQ時的裝置辨認之用 「獨佔IRQ」時,可設定為null

  8. request_irq • flag 各個位元 SA_INTERRUPT 設定此位元,表是安裝「快速型」ISR,表示在中斷失效其間,執行完畢所有ISR。 SA_SHIRQ 此位元表示IRQ是否可不同裝置共享 SA_SAMPLE_RANDOM可預期信號(週期)–不值得設定此位元 不可預期訊號(隨機)– 設定此位元,有助於系統 "添亂” 補充

  9. 安裝ISR的時機 • 模組初始話時安裝好ISR • 發生模組佔用IRQ,即使硬體閒置,IRQ也不能交至其他裝置 • 裝置首次被開啟時安裝ISR • 也就是在硬體被首次開啟之前,通知硬體可以發出中斷之前,呼叫request_irq

  10. /proc/interrupts • 每個IRQ,核心內部各維護一個計數器。每當中斷抵達CPU,對應的IRQ計數器就會被累增一次。 已安裝IRQ 的中斷 CPU處理的中斷次數 IRQ中斷信號觸發方式 驅動程式為ISR註冊的名稱(dev_name) LinuxKernel集中中斷至CPU0,以提升快取命中率。

  11. /proc/stat • 紀錄關於系統活動的幾項低階系統資訊

  12. /proc/stat • 從系統啟動開始累計到當前時刻,各別的時間 • user –用戶態的CPU時間(單位:jiffies) ,不包含 nice值為負進程 • nice - nice值為負的進程所佔用的CPU時間(單位:jiffies) • system -核心時間(單位:jiffies) • idle – 除硬碟I/O等待時間以外其它等待時間(單位:jiffies) • iowait - 硬盤IO等待時間(單位:jiffies) • irq –硬中斷時間(單位:jiffies) • softirq - 軟中斷時間(單位:jiffies) • CPU 時間=user+nice+system+idle+iowait+irq+softirq user nice system idle iowait irq softirq Ref:http://140.92.88.48/tlog/linux/entry/proc_stat_explained

  13. /proc/stat • 「intr」此行的中斷信息,為系統啟動以來,發生所有的中斷次數 total … irq1 irq2 context switch的次數 從系統啟動到現在為止的時間 創建的任務的個數目 當前運行隊列的任務的數目 當前被阻塞的任務的數目

  14. 自動探測IRQ通道 • 簡單說,就是「如何自動的得知裝置IRQ號碼??」 • 傳統的方式 • 借由I/O基底位址,求得對應IRQ 例如:x86 第一PC序列埠慣例為0x3F8與IRQ4的組合… • 現在硬體裝置幾乎都支援的方法 • 驅動程式從裝置的I/O port或PIC(Programmable Interrupt Controller)組態空間讀出一個狀態位元組,便可得知其裝置IRQ。 • 「自動探測IRQ編碼為驅動程式可用性的基本要求」

  15. 核心輔助探測法 • 核心提供協助驅動程式探測IRQ號碼的方法 • 僅適用獨占式中斷(非共享) unsigned long probe_irq_on(void) 回傳一個位元遮罩,來判斷哪些中斷尚未被使用,驅動程式保留並將其 傳至probe_irq_off(),且試圖啟動中斷。 intprobe_irq_off(unsigned long) 關閉裝置中斷,傳入位元遮罩 回傳值 0 – 表示沒有中斷發生 負值 – 發生一次以上中斷(同時觸發多個裝置)

  16. 自助探測法 • 根據對目標裝置的認知,猜測其可能的IRQ,並逐一起動四個可能的IRQ值,然後檢查是否發生中斷。 • 無法得知可能的IRQ,則要測試可用的IRQ,必須從IRQ0~IRQNR_IRQS-1,逐一測試。 • NR_IRQS定義於<asm/irq.h>

  17. ISR的「快」 「慢」之分 • 能否於下一個中斷來臨之前完成工作,以區隔「快速型」與「慢速型」的ISR • 目前核心版本只留下「快速型ISR」,並以SA_INTERRUPT旗標註冊ISR。 • 除非像計時器中斷,允許ISR不受其他中斷干擾,否則不建議使用SA_INTERRUPT旗標註冊ISR。

  18. PART2.實作ISR

  19. ISR • ISR工作在於接待、回饋發出中斷的裝置 • ISR執行時間稱為中斷時期(interrupt time) • ISR函式遵守與kernel timer一樣的限制: • 不能與user-space傳輸資料(與程序無關) • 不能做可能導致休眠的動作(例如呼叫wait_event()) • 只能以GFP_ATOMIC來配置記憶體 • 不能鎖定權狀(semaphore) • 不能呼叫schedule() • 當硬體發生中斷,通常表示user-space程式正在期待事件發生。 補充 ISR 影像擷取器 no Read() buffer

  20. ISR宣告 • 典型的ISR宣告方式 static irqreturn_tintr_handler(intirq,void *dev_id,structpt_regs *regs) • irq irq代表「IRQ編碼」,可記錄在日誌檔裡的資訊,以便除錯之用。 • dev_id 驅動程式可借由dev_id傳遞需要在中斷期間針對個別裝置處理的資料結構;在不用撰寫額外ISR程式就可以用同一個ISR處理同一類裝置 • regs 儲存CPU進入中斷模式前的狀態(每個暫存器的值)

  21. ISR 回傳值 • ISR回傳值代表中斷事件是否已經處置妥當 • 回傳值 IRQ_HANDLED-ISR發現它的裝置發出需要注意的中斷 IRQ_NONE – 沒有發現中斷

  22. ISRSample

  23. 抵制一次中斷 • 驅動程式需暫時抵制特定中斷線路的信號傳達 • 核心提供三個輔助函式(/linux/interrupts.h) void disable_irq(intirq); void disable_irq_nonsync(intirq); void enable_irq(intirq); • 借由改變PIC(Programmable Interrupt Controller)上暫存器的特定位元,來達到放型或阻擋特定IRQ的效果。 中斷 信息 Device PIC CPU

  24. 抵制中斷的風險 • 呼叫disable_irq()的函式持有ISR所需資源的迴旋鎖,將造成系統死結。 • 呼叫disable_irq_nosync()會改變PIC暫存器的位元遮罩後返回,不管受影響的IRQ當時是否有ISR正在執行,因此需自行承擔互相競狀況的風險。

  25. 壓制所有中斷 • 2.6版核心提供兩個函式,壓制CPU處理任何中斷訊息 void local_irq_save(unsigned long flags); void local_irq_disable(void); • local_irq_save()儲存當時中斷狀態存入flags,然後關閉當時 CPU 的中斷信號受理能力 • local_irq_disable()直接關閉當時CPU的中斷受理能力,而不保存狀態

  26. 恢復CPU處理中斷能力 void local_irq_restore(unsigned long flags); void local_irq_enable(void); • local_irq_restore - 會恢復先前存入flags的旗標回復給 CPU • local_irq_enable – 無條件回復中斷受理狀態

  27. PART3.ISR的上下半段

  28. ISR的上下半段 • 為解決ISR的長時間工作所設計的解決之道 • 將ISR分成兩段 • 前半段(top half) - 指得是呼叫request_irq()時所指定的interrupt handler函數 • 儲存裝置相關資料 • 將 bottom half 排程後執行結束 • 後半段(bottom half) –由排程器另找安全時間才開始執行(真正負責回應中斷的工作)。 • 喚醒正在等待資料的程序、啟動另一次I/O作業…等較為多樣性的工作 http://www.jollen.org/blog/2008/03/interrupt_handling_bottom_half.html

  29. PART4.中斷共享

  30. 安裝共享式的IRS • 使用request_irq()安裝 • Flags引數設定SA_SHIRQ位元 • dev_id需為系統上獨一無二的數值,且不能設為NULL • request_irq()返回成功的情況(取得IRQ) • 指定的IRQ通道尚未註冊給任何IRS • 指定的IRQ通道的所有ISR,皆註冊為共享模式

  31. ISR的執行 • 核心收到中斷後,觸發每個註冊該IRQ的ISR,而每個ISR皆需做兩個動作 • 判斷是否需要處理該次中斷 • 該次中斷是否來至其他裝置 • ldd3->short.c->short_sh_interrupt return IRQ_NONE Device (name2) IRQ6 中斷信號 Kernel

  32. /proc中的共享式中斷 • /proc中的stat與interrupts的差別 • /proc/stat對ISR資訊一無所知 • /proc/interrupts則知道共用一個IRQ的所有ISRs 已安裝IRQ 的中斷 CPU處理的中斷次數 IRQ中斷信號觸發方式 驅動程式為ISR註冊的名稱(dev_name)

  33. PART5.中斷驅動式I/O

  34. 中斷驅動式I/O • CPU與裝置之間資料傳輸可能因任何原因而延遲,因此驅動程式需提供緩衝區。 • 中斷驅動式I/O(interrupt-driven I/O) – 緩衝機制 ISR input process output Device Buffer

  35. 中斷驅動式I/O • 中斷驅動資料傳輸成功,要依賴硬體依條件來產生中斷信號: • 資料輸入(周邊→CPU) • 裝置必須在資料到達且可供系統處理器擷取的情況下,對CPU發出中斷信號 • 資料輸出(CPU→周邊) • 裝置必須在準備好接收新資料或回報已成功傳輸出資料時,對CPU發出中斷信號 • ldd3->shortprint.c->shortp_write() • ldd3->shortprint.c->shortp_start_output() • ldd3->shortprint.c->shortp_start_output()

  36. Thank you for listening

  37. 2.6.xx…request_irq Back

  38. request_irq flag • 從Linux Kernel 2.6.19開始有些中斷處理介面改掉 • SA_INTERRUPT改成IRQF_DISABLE, • 其他的flag前面的"SA_”字樣改成"IRQF”,這樣才能正確對應到header file內的定義。 • 譬如 :SA_TIMER -> IRQF_TIMER Back Ref:http://www.wretch.cc/blog/kerker2001

  39. ISR補充 • Interrupt handler 執行於 interrupt mode,並無 process context資訊,因此,在 interrupt mode 下執行的執行碼需注意以下 3 點: • 由於沒有 process context 的關係,因此無法存取 user space。 • 無法存取 current 巨集。current 巨集是一個指向自己的 kernel symbol。 • 不能呼叫 scheduler 做排程,也不能做 sleeping waiting。由於 down/up 的 semaphore API 是 sleeping waiting 的版本,因此在 interrupt mode 必須改用 spinlock,spinlock是以 busy waiting 的方式做 wait operation。 Ref:http://www.jollen.org/blog/2008/03/interrupt_handling_1.html

  40. interrupt handler 實作原則 • 在 interrupt handler 裡,叫醒真正負責此中斷的 task 後立即結束執行。 • Interrupt handler 應儘量執行最少的程式碼。 • Interrupt handler 若執行過久,會造成中斷的關閉時間過長,因此可能會遺失緊接著產生的中斷請求。 • 若 interrupt handler 裡有過長的計算動作或執行過久的程式碼,則應使用 tasklet或 task queue 將該段程式碼做排程,留待其它時間再執行。如此便可避免interrupt handler執行時間過久。 Back Ref: http://www.jollen.org/blog/2008/03/interrupt_handling_semaphore.html

More Related