【发布时间】:2018-02-15 02:01:16
【问题描述】:
TL;DR:使用带有 NO_HZ_FULL 的 Linux 内核实时我需要隔离一个进程以获得确定性结果,但 /proc/interrupts 告诉我还有本地定时器中断(等等)。如何禁用它?
加长版:
我想确保我的程序没有被中断,所以我尝试使用实时 Linux 内核。 我使用的是实时版本的 Arch Linux(AUR 上的 linux-rt),我修改了内核配置以选择以下选项:
CONFIG_NO_HZ_FULL=y
CONFIG_NO_HZ_FULL_ALL=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_ALL=y
然后我重新启动计算机以使用以下选项在此实时内核上启动:
nmi_watchdog=0
rcu_nocbs=1
nohz_full=1
isolcpus=1
我还在 BIOS 中禁用了以下选项:
C state
intel speed step
turbo mode
VTx
VTd
hyperthreading
我的 CPU (i7-6700 3.40GHz) 有 4 个核心(8 个采用超线程技术的逻辑 CPU) 我可以在 /proc/interrupts 文件中看到 CPU0、CPU1、CPU2、CPU3。
CPU1 被isolcpus 内核参数隔离,我想禁用这个CPU 上的本地定时器中断。
我虽然具有 CONFIG_NO_HZ_FULL 和 CPU 隔离 (isolcpus) 的实时内核就足够了,我尝试通过运行这些命令来检查:
cat /proc/interrupts | grep LOC > ~/tmp/log/overload_cpu1
taskset -c 1 ./overload
cat /proc/interrupts | grep LOC >> ~/tmp/log/overload_cpu1
重载过程在哪里:
***overload.c:***
int main()
{
for(int i=0;i<100;++i)
for(int j=0;j<100000000;++j);
}
文件overload_cpu1 包含结果:
LOC: 234328 488 12091 11299 Local timer interrupts
LOC: 239072 651 12215 11323 Local timer interrupts
含义 651-488 = 来自本地计时器的 163 个中断,而不是 0...
为了比较,我做了同样的实验,但我改变了我的进程 overload 运行的核心(我一直在观察 CPU1 上的中断):
taskset -c 0 : 8 interrupts
taskset -c 1 : 163 interrupts
taskset -c 2 : 7 interrupts
taskset -c 3 : 8 interrupts
我的一个问题是为什么没有 0 中断?为什么当我的进程在 CPU1 上运行时中断数更大? (我的意思是,如果我的进程是单独的,我的意思是 NO_HZ_FULL 会阻止中断:“CONFIG_NO_HZ_FULL=y Kconfig 选项会导致内核避免 通过单个可运行任务向 CPU 发送调度时钟中断"(https://www.kernel.org/doc/Documentation/timers/NO_HZ.txt)
也许解释是 CPU1 上正在运行其他进程。 我使用 ps 命令检查:
CLS CPUID RTPRIO PRI NI CMD PID
TS 1 - 19 0 [cpuhp/1] 18
FF 1 99 139 - [migration/1] 20
TS 1 - 19 0 [rcuc/1] 21
FF 1 1 41 - [ktimersoftd/1] 22
TS 1 - 19 0 [ksoftirqd/1] 23
TS 1 - 19 0 [kworker/1:0] 24
TS 1 - 39 -20 [kworker/1:0H] 25
FF 1 1 41 - [posixcputmr/1] 28
TS 1 - 19 0 [kworker/1:1] 247
TS 1 - 39 -20 [kworker/1:1H] 501
如您所见,CPU1 上有线程。 是否可以禁用这些进程?我猜是因为如果不是这样,NO_HZ_FULL 将永远无法正常工作?
TS 类的任务不会打扰我,因为它们在 SCHED_FIFO 中没有优先级,我可以将此策略设置为我的程序。 对于 FF 类且优先级低于 99 的任务也是如此。
但是,您可以看到 SCHED_FIFO 中的 migration/1 和优先级 99。 也许这些进程在运行时会导致中断。这解释了当我的进程在 CPU0、CPU2 和 CPU3 上(分别为 8,7 和 8 个中断)时的少数中断,但这也意味着这些进程不是经常运行,然后没有解释为什么我的进程运行时有很多中断在 CPU1 上(163 个中断)。
我也做了同样的实验,但我的重载过程使用了 SCHED_FIFO,我得到了:
taskset -c 0 : 1
taskset -c 1 : 4063
taskset -c 2 : 1
taskset -c 3 : 0
在此配置中,如果我的进程在 CPU1 上使用 SCHED_FIFO 策略,而在其他 CPU 上使用较少,则中断会更多。你知道为什么吗?
【问题讨论】:
-
我以前遇到过这个问题。如果我记得,问题源于我使用的英特尔处理器内部的内核间通信——中断功能内置于硬件本身,不能通过软件进行配置。不管我为 Linux 设置了什么配置,问题都不是内核调度问题,而是我的硬件固有的问题;我可以运行 FreeDOS 并仍然看到 SMI 中断。最终,我们决定使用 FPGA 来实现我们的确定性要求——尽管这可能不适合您的需求,这是可以理解的。
-
是的,您的回答并没有解决我的问题,但仍然很高兴知道。谢谢你。 SMI 确实是不可屏蔽的中断,所以我猜它们包含在 /proc/interrupts 的“NMI”行中,我很幸运,因为我没有那么多这些中断。但是本地定时器中断不应该在 NMI 中。我还在时间上试验了一些奇怪的结果。我需要继续我的测试,稍后我可能会创建一个新问题,因为我认为它与本地计时器中断并没有真正的关系。
-
AFAIK,虽然 SMI 中断是不可屏蔽的,但 NMI 和 SMI 是两个独立的东西。我认为 SMI 中断对操作系统是完全透明的,而不是在任何这些计数器中。
-
您是否配置了
RT throttling( /proc/sys/kernel/sched_rt_period_us),这可以防止您的 RT 任务完全占用核心并搁置其他非 RT 任务。理论上,99优先级的RT任务在运行且不主动放弃核心时,不会出现LOC。
标签: timer linux-kernel real-time scheduler interrupt