fli*_*liX 15 linux operating-system interrupt
在mainbord上我们有一个中断控制器(IRC),它作为设备之间的多路复用器,可以引发中断和CPU:
|--------|
|-----------| | |
-(0)------| IRC _____|______| CPU |
-(...)----| ____/ | | |
-(15)-----|/ | |--------|
|-----------|
Run Code Online (Sandbox Code Playgroud)
每个设备都与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,例如该表位于何处以及如何调用?
Sau*_*abh 20
关于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";
}
}
Run Code Online (Sandbox Code Playgroud)