澄清 request_threaded_irq 的行为

The*_*ker 6 multithreading linux-device-driver linux-kernel

我在网上搜索过,但没有找到关于“request_threaded_irq”功能的几个相关问题的令人信服的答案。

问题 1: 首先,我正在阅读这篇关于线程 IRQ 的文章:

http://lwn.net/Articles/302043/

我不清楚这一行:

“只有当处理程序代码通过集成 tasklet/softirq 功能并简化锁定来利用它时,将中断转换为线程才有意义。”

我知道如果我们继续采用“传统”的上半部/下半部方法,我们将需要自旋锁或禁用本地 IRQ 来干预共享数据。但是,我不明白的是,线程中断如何通过集成 tasklet/softirq 功能来简化锁定需求。

问题 2: 其次,request_threaded_handler 方法比基于 work_queue 的下半部分方法有什么优势(如果有)?在这两种情况下,似乎“工作”都被推迟到了一个专用线程。那么区别是什么呢 ?

问题3: 最后,在以下原型中:

int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id)
Run Code Online (Sandbox Code Playgroud)

IRQ 的“处理程序”部分是否可能由相关的 IRQ(例如 UART 以高速率接收字符)持续触发,即使“thread_fn”(将 rx'd 字节写入循环缓冲区)部分中断处理程序正忙于处理先前唤醒的 IRQ ?那么,处理程序不会试图“唤醒”已经运行的“thread_fn”吗?在这种情况下,正在运行的 irq thread_fn 会如何表现?

如果有人能帮助我理解这一点,我将不胜感激。

谢谢,vj

Joe*_*des 5

对于问题 2,与工作队列不同,创建时的 IRQ 线程设置为具有更高的优先级。在 中kernel/irq/manage.c,您将看到如下所示的一些代码,用于为线程 IRQ 创建内核线程:

            static const struct sched_param param = {
                    .sched_priority = MAX_USER_RT_PRIO/2,
            };


            t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
                               new->name);
            if (IS_ERR(t)) {
                    ret = PTR_ERR(t);
                    goto out_mput;
            }

            sched_setscheduler_nocheck(t, SCHED_FIFO, &param);
Run Code Online (Sandbox Code Playgroud)

在这里您可以看到,内核线程的调度策略设置为RT一(SCHED_FIFO),并且线程的优先级设置为MAX_USER_RT_PRIO/2高于常规进程。

对于问题3,您所描述的情况也可能发生在正常中断中。通常在内核中,当 ISR 执行时,中断被禁用。在 ISR 执行期间,字符可以继续填充设备的缓冲区,并且即使在禁用中断的情况下,设备也可以而且必须继续发出中断。

设备的工作是确保 IRQ 线保持有效状态,直到 ISR 读取所有字符并完成所有处理。同样重要的是,中断是电平触发的,或者根据设计由中断控制器锁存。

最后,设备/外设应具有足够大小的 FIFO,以便以高速率传送的字符不会因慢速 ISR 而丢失。ISR 还应该设计为在执行时读取尽可能多的字符。

一般来说,我所看到的是,控制器会有一个一定大小的 FIFO X,当 FIFO 填满时X/2,它会触发一个中断,导致 ISR 抓取尽可能多的数据。ISR 读取尽可能多的内容,然后清除中断。同时,如果 FIFO 仍然存在X/2,设备将保持中断线有效,导致 ISR 再次执行。


art*_*ise 2

  1. 之前下半部不是a task,依然无法格挡。唯一的区别是中断被禁用。tasklet或softirq允许驱动程序的ISR 线程和用户 API(、和)之间存在不同的互锁。ioctl()read()write()
  2. 我认为这work queue几乎是相当的。然而,tasklet/ksoftirq具有高优先级,并且由该处理器上所有基于 ISR 的功能使用。这可能会提供更好的调度机会。此外,司机需要管理的事情也减少了;所有内容都已内置到内核的 ISR 处理程序代码中。
  3. 你必须处理好这个。通常可以使用乒乓kfifo缓冲区或您建议的类似缓冲区。应该handler是贪婪的,并在返回之前从 UART 获取所有数据IRQ_WAKE_THREAD