gpt4 book ai didi

c++ - Kworker 线程被 SCHED_RR 用户空间线程阻塞

转载 作者:太空宇宙 更新时间:2023-11-04 12:38:16 24 4
gpt4 key购买 nike

我们有一个使用内核 3.14.17、PREEMPT RT 的 Linux 系统。它是一个单核系统。

对于延迟问题,我们的应用程序将其某些线程的调度类型设置为 SCHED_RR。但是,这会导致内核中的 kworker 被阻塞,因为它们仅在 SCHED_OTHER 模式下运行。这可能会导致一种优先级倒置,因为低优先级 SCHED_RR 线程会阻止高优先级 SHED_RR 从驱动程序接收数据。

它是被阻止的 TTY 驱动程序。它在函数 tty_flip_buffer_push 中使用工作队列。可能有更多电话,但这是我们确定的电话。

有什么方法可以轻松解决此问题 - RT 应用程序依赖于 kworker?我们希望我们不必自己破解驱动程序/内核。 RT 内核中是否有针对此类内容的任何内核配置选项?我们可以吗,

  • 为 kworker 设置 SCHED_RR 优先级?
  • 禁用特定驱动程序的工作队列?

如果我们必须破解驱动程序,我们可能会给它自己的工作队列,使用 SCHED_RR kworker。

当然,任何其他解决方案也很有趣。如果有一些新功能,我们可以升级到更高版本的内核。

最佳答案

此行为的根本原因是 tty_flip_buffer_push()

kernel/drivers/tty/tty_buffer.c:518 ,tty_flip_buffer_push 调度一个异步任务。这很快就会由 kworker 线程异步执行。

然而,如果任何实时线程在系统上执行并保持繁忙,那么 kworker 线程很快执行的机会就会非常小。最终一旦 RT 线程放弃 CPU 或 RT-throttling被触发,它最终可能会为 kworker 线程提供执行的机会。


较旧的内核支持 TTY 子系统中的 low_latency 标志。

Linux 内核 v3.15 之前 tty_flip_buffer_push()尊重 tty 端口的 low_latency 标志。

如果 low_latency 标志由 UART 驱动程序设置如下(通常在其 .startup() 函数中),

t->uport.state->port.tty->low_latency = 1;

然后 tty_flip_buffer_push() 在当前函数调用本身的上下文中执行同步复制。因此它会自动继承当前任务的优先级,即不会因异步调度工作任务而导致优先级反转。

Note: If the serial driver sets the low_latency flag, it must avoid calling tty_flip_buffer_push() within an ISR(interrupt context). With the low_latency flag set, tty_flip_buffer_push() does NOT use separate workqueue, but directly calls the functions. So if called within an interrupt context, the ISR will take longer to execute. This will increase latency of other parts of the kernel/system. Also under certain conditions (dpeending on how much data is available in the serial buffer) tty_flip_buffer_push() may attempt to sleep (acquire a mutex). Calling sleep within an ISR in the Linux kernel causes a kernel bug.


<子>

随着 Linux 内核中的工作队列实现迁移到 CMWQ ,
不再可能确定性地获得独立的执行上下文
(即单独的线程)用于各个工作队列。

系统中的所有工作队列都由系统中的 kworker/* 线程支持。

注意:此部分已过时!!
完整保留以下内容作为旧版本 Linux 内核的引用。

低延迟/实时 UART/TTY 的自定义:

1。为 TTY 层创建和使用个人工作队列。

在 tty_init() 中创建一个新的工作队列。

使用 create_workqueue() 创建的工作队列将为系统上的每个 CPU 分配 1 个工作线程。

struct workqueue_struct *create_workqueue(const char *name);

改为使用 create_singlethread_workqueue(),创建一个具有单个 kworker 进程的工作队列

struct workqueue_struct *create_singlethread_workqueue(const char *name);

2。使用私有(private)工作队列。

在上面的私有(private)工作队列而不是内核的全局全局工作队列上排队翻转缓冲区工作。

int queue_work(struct workqueue_struct *queue, struct work_struct *work);

将 tty_flip_buffer_push() 调用的函数中的 schedule_work() 替换为 queue_work()

3。调整私有(private)工作队列的执行优先级。

在启动时,TTY 层工作队列使用的 kworker 线程可以通过创建它时使用的字符串 name 来识别。根据系统设计的要求,在此线程上使用 chrt 设置适当的更高 RT 优先级。

关于c++ - Kworker 线程被 SCHED_RR 用户空间线程阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40977152/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com