[英]Interrupt handling (Linux/General)
在mainbord上我們有一個中斷控制器(IRC),它作為設備之間的多路復用器,可以引發中斷和CPU:
|--------|
|-----------| | |
-(0)------| IRC _____|______| CPU |
-(...)----| ____/ | | |
-(15)-----|/ | |--------|
|-----------|
每個設備都與IRQ(左側的數字)相關聯。 每次執行后,CPU都會檢測到中斷請求線。 如果檢測到信號,將執行狀態保存,並且CPU加載中斷處理程序例程,該例程可以在位於存儲器中固定地址的中斷向量中找到。 據我所知,IRQ的數量和中斷向量中的向量編號不一樣,因為我有例如我的網卡注冊到IRQ 8.在Intel Pentium處理器上,這將指向一個使用的例程發出一個錯誤信號,因此必須有一個指向正確處理程序的映射。
問題:
1)如果我編寫設備驅動程序並為其注冊IRQ X. 系統從哪里知道應該處理哪個設備? 例如,我可以使用IRQ編號為10的request_irq(),但系統如何知道處理程序應該用於鼠標或鍵盤,或者用於編寫驅動程序的任何內容?
2)中斷向量看起來如何? 我的意思是如果我將IRQ 10用於我的設備,這將覆蓋用於表中錯誤處理的標准處理程序(根據Silberschatz(操作系統概念),第一個可用的是32)。
3)誰最初設置了IRQ? Bios? 操作系統?
4)誰負責IRQ與中斷向量中的偏移的匹配?
5)可以共享IRQS。 怎么可能? 主板上有硬件通道,用於將設備連接到中斷控制器。 如何將通道配置為相同的中斷? 必須有一個表格,表示第2道和第3道處理IRQ15,例如該表位於何處以及如何調用?
關於linux內核的答案。 應該適用於大多數其他操作系統。
1)如果我編寫設備驅動程序並為其注冊IRQ X. 系統從哪里知道應該處理哪個設備? 例如,我可以使用IRQ編號為10的request_irq(),但系統如何知道處理程序應該用於鼠標或鍵盤,或者用於編寫驅動程序的任何內容?
沒有一個答案。 例如,如果這是一個自定義嵌入式系統,硬件設計師將告訴驅動程序編寫者“我將把設備x路由到irq y”。 為了更大的靈活性,例如對於通常使用PCI協議的網卡。 有硬件/固件級仲裁,用於在檢測到新設備時為其分配irq編號。 然后將其寫入PCI配置寄存器之一。 驅動程序首先讀取此設備寄存器,然后為該特定irq注冊其中斷處理程序。 其他協議將有類似的機制。
你可以做的是在內核代碼中查找對request_irq的調用以及驅動程序如何獲得irq值。 每種類型的駕駛員都會有所不同。
因此,這個問題的答案是,系統不知道。 硬件設計者或硬件協議將此信息提供給驅動程序編寫者。 然后驅動程序編寫器注冊該特定irq的處理程序,告訴系統如果你看到irq會怎么做。
2)中斷向量看起來如何? 我的意思是如果我將IRQ 10用於我的設備,這將覆蓋用於表中錯誤處理的標准處理程序(根據Silberschatz(操作系統概念),第一個可用的是32)。
好問題。 它有兩個部分。
a)當你request_irq(irq,handler)時。 系統確實沒有在IVT或IDT中編程0。 但是進入N + irq。 其中N是該CPU支持的錯誤處理程序或通用異常的數量。 細節因系統而異。
b)如果您錯誤地請求另一個驅動程序使用的irq會發生什么。 您收到錯誤,IDT未使用您的處理程序進行編程。
注意:IDT是中斷描述符表。
3)誰最初設置了IRQ? Bios? 操作系統?
首先是Bios,然后是OS。 但是有一些操作系統,比如MS-DOS,它不會重新編程BIOS設置的IVT。 更復雜的現代操作系統如Windows或Linux不希望依賴特定的BIOS功能,並且他們重新編程IDT。 但是,只有在OS進入畫面之后,bios才能做到這一點。
4)誰負責IRQ與中斷向量中的偏移的匹配?
我真的不清楚你的意思。 流程是這樣的。 首先為您的設備分配一個irq編號,然后使用該irq編號為其注冊一個處理程序。 如果使用錯誤的irq編號,然后在設備上啟用中斷,系統將崩潰。 因為處理程序是從錯誤的irq編號注冊的。
5)可以共享IRQS。 怎么可能? 主板上有硬件通道,用於將設備連接到中斷控制器。 如何將通道配置為相同的中斷? 必須有一個表格,表示第2道和第3道處理IRQ15,例如該表位於何處以及如何調用?
這個問題問得好。 額外的表不是如何在內核中解決的。 而是對於每個共享的irq,處理程序保存在函數指針的鏈接列表中。 內核循環遍歷所有處理程序並一個接一個地調用它們,直到其中一個處理程序將中斷聲明為自己的中斷。
The code looks like this:
driver1:
d1_int_handler:
if (device_interrupted()) <------------- This reads the hardware
{
do_interrupt_handling();
return MY_INTERRUPT;
}else {
return NOT_MY_INTERRUPT;
}
driver2:
Similar to driver 1
kernel:
do_irq(irq n)
{
if (shared_irq(n))
{
irq_chain = get_chain(n);
while(irq_chain)
{
if ((ret = irq_chain->handler()) == MY_INTERRUPT)
break;
irq_chain = irq_chain->next;
}
if (ret != MY_INTERRUPT)
error "None of the drivers accepted the interrupt";
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.