Linux实时调度-kworker线程无法运行并导致性能影响

Linux实时调度-kworker线程无法运行并导致性能影响,linux,multithreading,linux-kernel,real-time,scheduling,Linux,Multithreading,Linux Kernel,Real Time,Scheduling,我有一个应用程序,它使用CPU关联将一些线程固定到特定的核心 我尝试将这些线程移动到实时优先级策略,在这些策略中使用系统上可用的最低优先级的SCHED_FIFO/SCHED_RR: param.sched_priority = sched_get_priority_min(SCHED_FIFO); pthread_setschedparam(pthread_self(), SCHED_FIFO, &param); 因此,这些线程受到了高性能的影响 经过一些研究,我发现原因是一个线程称为

我有一个应用程序,它使用CPU关联将一些线程固定到特定的核心

我尝试将这些线程移动到实时优先级策略,在这些策略中使用系统上可用的最低优先级的SCHED_FIFO/SCHED_RR:

param.sched_priority = sched_get_priority_min(SCHED_FIFO);
pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
因此,这些线程受到了高性能的影响

经过一些研究,我发现原因是一个线程称为: kworker/1:0 处于R状态,但无法运行,因为它有一个常规的策略,而不是实时的,并且因为这个原因而饿死

当我将此kworker线程移动到RT priority时,我的应用程序恢复了高性能:

chrt --fifo -p 99 <kworker_pid>
chrt--fifo-p99
这似乎是某种优先级反转,我的线程正在等待优先级较低的kworker,因此不会运行

我试图弄清楚这个kwroker线程到底做了什么,以及为什么它被卡住会对我的应用程序产生如此大的影响,然而,我得到的唯一线索是查看它的内核回溯:

/proc/<kworker PID>/stack
[<ffffffff8107c1f3>] worker_thread+0x123/0x400
[<ffffffff810820be>] kthread+0xce/0xe0
[<ffffffff81602cec>] ret_from_fork+0x7c/0xb0
/proc//stack
[]辅助线程+0x123/0x400
[]kthread+0xce/0xe0
[]从叉子返回+0x7c/0xb0

有什么想法吗?

要了解kworker线程正在做什么,您可以使用
perf
调查情况

由于kworker线程通常执行工作队列项,因此您可以查看工作队列跟踪事件,例如:

perf trace -e 'workqueue:workqueue_queue_work' --call-graph dwarf -C $CPU_NO
其中
$CPU\u NO
是一个CPU核心号,应用程序的固定线程被阻止

如果工作项由另一个CPU执行的操作排队,则必须使用bcc trace或bpftrace添加条件,例如:

/usr/share/bcc/tools/trace -C -t -K -U \
    't:workqueue:workqueue_queue_work (args->req_cpu==1) \
    "%d => %d", args->cpu, args->req_cpu'

(tracepoint还有一个带有工作队列名称的字符串参数,这里也很感兴趣,但是)


堆栈跟踪可能包含足够的提示,以了解应用程序是如何触发该工作队列项的。你可以得到一些指针来研究你是否可以对它做些什么-例如,这样它就不会再发生在CPU上了(获得一些初始提示)。

要了解kworker线程正在做什么,你可以使用
perf
来调查情况

由于kworker线程通常执行工作队列项,因此您可以查看工作队列跟踪事件,例如:

perf trace -e 'workqueue:workqueue_queue_work' --call-graph dwarf -C $CPU_NO
其中
$CPU\u NO
是一个CPU核心号,应用程序的固定线程被阻止

如果工作项由另一个CPU执行的操作排队,则必须使用bcc trace或bpftrace添加条件,例如:

/usr/share/bcc/tools/trace -C -t -K -U \
    't:workqueue:workqueue_queue_work (args->req_cpu==1) \
    "%d => %d", args->cpu, args->req_cpu'

(tracepoint还有一个带有工作队列名称的字符串参数,这里也很感兴趣,但是)


堆栈跟踪可能包含足够的提示,以了解应用程序是如何触发该工作队列项的。你会得到一些关于你是否可以做些什么的建议——例如,让它不再发生在CPU上(获得一些初始提示)。

显而易见的一点——不要在通用操作系统上做这样的事情!要避免这些问题几乎是不可能的。(CPU在做什么?这就是你需要弄清楚的。如果你的应用程序没有向前推进,为什么它会旋转CPU?如果是,你有什么反对意见?@DavidSchwartz-注意到。。。但是出于好奇…你对发生的事情有什么想法吗?我认为在你弄清楚CPU在做什么之前,你是无法弄清楚的。问题是CPU上运行的任何东西都在旋转,而没有前进。@DavidSchwartz-好吧,这里有一件棘手的事情……我的主线程没有卡住。它不是在锁上旋转,等待系统调用或类似的事情。它似乎在对内核进行异步调用,然后继续。。。这个异步调用产生了影响,那么为什么kworker线程没有运行呢?很明显的一点是——不要在通用操作系统上做这样的事情!要避免这些问题几乎是不可能的。(CPU在做什么?这就是你需要弄清楚的。如果你的应用程序没有向前推进,为什么它会旋转CPU?如果是,你有什么反对意见?@DavidSchwartz-注意到。。。但是出于好奇…你对发生的事情有什么想法吗?我认为在你弄清楚CPU在做什么之前,你是无法弄清楚的。问题是CPU上运行的任何东西都在旋转,而没有前进。@DavidSchwartz-好吧,这里有一件棘手的事情……我的主线程没有卡住。它不是在锁上旋转,等待系统调用或类似的事情。它似乎在对内核进行异步调用,然后继续。。。而这个异步调用产生了影响,那么为什么kworker线程没有运行呢?