内核模块和SCHED_RR线程的优先级

时间:2011-10-06 15:45:16

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

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

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

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

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

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

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

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

    运行程序
    • priority = 10 for main thread
    • priority = 10 for SPI read thread
    • 优先级= 4,用于USB /激光轮询线程

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

问题1:

我的假设是内核空间中的spi_async触发的IRQ处理程序和回调的优先级高于用户空间中运行的任何线程(无论是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

1 个答案:

答案 0 :(得分:1)

并非所有内核线程都具有RT优先级。想象一下,需要做一些背景工作的周期性唤醒线程正在唤醒。您不希望此线程预先设置您的RT线程。所以我猜你的第一个假设是错误的。

根据您的其他问题:

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

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

以下是发生的事情:

  • 解雇IRQ
  • 调用spi_async,这意味着数据传输已排队,将由spi主驱动程序创建的线程获取。
  • spi主线程与你的主处理线程激光线程竞争,但是这个内核线程没有RT优先级,所以每当一个RR线程运行时它就会丢失。

你可以做的是回到正常的日程安排,同时玩各种CONFIG_PREEMPT_选项。或者使用spi主驱动程序,以确保任何延迟工作排队的优先级足够高。甚至根本没有排队。