【问题标题】:Priority of kernel modules and SCHED_RR threads内核模块和 SCHED_RR 线程的优先级
【发布时间】:2011-12-02 09:03:18
【问题描述】:

我有一个连接了两个设备的嵌入式 Linux 平台(Beagleboard,运行 Angstrom Linux):

  • 通过 USB 连接的激光测距仪 (Hokuyo UTM 30)
  • 通过 SPI 连接的自定义外部板

我们编写了一个负责 SPI 数据传输的 Linux 内核模块。它有一个 IRQ 处理程序,其中调用了 spi_async,这反过来又会导致调用异步回调方法。

我的 C++ 应用程序由三个线程组成:

  • 数据处理的主线程
  • 激光轮询线程
  • 一个 SPI 轮询线程

我遇到的问题似乎是由上述模块的交互方式引起的。

  • 当我关闭 USB 设备(激光测距仪)时,我正确接收所有 SPI 消息(每 3 毫秒 1 条消息,消息长度除以数据速率
  • 当我打开 USB 设备并使用正常的线程调度(SCHED_OTHER,优先级 0,没有设置好的级别)运行我的程序时,大约 1% 的消息“丢失”,因为 spi_async 的回调方法在运行时运行下一个 IRQ 发生(我可以以不同的方式处理这种情况,以免丢失消息,所以这不是一个大问题。)
  • 打开 USB 设备并使用 SCHED_RR 运行程序并

    • 主线程的优先级 = 10
    • SPI 读取线程的优先级 = 10
    • USB/激光轮询线程的优先级 = 4

    然后我丢失了 40% 的消息,因为在调用 spi-callback 方法之前再次触发了 IRQ! (我仍然可以找到解决方法,但问题是我需要快速响应时间,在这种情况下无法再达到)。我需要使用线程调度和激光设备,所以我正在寻找解决这种情况的方法。

问题一:

我的假设是 IRQ 处理程序和内核空间中由 spi_async 触发的回调具有比用户空间中运行的任何线程更高的优先级(无论是 SCHED_RR 还是 SCHED_OTHER)。这意味着在我的应用程序中转向 SCHED_RR 不应减慢 SPI 传输,但这似乎是非常错误的。是吗?

问题 2:

我如何确定这里发生了什么?存在哪些调试辅助工具? (或者也许您不需要任何进一步的信息?)我的主要问题是:为什么我只有在打开激光设备时才会遇到这些问题。 USB驱动会不会很耗时间?

----- 编辑:

我做了以下观察:

spi_async 的回调调用wake_up_interruptible(&mydata->readq);(使用wait_queue_head_t readq;)。从用户空间(我的应用程序)我调用一个函数,结果为poll_wait(file, &mydata->readq, wait); 当民意调查返回时,用户空间调用read()

  • 当我的应用程序使用SCHED_OTHER 运行时,我可以看到回调方法首先完成,然后进入我的内核模块中的read() 方法。
  • 当我的应用程序以SCHED_RR 运行时,退出回调之前进入读取。

这似乎证明了用户空间线程的优先级高于回调方法的上下文的优先级。有什么方法可以改变这种行为并且我的应用程序线程仍然有SCHED_RR

【问题讨论】:

  • 无事可做时你的线程在做什么?(即它们是在旋转/轮询某些东西,还是以某种方式阻塞?如果它们在某个地方旋转,你会吃掉大量的 CPU 和延迟将在实时调度程序下飙升)
  • 主线程在完成处理时(通常为0.5ms)阻塞,激光线程在串行连接上没有数据时阻塞,SPI线程在没有新的SPI消息时阻塞。 CPU 负载
  • 解决延迟工作优先级的唯一方法是修改 spi master 驱动。

标签: c++ c linux real-time scheduling


【解决方案1】:

并非所有内核线程都有 RT 优先级。想象一个需要做一些后台工作的周期性唤醒线程正在唤醒。您不希望该线程抢占您的 RT 线程。所以我猜你的第一个假设是错误的。

根据您的其他问题:

  • 您的主处理循环通过队列接收 SPI 数据
  • spi 处理线程为主处理队列提供数据

您的主处理线程似乎妨碍了负责 spi 数据传输的 spi 驱动程序线程。

这是发生了什么:

  • 一个 IRQ 被触发
  • spi_async 被调用,这意味着数据传输已排队,将由 spi 主驱动程序创建的线程拾取。
  • spi 主线程与您的主处理线程激光线程竞争,但此内核线程没有 RT 优先级,因此每次运行 RR 线程时它都会丢失。

您可以做的是回到正常的调度,同时使用各种 CONFIG_PREEMPT_ 选项。或者弄乱 spi 主驱动程序,以确保任何延迟的工作都以足够的优先级排队。甚至根本不排队。

【讨论】:

  • spi_sync 的文档说:“这个调用只能在可能休眠的上下文中使用”,这不是 IRQ 的情况,对吧?
  • 好的,当前的内核 API 是完全异步的,带有一些同步包装器。
  • 您可以使用 request_threaded_irq 并调用可能在 irq 处理程序中休眠的函数。
猜你喜欢
  • 2017-05-04
  • 2021-02-25
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多