简体   繁体   English

内核模块中缺少键盘中断

[英]keyboard interrupt missed in kernel module

I was working on a project where I was doing some action based on the keyboard interrupt received.我正在做一个项目,我正在根据收到的键盘中断执行一些操作。 So I registered for the keyboard interrupt and mark the interrupt as shared.所以我注册了键盘中断并将中断标记为共享。 But my program wasnt working as it should.但是我的程序没有正常工作。 To debug the issue, I wrote a small program that just registers for the keyboard interrupt and outputs some message to kernel when interrupt from keyboard is received.为了调试这个问题,我编写了一个小程序,它只注册键盘中断,并在收到键盘中断时向内核输出一些消息。 But I found out a lot of interrupts from keyboard are missed when interrupt rate is high.但是我发现当中断率很高时,很多来自键盘的中断都被错过了。 For example, in the sample code below, I register for the interrupt and output message to kernel when 'a' is pressed.例如,在下面的示例代码中,当按下“a”时,我注册了中断并向内核输出消息。 From the counter value, the total number of interrupts are less than the actual number of interrupts geenrated by keyboard.从计数器值来看,总的中断次数小于键盘实际产生的中断次数。 I found this out by echoing the keypress to a terminal and counting the number of a's echoed to the terminal.我通过将按键回显到终端并计算回显到终端的 a 的数量来发现这一点。 So for example if there are 350 echoed a's on the terminal, the count will only be around 300-320.因此,例如,如果终端上有 350 个回显 a,则计数只会在 300-320 左右。 Same goes for higher number of interrupts.更高数量的中断也是如此。 The larger the number of interrupts, the more interrupts are missed but the percentage of interrupts missed seems to be nearly equal in all cases.中断数量越大,错过的中断就越多,但在所有情况下,错过的中断百分比似乎几乎相等。 Can someone please explain what is the reason for this behaviour?有人可以解释这种行为的原因是什么吗? Thanks in advance.提前致谢。 Below is source code.下面是源代码。

#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");

Can you try using workqueues as bottom half because if irq handler[Top] is taking time to complete in that case interrupts can be missed.您可以尝试使用工作队列作为下半部分,因为如果 irq handler[Top] 需要时间来完成,在这种情况下可能会错过中断。

Its better to use workqueue for doing non time critical processing.最好使用工作队列进行非时间关键处理。

You code should be like你的代码应该像

    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 !");
       }
    }

Also you can check the keyboard controller data sheet for minimum time interval between interrupts from hardware perspective and then check the interrupt execution time to see interrupt handler execution time should be less than than hw interrupt generation time.您也可以从硬件角度检查键盘控制器数据表中中断之间的最小时间间隔,然后检查中断执行时间以查看中断处理程序执行时间应小于硬件中断生成时间。

Or you can also maintain event buffer after considering timing,system load.或者您也可以在考虑时序、系统负载后维护事件缓冲区。

From here :这里

The logging code already tries to mitigate this problem by detecting and suppressing streams of identical messages.日志代码已经尝试通过检测和抑制相同消息流来缓解这个问题。

Using printk for stream of identical messages - bad idea.printk用于相同的消息流 - 坏主意。

I've seen exactly this problem in a different driver that missed interrupts.我在另一个错过中断的驱动程序中看到了这个问题。 My driver is using a fast IRQ handler that just dispatches jobs to a bottom-half work-queue.我的驱动程序正在使用一个快速 IRQ 处理程序,它只是将作业分派到下半部工作队列。

What I found is that when the IRQ handler is executing, the kernel may not register new interrupts for the same handler.我发现当 IRQ 处理程序正在执行时,内核可能不会为同一个处理程序注册新的中断。 I did not see a consistent behavior on this however.然而,我没有看到一致的行为。 It was hit and miss.它受到了打击和错过。

I've debugged this by making the IRQ handler take a really long time (>= 10s) and issuing interrupts at one second interval.我通过使 IRQ 处理程序花费很长时间(> = 10 秒)并以一秒为间隔发出中断来对此进行调试。 Out of 10 or more interrupts issued when the IRQ handler was executing, only 7 or 8 were registered.在 IRQ 处理程序执行时发出的 10 个或更多中断中,只有 7 个或 8 个被注册。

My stop-gap solution was to add a watch-dog to the device firmware to reissue an interrupt if it sees not-serviced buffers on host but I'm looking for a better and deterministic solution.我的权宜之计是向设备固件添加一个看门狗,如果它在主机上看到未服务的缓冲区,则重新发出中断,但我正在寻找更好的确定性解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM