Transcript CH10 銝剜鋆蔭
中斷處置
Interrupts
當周邊裝置事件發生時,為了要通知處理器所發出的
一種特殊電子信號,稱為「中斷」(interrupts)
Device
Driver
註冊(告知)
Kernel
CPU
處理程序(handler)
驅動程式註冊中斷示意圖
1
區域網路設備實作技術及效能分析
PART1.安裝ISR
2
ISR(interrupt service routine)
稱為中斷服務常式或中斷處理程式(interrupt
handler)
當裝置中斷被觸發時,ISR便會執行,而工作就是回應該中斷的
請求(request)。
一般而言,裝置產生中斷時,都是與資料讀寫有關的請求。
ISR便根據中斷的特性,判斷此中斷式要求驅動程式將資料寫入
裝置,或是由裝置讀取資料。
3
Ref:http://www.jollen.org/blog/2008/03/interrupt_handling_semaphore.html
區域網路設備實作技術及效能分析
IRQ(interrupt request)
又稱中斷線路「interrupt channel」
針對每個周邊裝置配置其對應的IRQ
借由IQR來判別周邊裝置所發出的訊號該由哪個ISR進行處理
Device
中斷
信號
Interrupt channel
Kernel
CPU
Interrupt vector table
IRQ與ISR對應表
驅動程式查找IVT示意圖
4
區域網路設備實作技術及效能分析
註冊、釋放ISR
int request_irq(unsigned int irq,
irqreturn_t (*handler)(int,void *,struct pt_regs *),
unsigned long flags,
const char *dev_name,
void *dev_id);
void free_irq(unsigned int irq, void *dev_id)’
回傳值
0 – 核心同意配置irq通道給裝置
負值 – 錯誤碼(例如常見的-EBUSY,表示要求的IRQ已被其他
驅動程式佔用)
註:宣告於linux/interrupt.h
5
補充
區域網路設備實作技術及效能分析
request_irq
request_irq() 引數
unsigned int irq
索取的中斷通道之編號
void (*handler)(int, void *,struct pt_regs*)
要被安裝ISR之函式指標
unsigned long flags
中斷管理選項之位元遮罩
const char *dev_name
代表ISR之字串(/proc/interrupts)
void *dev_id
「共享IRQ」時,釋放IRQ時的裝置辨認之用
「獨佔IRQ」時,可設定為null
6
區域網路設備實作技術及效能分析
request_irq
flag 各個位元
SA_INTERRUPT
設定此位元,表是安裝「快速型」ISR,表示在中
斷失效其間,執行完畢所有ISR。
SA_SHIRQ
此位元表示IRQ是否可不同裝置共享
SA_SAMPLE_RANDOM
可預期信號(週期)–不值得設定此位元
不可預期訊號(隨機)– 設定此位元,有助於系統
"添亂”
補充
7
區域網路設備實作技術及效能分析
安裝ISR的時機
模組初始話時安裝好ISR
發生模組佔用IRQ,即使硬體閒置,IRQ也不能交至其他裝置
裝置首次被開啟時安裝ISR
也就是在硬體被首次開啟之前,通知硬體可以發出中斷之前,
呼叫request_irq
8
區域網路設備實作技術及效能分析
/proc/interrupts
每個IRQ,核心內部各維護一個計數器。每當中斷抵達
CPU,對應的IRQ計數器就會被累增一次。
已安裝IRQ
的中斷
9
CPU處理的 IRQ中斷信
中斷次數 號觸發方式
Linux Kernel集中中斷至
CPU0,以提升快取命中率。
驅動程式為ISR
註冊的名稱
(dev_name)
區域網路設備實作技術及效能分析
/proc/stat
紀錄關於系統活動的幾項低階系統資訊
10
區域網路設備實作技術及效能分析
/proc/stat
user
nice
system
idle
iowait
irq
softirq
從系統啟動開始累計到當前時刻,各別的時間
user –用戶態的CPU時間(單位:jiffies) ,不包含 nice值為負進程
nice
11
nice值為負的進程所佔用的CPU時間(單位:jiffies)
system -核心時間(單位:jiffies)
idle – 除硬碟I/O等待時間以外其它等待時間(單位:jiffies)
iowait - 硬盤IO等待時間(單位:jiffies)
irq –硬中斷時間(單位:jiffies)
softirq - 軟中斷時間(單位:jiffies)
CPU 時間=user+nice+system+idle+iowait+irq+softirq
Ref:http://140.92.88.48/tlog/linux/entry/proc_stat_explained
區域網路設備實作技術及效能分析
/proc/stat
total
irq1 irq2 …
「intr」此行的中斷信息,為系統啟動以來,發生所有的中斷次數
context switch的次數
從系統啟動到現在為止的時間
創建的任務的個數目
當前運行隊列的任務的數目
當前被阻塞的任務的數目
12
區域網路設備實作技術及效能分析
自動探測IRQ通道
簡單說,就是「如何自動的得知裝置IRQ號碼??」
傳統的方式
借由I/O基底位址,求得對應IRQ
例如:x86 第一PC序列埠慣例為0x3F8與IRQ4的組合…
現在硬體裝置幾乎都支援的方法
驅動程式從裝置的I/O port或PIC(Programmable Interrupt
Controller)組態空間讀出一個狀態位元組,便可得知其裝置
IRQ。
13
「自動探測IRQ編碼為驅動程式可用性的基本要求」
區域網路設備實作技術及效能分析
核心輔助探測法
核心提供協助驅動程式探測IRQ號碼的方法
僅適用獨占式中斷(非共享)
unsigned long probe_irq_on(void)
回傳一個位元遮罩,來判斷哪些中斷尚未被使用,驅動程式保留並將其
傳至probe_irq_off(),且試圖啟動中斷。
int probe_irq_off(unsigned long)
關閉裝置中斷,傳入位元遮罩
回傳值
0 – 表示沒有中斷發生
負值 – 發生一次以上中斷(同時觸發多個裝置)
14
區域網路設備實作技術及效能分析
自助探測法
根據對目標裝置的認知,猜測其可能的IRQ,並逐一起
動四個可能的IRQ值,然後檢查是否發生中斷。
無法得知可能的IRQ,則要測試可用的IRQ,必須從
IRQ0~IRQ NR_IRQS-1,逐一測試。
NR_IRQS定義於<asm/irq.h>
15
區域網路設備實作技術及效能分析
ISR的「快」 「慢」之分
能否於下一個中斷來臨之前完成工作,以區隔「快速
型」與「慢速型」的ISR
目前核心版本只留下「快速型ISR」,並以
SA_INTERRUPT旗標註冊ISR。
除非像計時器中斷,允許ISR不受其他中斷干擾,否則
不建議使用SA_INTERRUPT旗標註冊ISR。
16
區域網路設備實作技術及效能分析
PART2.實作ISR
17
ISR
ISR工作在於接待、回饋發出中斷的裝置
ISR執行時間稱為中斷時期(interrupt time)
ISR函式遵守與kernel timer一樣的限制: 補充
不能與user-space傳輸資料(與程序無關)
不能做可能導致休眠的動作(例如呼叫wait_event())
只能以GFP_ATOMIC來配置記憶體
不能鎖定權狀(semaphore)
不能呼叫schedule()
當硬體發生中斷,通常表示user-space程式正在期待事件發
生。
ISR
18
Read()
no
buffer
影像擷取器
區域網路設備實作技術及效能分析
ISR宣告
典型的ISR宣告方式
static irqreturn_t intr_handler(int irq,void *dev_id,struct pt_regs *regs)
irq
irq代表「IRQ編碼」,可記錄在日誌檔裡的資訊,以便除錯之用。
dev_id
驅動程式可借由dev_id傳遞需要在中斷期間針對個別裝置處理的資料
結構;在不用撰寫額外ISR程式就可以用同一個ISR處理同一類裝置
regs
儲存CPU進入中斷模式前的狀態(每個暫存器的值)
19
區域網路設備實作技術及效能分析
ISR 回傳值
ISR回傳值代表中斷事件是否已經處置妥當
回傳值
IRQ_HANDLED - ISR發現它的裝置發出需要注意的中斷
IRQ_NONE – 沒有發現中斷
20
區域網路設備實作技術及效能分析
ISR Sample
static irqreturn_t sample_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct sample_dev *dev = dev_id;
/*現在dev指向正確的硬體*/
/*….*/
}
21
static void sample_dev *dev(struct inode *inode, struct file *filp)
{
struct sample_dev *dev = hwinfo+MINOR(inode->i_rdev);
request_irq(dev->irq, sample_interrupt,
0/*flags*/,
”sample”,
dev/*dev_id*/);
/*…*/
return 0;
}
區域網路設備實作技術及效能分析
抵制一次中斷
驅動程式需暫時抵制特定中斷線路的信號傳達
核心提供三個輔助函式(/linux/interrupts.h)
void disable_irq(int irq);
void disable_irq_nonsync(int irq);
void enable_irq(int irq);
借由改變PIC(Programmable Interrupt Controller)
上暫存器的特定位元,來達到放型或阻擋特定IRQ的效
果。
Device
22
中斷
信息
PIC
CPU
區域網路設備實作技術及效能分析
抵制中斷的風險
呼叫disable_irq()的函式持有ISR所需資源的迴旋鎖,
將造成系統死結。
呼叫disable_irq_nosync()會改變PIC暫存器的位元遮
罩後返回,不管受影響的IRQ當時是否有ISR正在執行,
因此需自行承擔互相競狀況的風險。
23
區域網路設備實作技術及效能分析
壓制所有中斷
2.6版核心提供兩個函式,壓制CPU處理任何中斷訊息
void local_irq_save(unsigned long flags);
void local_irq_disable(void);
local_irq_save()儲存當時中斷狀態存入flags,然後
關閉當時 CPU 的中斷信號受理能力
local_irq_disable()直接關閉當時CPU的中斷受理能
力,而不保存狀態
24
區域網路設備實作技術及效能分析
恢復CPU處理中斷能力
void local_irq_restore(unsigned long flags);
void local_irq_enable(void);
local_irq_restore - 會恢復先前存入flags的旗標回
復給 CPU
local_irq_enable – 無條件回復中斷受理狀態
25
區域網路設備實作技術及效能分析
PART3.ISR的上下半段
26
ISR的上下半段
為解決ISR的長時間工作所設計的解決之道
將ISR分成兩段
前半段(top half) - 指得是呼叫request_irq()時所指定的
interrupt handler函數
1. 儲存裝置相關資料
2. 將 bottom half 排程後執行結束
後半段(bottom half) –由排程器另找安全時間才開始執行(真
正負責回應中斷的工作)。
喚醒正在等待資料的程序、啟動另一次I/O作業…等較為多樣性的工
作
27 http://www.jollen.org/blog/2008/03/interrupt_handling_bottom_half.html
區域網路設備實作技術及效能分析
PART4.中斷共享
28
安裝共享式的IRS
使用request_irq()安裝
Flags引數設定SA_SHIRQ位元
dev_id需為系統上獨一無二的數值,且不能設為NULL
request_irq()返回成功的情況(取得IRQ)
指定的IRQ通道尚未註冊給任何IRS
指定的IRQ通道的所有ISR,皆註冊為共享模式
29
區域網路設備實作技術及效能分析
ISR的執行
核心收到中斷後,觸發每個註冊該IRQ的ISR,而每個
ISR皆需做兩個動作
判斷是否需要處理該次中斷
該次中斷是否來至其他裝置
ldd3->short.c->short_sh_interrupt
Device
(name2)
IRQ6
中斷信號
Kernel
IRQ6-ISR1(name1)
return IRQ_NONE
IRQ6-ISR2(name2)
IRQ6-ISR3(name3)
30
區域網路設備實作技術及效能分析
/proc中的共享式中斷
/proc中的stat與interrupts的差別
/proc/stat對ISR資訊一無所知
/proc/interrupts則知道共用一個IRQ的所有ISRs
已安裝IRQ
的中斷
31
CPU處理的 IRQ中斷信
中斷次數 號觸發方式
驅動程式為ISR
註冊的名稱
(dev_name)
區域網路設備實作技術及效能分析
PART5.中斷驅動式I/O
32
中斷驅動式I/O
CPU與裝置之間資料傳輸可能因任何原因而延遲,因此
驅動程式需提供緩衝區。
中斷驅動式I/O(interrupt-driven I/O) – 緩衝機制
Device
33
ISR
input
Buffer
process
output
區域網路設備實作技術及效能分析
中斷驅動式I/O
中斷驅動資料傳輸成功,要依賴硬體依條件來產生中
斷信號:
資料輸入(周邊→CPU)
裝置必須在資料到達且可供系統處理器擷取的情況下,對CPU發出中
斷信號
資料輸出(CPU→周邊)
裝置必須在準備好接收新資料或回報已成功傳輸出資料時,對CPU發
出中斷信號
ldd3->shortprint.c->shortp_write()
ldd3->shortprint.c->shortp_start_output()
ldd3->shortprint.c->shortp_start_output()
34
區域網路設備實作技術及效能分析
Thank you for listening
35
區域網路設備實作技術及效能分析
2.6.xx…request_irq
/*…/include/linux/interrupts*/
static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
36
/*…/kernel/irq/manage.c*/
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
{
struct irqaction *action;
struct irq_desc *desc;
int retval;
….
}
Back
區域網路設備實作技術及效能分析
request_irq flag
從Linux Kernel 2.6.19開始有些中斷處理介面改掉
SA_INTERRUPT改成IRQF_DISABLE,
其他的flag前面的"SA_”字樣改成"IRQF”,這樣才能
正確對應到header file內的定義。
譬如 :SA_TIMER -> IRQF_TIMER
/*…/include/linux/interrupts*/
#define IRQF_DISABLED
0x00000020
#define IRQF_SAMPLE_RANDOM
0x00000040
#define IRQF_SHARED
0x00000080
#define IRQF_PROBE_SHARED
0x00000100
#define __IRQF_TIMER
0x00000200
…
37
Ref:http://www.wretch.cc/blog/kerker2001
Back
區域網路設備實作技術及效能分析
ISR補充
Interrupt handler 執行於 interrupt mode,並無
process context資訊,因此,在 interrupt mode 下
執行的執行碼需注意以下 3 點:
由於沒有 process context 的關係,因此無法存取 user
space。
2. 無法存取 current 巨集。current 巨集是一個指向自己的
kernel symbol。
3. 不能呼叫 scheduler 做排程,也不能做 sleeping waiting。
由於 down/up 的 semaphore API 是 sleeping waiting 的
版本,因此在 interrupt mode 必須改用 spinlock,
spinlock 是以 busy waiting 的方式做 wait operation。
1.
38
Ref:http://www.jollen.org/blog/2008/03/interrupt_handling_1.html
區域網路設備實作技術及效能分析
interrupt handler 實作原則
在 interrupt handler 裡,叫醒真正負責此中斷的 task 後
立即結束執行。
2. Interrupt handler 應儘量執行最少的程式碼。
3. Interrupt handler 若執行過久,會造成中斷的關閉時間過
長,因此可能會遺失緊接著產生的中斷請求。
4. 若 interrupt handler 裡有過長的計算動作或執行過久的程
式碼,則應使用 tasklet 或 task queue 將該段程式碼做排
程,留待其它時間再執行。如此便可避免interrupt handler
執行時間過久。
1.
39
Ref: http://www.jollen.org/blog/2008/03/interrupt_handling_semaphore.html
Back
區域網路設備實作技術及效能分析