在大型机上,我们有一个中断控制器(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最初是谁设置的?传记?操作系统?
4)谁负责IRQ和中断向量中的偏移量的匹配?
5)可以共享IRQS。那件事怎么可能?主板上有硬件通道,将设备连接到中断控制器。如何将to通道配置为相同的中断?必须有一个表,上面写着通道2和通道3处理IRQ15,例如,这个表驻留在哪里,它是如何调用的?
发布于 2012-06-04 01:57:42
关于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)当你处理(irq,request_irq )时。系统实际上不会在IVT或IDT中对条目0进行编程。但条目N+ irq.其中N是该CPU上支持的错误处理程序或通用异常的数量。详细信息因系统而异。
b)如果您错误地请求了另一个驱动程序使用的irq,会发生什么情况。你得到一个错误,IDT不是用你的处理程序编程的。
注意: IDT是中断描述符表。
3) IRQ最初是谁设置的?传记?操作系统?
首先是Bios,然后是OS。但是也有一些操作系统,例如MS-DOS,它不会重新编程BIOS设置的IVT。更复杂的现代操作系统,如Windows或Linux,不想依赖特定的bios功能,它们重新编写了IDT程序。但是,只有在操作系统出现的时候,bios才会开始这样做。
4)谁负责IRQ和中断向量中的偏移量的匹配?
我真的不明白你的意思。流程是这样的。首先,为您的设备分配一个irq编号,然后使用该irq编号为其注册一个处理程序。如果您使用错误的irq编号,然后在您的设备上启用中断,系统将崩溃。因为处理程序注册了错误的irq编号。
5)可以共享IRQS。那件事怎么可能?主板上有硬件通道,将设备连接到中断控制器。如何将to通道配置为相同的中断?必须有一个表,上面写着通道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";
}
}https://stackoverflow.com/questions/10869549
复制相似问题