我正在开展一个项目,我根据收到的键盘中断做了一些动作。所以我注册了键盘中断并将中断标记为共享。但我的计划并没有按预期工作。为了调试这个问题,我编写了一个小程序,它只注册键盘中断,并在收到键盘中断时向内核输出一些消息。但是我发现当中断率很高时会丢失很多来自键盘的中断。例如,在下面的示例代码中,当注意到' a'时,我会向内核注册中断和输出消息。被压了。从计数器值开始,中断总数小于键盘产生的实际中断数。我通过将按键回显到终端并计算回显给终端的号码来发现这一点。因此,例如,如果终端上有350个回显,则计数将仅为300-320左右。同样适用于更多的中断。中断次数越多,错过的中断越多,但在所有情况下,错过的中断百分比似乎几乎相等。有人可以解释一下这种行为的原因是什么?提前致谢。以下是源代码。
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <asm/io.h>
/*
The keyboard ISR
*/
irq_handler_t irq_handler (int irq, void *dev_id, struct pt_regs *regs)
{
static int count = 0;
static unsigned char scancode;
scancode = inb (0x60);
if (0x1E == scancode)
{
count++;
printk ("\nKeyboard key 'a' pressed !");
}
return (irq_handler_t) IRQ_HANDLED;
}
/*
Register IRQ handler
*/
int init_module ()
{
return request_irq (1, (irq_handler_t) irq_handler, IRQF_SHARED, "kbd_irq_handler", (void *)(irq_handler));
}
MODULE_LICENSE ("GPL");
答案 0 :(得分:1)
你可以尝试使用工作队列作为下半部分,因为如果irq handler [Top]需要时间来完成,那么中断可能会被遗漏。
最好使用workqueue进行非时间关键处理。
您的代码应该像
static unsigned char scancode;
irq_handler_t irq_handler (int irq, void *dev_id, struct pt_regs *regs)
{
scancode = inb (0x60);
schedule_delayed_work(work_struct);//in this function pointer is passed
return (irq_handler_t) IRQ_HANDLED;
}
func()
{
if (0x1E == scancode)
{
count++;
printk ("\nKeyboard key 'a' pressed !");
}
}
您还可以从硬件角度检查键盘控制器数据表中断之间的最小时间间隔,然后检查中断执行时间,看中断处理程序执行时间应小于hw中断生成时间。
或者您也可以在考虑时序,系统负载后维护事件缓冲区。
答案 1 :(得分:0)
答案 2 :(得分:0)
我在错过中断的不同驱动程序中看到了这个问题。 我的驱动程序正在使用快速IRQ处理程序,只将作业分派到下半部分工作队列。
我发现当IRQ处理程序正在执行时,内核可能不会为同一个处理程序注册新的中断。然而,我没有看到一致的行为。它很受欢迎。
我通过使IRQ处理程序花费很长时间(&gt; = 10秒)并以一秒间隔发出中断来调试此操作。在执行IRQ处理程序时发出的10个或更多中断中,只有7个或8个被注册。
我的止损解决方案是在设备固件中添加一个看门狗,如果它在主机上看到未提供服务的缓冲区,则会重新发出中断,但我正在寻找更好,更确定的解决方案。