【问题标题】:Linux Interrupt vs. PollingLinux 中断与轮询
【发布时间】:2014-03-26 13:41:20
【问题描述】:

我正在开发一个带有 DSP 和 ARM 的系统。在 ARM 上有一个 linux 操作系统。我有一个 DSP 向 ARM (Linux) 发送数据 - 在 Linux 中有一个内核模块,它读取从 DSP 接收到的数据。内核模块正在唤醒以读取数据,使用 DSP 到 ARM 之间的硬件中断。

我想编写一个用户空间应用程序,它会在每次有来自 DSP 的新数据到达时从内核空间(内核模块)读取数据。
问题是:

有什么更好的方法来做到这一点,从内核到用户空间的软件中断或每 10 毫秒从用户空间轮询一次(使用内核读取已知的内存地址)..?

知道:

  • 从 DSP 到内核的数据必须在很短的时间内到达 - 100us。
  • 从内核到用户空间的数据可能需要 10 毫秒到 30 毫秒。
  • 正在读取的数据被认为很小 - 大约 100 字节。

【问题讨论】:

  • 有点取决于您的应用程序...您能否再给我们一些参数,说明您对数据通知所做的工作,该代码的时间限制是什么?
  • 关于读取内核中已知的内存地址,不要那样做!看看其他设备是如何工作的:它们让用户空间应用程序打开一个文件描述符,然后应用程序可以从中读取数据。您可能还想了解其他(类似)设备如何处理通知/轮询。
  • 您的延迟要求是什么?您的电源限制是什么?
  • 通常从驱动程序设置一个信号量 - 用户空间线程等待它,驱动程序发出信号并在退出时要求重新安排。轮询只是浪费和延迟诱导。
  • 我用时间延迟和数据大小更新了问题..

标签: c linux linux-kernel real-time interrupt


【解决方案1】:

我将创建一个设备并将用户空间程序块放在read 上。中间不需要等待 10 毫秒,这通过阻塞来有效处理。

使用poll(是的,我明白这不是你的意思)进行轮询可以正常工作,但是没有理由在一个函数时调用两个函数(首先是poll,然后是read)无论如何都可以做到。无需每 10 毫秒执行一次,您可以在处理完上次读取的内容后立即再次调用 poll

不建议每 10 毫秒检查一次已知内存位置的轮询。这不仅是一种丑陋的 hack,而且比您想象的更复杂(您必须将包含该内存位置的页面映射到用户空间),并且是一种不必要地消耗 CPU 的忙等待形式,它还具有 5ms 的平均延迟和最坏情况下的延迟为 10 毫秒,这是完全没有必要的。 read 的平均和最坏情况延迟大约为零(嗯,不完全是,但几乎如此......它与唤醒阻塞任务一样快)。

中断(即信号)非常有效,但与简单的读取和阻塞相比,使程序更加复杂/扭曲(必须编写信号处理程序,可能不使用处理程序中的某些功能,必须与主应用程序通信等.)。虽然从技术上讲是一个很好的解决方案,但我建议不要使用它们,因为程序不需要比必要的复杂。

【讨论】:

    【解决方案2】:

    轮询比等待没有优势。该进程仍然必须被安排并切换到所有这些,然后它会在部分时间进行无用的轮询。

    Linux 在从中断返回时运行调度程序,所以当你在内核中断处理程序中唤醒等待任务并且它设置了高优先级(显然你应该给它实时优先级)时,任务将立即被调度.你不会通过投票来击败它。

    (字符)设备文件的标准接口相当快,所以只需实现阻塞读取、轮询(这是一个阻塞系统调用,实际上不轮询任何东西)和可能的异步读取(使用实时信号),但我怀疑在读取系统调用中等待的专用线程的性能将优于 AIO。而且写起来也更容易。您应该在内核源代码中找到足够多的示例。

    【讨论】:

      【解决方案3】:

      您似乎没有提到任何严格的时间限制,因此您真的可以采用任何一种方法。然而,正如 Martin James 所说,轮询会给应用程序带来一些开销,而这可能是您不希望的。

      就个人而言,我会选择由内核触发的中断或事件标志。虽然您可能没有严格的时间限制,但我假设您想要一些更具确定性的东西,而不是没有。内核中断将使您更接近这一点。

      【讨论】:

        猜你喜欢
        • 2016-06-15
        • 2012-05-10
        • 2012-06-11
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多