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

Priority of kernel modules and SCHED_RR threads

本文关键字:线程 优先级 RR SCHED 内核模块      更新时间:2023-10-16

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

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

我们编写了一个Linux内核模块,负责SPI数据的传输。它有一个IRQ处理程序,在该处理程序中调用spi_async,从而导致调用async回调方法。

我的c++程序由三个线程组成:

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

我遇到的问题似乎是由上述模块如何相互作用引起的。

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

    运行程序
    • 优先级= 10主线程
    • 优先级= 10 SPI读取线程
    • USB/Laser轮询线程的priority = 4

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

问题1:

我的假设是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为我的应用程序的线程?

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

根据你的其他问题:

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

似乎你的主处理线程在负责spi数据传输的spi驱动程序线程的方式。

结果如下:

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

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