Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux内核中断处理程序互斥保护?_Linux_Linux Kernel_Linux Device Driver_Interrupt - Fatal编程技术网

Linux内核中断处理程序互斥保护?

Linux内核中断处理程序互斥保护?,linux,linux-kernel,linux-device-driver,interrupt,Linux,Linux Kernel,Linux Device Driver,Interrupt,我是否需要保护我的中断处理程序在同一中断中被多次调用 鉴于下面的代码,我不确定应该进行哪些系统调用。我在当前的实现中遇到了罕见的随机死锁:- void interrupt_handler(void) { down_interruptible(&sem); // or use a lock here ? clear_intr(); // clear interrupt source on H/W wake_up_interruptible(...);

我是否需要保护我的中断处理程序在同一中断中被多次调用

鉴于下面的代码,我不确定应该进行哪些系统调用。我在当前的实现中遇到了罕见的随机死锁:-

void interrupt_handler(void)
{
    down_interruptible(&sem);  // or use a lock here ?

    clear_intr(); // clear interrupt source on H/W

    wake_up_interruptible(...);

    up(&sem); // unlock?

    return IRQ_HANDLED;
}

void set/clear_intr()
{
    spin_lock_irq(&lock);
    RMW(x); // set/clear a bit by read/modify/write the H/W interrupt routing register
    spin_unlock_irq(&lock);
}

void read()
{
    set_intr();  // same as clear_intr, but sets a bit
    wait_event_interruptible(...);
}
  • 是否应
    中断处理程序
    向下可中断
    旋转锁定irq
    /
    旋转锁定irq保存
    /
    本地irq禁用
  • 是否应
    set/clear\u intr
    spin\u lock\u irq
    be
    spin\u lock\u irqsave
    /
    local\u irq\u disable
  • 它(H/W->kernel->driver handler)能否一直生成/获取中断,直到清除为止?
    interrupt\u处理程序
    在其内部时能否继续被调用
  • 如果当前实现的中断处理程序是可重入的,那么它是否会阻塞
    关闭\u interruptable
  • 从LDD3:-

    必须是可重入的它必须能够同时在多个上下文中运行


    编辑1)在获得一些不错的帮助后,建议如下:-

  • interrupt\u处理程序中删除
    down\u interruptable
  • 移动
    spin\u lock\u irq
    外部设置/清除方法(不需要
    spin\u lock\u irqsave
    代码:-

    void interrupt_handler(void)
    {
        read_reg(y); // eg of other stuff in the handler
    
        spin_lock_irq(&lock);
    
        clear_intr(); // clear interrupt source on H/W
    
        spin_unlock_irq(&lock);
    
        wake_up_interruptible(...);
    
        return IRQ_HANDLED;
    }
    
    void set/clear_intr()
    {
        RMW(x);
    }
    
    void read()
    {
        error_checks(); // eg of some other stuff in the read method
    
        spin_lock_irq(&lock);
    
        set_intr();  // same as clear_intr, but sets a bit
    
        spin_unlock_irq(&lock);
    
        wait_event_interruptible(...);
    
        // more code here...
    }
    

    编辑2)在阅读了更多的SO帖子:阅读了与Robert Loves的链接后,我读了以下内容:

    一些中断处理程序(在 Linux(作为快速中断处理程序)运行 所有的中断都在本地 处理器已禁用。这样做是为了 确保中断处理程序运行 没有中断,尽快 可能的更何况,大家都打断了 处理程序使用其当前 所有设备上的中断线已禁用 处理器。这确保了两个 同样的中断处理程序 中断行不运行 同时它还可以防止设备损坏 驱动程序编写器不必处理 递归中断,使 编程


    我启用了快速中断(SA_中断)!所以不需要互斥锁/锁/信号量/旋转/等待/睡眠/等等

    不要在中断上下文中使用信号量,而是使用
    spin\u lock\u irqsave
    。引用LDD3:

    如果你有一个旋转锁可以 由在(硬件)中运行的代码获取 或软件)中断上下文,您 必须使用旋转锁定的其中一种形式 这将禁用中断。做 否则会导致系统死锁, 迟早如果您不访问 你的锁在硬件中断 处理程序,但您可以通过软件执行 中断(在代码中,使用的是 例如,tasklet是一个涵盖的主题 在第7章),您可以使用 旋转锁以安全避免死锁 同时仍然允许硬件 需要维修的中断

    至于第2点,让您的
    set_intr
    clear_intr
    要求调用方锁定自旋锁,否则您会发现代码死锁。同样来自LDD3:

    要使您的锁正常工作, 你必须用它来写一些函数 假设他们的来电者 已获取相关锁。 通常,只有你的内部,静态 函数可以用这种方式编写; 从外部调用的函数必须 显式处理锁定。当你 编写内部函数,使 关于锁定的假设,请自己动手 (还有其他与您合作的人 编码)一个帮助并记录这些 明确的假设。这可能是非常危险的 几个月后很难再回来 弄清楚你是否需要持有一张支票 锁定以调用特定函数或 不是


    在中断上下文中使用spinlock,因为如果没有获得锁,您不想在中断上下文中睡眠。

    您发布的代码看起来不像设备驱动程序irq处理程序。 内核驱动程序中的irq处理程序返回irqreturn__t并将int irq_no、void*数据作为参数

    您还没有指定是注册线程处理程序还是非线程处理程序。 无论您是否持有任何自旋锁,非线程irq处理程序都不能有任何休眠调用。 wait_事件、互斥、信号量等都是休眠调用,不能在非线程irq处理程序中使用。但是,您可以保持自旋锁以防止中断处理程序中断。这将确保可屏蔽IRQ和调度器不会中断中间的IRQ处理程序。


    在线程化irq处理程序中,可以使用休眠调用(等待队列、互斥等),但仍不推荐使用。

    您回答了(LDD3引述)自己的第一个问题(以及其他一些问题的重新表述)。一般来说,防止锁定时间关键的东西(如中断处理)。很抱歉,我不能提供更多的答案,+1来自me@sehe是的,但是对
    向下
    /
    向上
    的调用应该在那里吗?@sehe并且有了它,这个方法就不能说是可重入的@IanVaughan:只有当您确定在调用代码时没有中断被禁用时,才应该使用
    spin\u lock\u irq
    。我建议您至少将中断处理程序中的调用更改为使用
    spin\u lock\u irqsave
    。@Ian Vaughan-不允许在中断处理程序或原子上下文中使用down/up!!!你的意思是不要在
    中断处理程序中使用
    down\u interruptible
    ?@IanVaughan:是的,那是自找麻烦。我已经扩展了我的答案。你的意思是用
    旋转锁定irqsave
    替换
    向下可中断的
    (这肯定会使它不可重入)?或者确保我在set/clear中使用
    spin\u lock\u irqsave
    (而不是当前的
    spin\u lock\u irq
    )重新编辑:我看不出将锁定/解锁移到方法之外有什么帮助,要么调用方为我执行,要么它为我完成,无论哪种方式都是一样的?除非我锁定了更大/更多的代码。@IanVaughan:我主要建议将锁定/解锁移到方法之外以避免