首页 > 解决方案 > 从内核调用 local_irq_disable() 也会禁用用户空间中的本地中断?

问题描述

从内核我可以调用local_irq_disable(). 据我了解,它将禁用当前 CPU 的中断。在我打电话之前,中断将保持禁用状态local_irq_enable()。如果我的理解不正确,请纠正我。

如果我的理解是正确的,这是否意味着在调用local_irq_disable()中断时也会为在同一个 CPU 上运行的用户空间中的进程禁用?

更多细节:

我有一个在用户空间中运行的进程,我想在不受中断和上下文切换影响的情况下运行它。由于从用户空间不可能,我认为从内核禁用特定 CPU 的中断和内核抢占在这种情况下会有所帮助。因此,我使用以下代码编写了一个简单的设备驱动程序来禁用内核抢占和本地中断,

    int i = irqs_disabled();
    pr_info("before interrupt disable: %d\n", i);
    pr_info("module is loaded on processor: %d\n", smp_processor_id());
    id = get_cpu();
    
    message[1] = smp_processor_id() + '0';
    
    local_irq_disable(); 
    
    printk(KERN_INFO " Current CPU id is %c\n", message[1]);
    printk(KERN_INFO " local_irq_disable() called, Disable local interrupts\n");
    pr_info("After interrupt disable: %d\n", irqs_disabled());

输出:$dmesg

[22690.997561] before interrupt disable: 0
[22690.997564]  Current CPU id is 1
[22690.997565]  local_irq_disable() called, Disable local interrupts
[22690.997566] After interrupt disable: 1

我认为输出确认local_irq_disable()确实禁用了本地中断。

在我禁用内核抢占和中断后,在用户空间中我用来CPU_SET()将我的进程固定到那个特定的 CPU 中。但是在做了所有这些之后,我仍然没有得到想要的结果。因此,似乎从内核禁用特定 CPU 的中断也会禁用在该 CPU 上运行的用户空间进程的中断是不正确的。我很困惑。

我正在寻找上述问题的答案,但找不到任何合适的答案。

标签: linux-kernelx86-64linux-device-driverinterrupt

解决方案


禁用中断的 CPU 状态的持续时间应该很,因为它会影响整个操作系统。因此,允许用户空间代码在禁用中断的情况下运行被认为是不好的做法,Linux 内核不支持。

内核模块负责由local_irq_disable/local_irq_enable仅由内核代码包装。有时内核本身可以“修复”这些函数的错误使用,但在编写模块时不应依赖这一事实。

我有一个在用户空间中运行的进程,我想在不受中断和上下文切换影响的情况下运行它。

可以通过适当设置进程的调度策略、亲和性和优先级来实现对上下文切换的保护。这样,调度程序将永远不会尝试重新调度您的进程。Stack Overflow 上有几个关于使 CPU 专供选定进程使用的问题。

至于中断,不应为用户代码禁用它们。

如果用户代码访问了一些应该禁用中断的硬件,那么请考虑将您的代码移动到内核空间。

如果即使是罕见的中断也会严重影响进程的性能或其时序,那么请尝试将 Linux 内核重新配置为“更实时”。还有一些启动时配置选项,可以帮助进一步减少特定内核上的中断数量。参见例如这个问题:为什么使用任务集在一组隔离的内核上运行多线程 Linux 程序会导致所有线程在一个内核上运行?.

请注意,Linux 内核不是实时操作系统的基础,而且从未打算成为。因此,如果没有配置和启动设置可以帮助您,请考虑为您的应用程序选择另一个实时操作系统。


推荐阅读