Linux kernel 字符设备中的中断处理

Linux kernel 字符设备中的中断处理,linux-kernel,interrupt-handling,ioctl,Linux Kernel,Interrupt Handling,Ioctl,我试图在内核中为用户界面正确注册中断 令人惊讶的是,我并没有在内核中找到很多这样的例子 irq处理器 } 等待中断的ioctl static long el_device_ioctl(结构文件*filp, 未签名的int ioctl_num, 无符号长ioctl_参数) { 结构el_irq_dev*el_irq=&el_irq_devices[0]; 开关(ioctl_num){ 案例IOCTL_WAIT_IRQ:buf_路); 旋转锁定(&el\u irq->my\u lock); 如果(e

我试图在内核中为用户界面正确注册中断

令人惊讶的是,我并没有在内核中找到很多这样的例子

irq处理器 }

等待中断的ioctl
static long el_device_ioctl(结构文件*filp,
未签名的int ioctl_num,
无符号长ioctl_参数)
{
结构el_irq_dev*el_irq=&el_irq_devices[0];
开关(ioctl_num){
案例IOCTL_WAIT_IRQ:buf_路);
旋转锁定(&el\u irq->my\u lock);
如果(el_irq->buf_wr!=&el_irq->buf_rd)
{
我的价值=一些缓冲区[el_irq->buf_rd];
el_irq->buf_rd++;
如果(el_irq->buf_rd>=16)
el_irq->buf_rd=0;
}
旋转解锁(&el\u irq->my\u lock);
将_复制到_用户(ioctl_参数和my_值,sizeof(my_值));
违约:
打破
}
返回0;
}
我的问题是:

  • 我们应该在中断中清除fpga中的中断(clear_interrupt())吗 起床之前还是之后?我们是否可以将清除中断放在用户空间处理程序(IOCTL_WAIT_IRQ)中,而不是在 中断处理程序
  • 正如您在代码中看到的,我使用循环缓冲区来处理用户空间处理程序缺少中断的情况。这是真的需要,还是我们可以假设没有遗漏? 换句话说,假设永远不会错过中断,这是真的吗?这样ioctl调用永远不会看到超过1个等待中断?如果是-也许我不需要中断处理程序和ioctl处理程序之间的缓冲机制
  • 谢谢,, 快速回答

  • 在我看来,清除用户空间处理程序中的中断是合理的。在所有的工作都完成之后,尽可能晚地做这件事是有意义的,只要你在清理之后再次检查,确认确实没有工作要做(在清理之前可能已经有更多的工作了)
  • 用户空间处理程序可能确实会错过中断,例如,如果在调用IOCTL_WAIT_IRQ的两次调用之间出现多个中断。从某种意义上说,如果在中断清除之前有几项工作到达,中断也可能会被“错过”。堆栈(硬件和软件)的设计应确保这不是一个问题。中断应该只是发出有工作要做的信号,用户空间处理程序应该能够在返回之前完成所有未完成的工作
  • 您可能应该在IOCtl代码[1]中使用spin_lock_irqsave()

  • [1]

    为什么您首先需要所有这些?我们有fpga内存空间,而是在用户空间中执行大多数驱动程序,只是从内核向用户空间发送中断信号什么类型的内存?一般用途?为什么不在内核驱动程序中使用DMA呢?谢谢你的详细回答。假设永远不会错过中断是合理的吗?i、 e.ioctl不应看到超过1个等待中断?如果是-也许我不需要中断处理程序和IOCTL之间的缓冲机制,但我不太清楚这里“错过的中断”是什么意思。最简单的方法是在上次clear_interrupts()之后至少有一个中断时,让IOCtl处理程序(不用担心大写字母,有几个变体)返回。但是用户空间处理程序应该假设,自从上次IOCtl返回以来,可能已经发生了多个中断,并且应该有一种方法让用户空间处理程序了解这些中断报告的所有工作。因此,我假设我在本例中使用的缓冲机制(一些缓冲区),如果这是为所有作品提供用户空间的唯一方式,那么是的。在代码中,您将“ch”指定给当前缓冲区插槽,但我看不出“ch”是从何处获得的,也看不出它到底是什么(我猜您只是在草图代码中遗漏了它)。很多硬件都会在内部实现一个缓冲区,就像某个_缓冲区一样,最终的处理程序(在本例中是用户空间处理程序)可以直接读取。在这种情况下,不需要一些缓冲区。如果这个硬件不能做到这一点,那么您应该确保尽可能快地清除中断,以避免丢失工作。那有帮助吗?是的,帮助很大!我还将此标记为解决方案。我现在也开始认为我真的不需要这个缓冲区,因为HW很关心这个。只要我不清除fpga中的中断,我希望fpga缓冲区不会比预期的要满。因此,如果用户空间处理程序(在ioctl上等待)足够快,可以复制缓冲区并清除中断,那么应该不会有任何真正的问题,对吗?
    static irqreturn_t irq_handler(int irq, void *dev_id)
    {
       struct el_irq_dev *el_irq = &el_irq_devices[0];
        printk("irq in\n");
    
        spin_lock(&el->my_lock,flags);
    
        clear_interrupt() 
    
        some_buffer[buf_wr] = ch;
        el_irq->buf_wr++;
        if (el_irqbuf_wr >= 16)
            el_irqbuf_wr = 0;
    
    
         spin_unlock(&el->my_lock,flags);
         wake_up_interruptible(&el->pollw);
    
    
    
    return IRQ_HANDLED;
    
    static long el_device_ioctl( struct file *filp, 
             unsigned int ioctl_num, 
             unsigned long ioctl_param)
    {
        struct el_irq_dev *el_irq = &el_irq_devices[0];
    switch (ioctl_num) {
    case IOCTL_WAIT_IRQ:      <<<---- using ioctl (no poll) to wait on interrupt
        wait_event_interruptible(el_irq->pollw, &el_irq->buf_wr != &el_irq->buf_rd) ;
        spin_lock(&el_irq->my_lock);
        if (el_irq->buf_wr != &el_irq->buf_rd)
        {
            my_value=some_buffer[el_irq->buf_rd];
            el_irq->buf_rd++;
            if (el_irq->buf_rd >= 16)
                el_irq->buf_rd = 0;
        }
    
        spin_unlock(&el_irq->my_lock);
        copy_to_user(ioctl_param,&my_value,sizeof(my_value));
    
    default:
            break;
        }
        return 0;
    }