实时Linux:禁用本地定时器中断。

11
TL;DR: 使用带有NO_HZ_FULL的Linux内核实时功能,我需要隔离一个进程以获得确定性结果,但/proc/interrupts告诉我仍然存在本地计时器中断(以及其他中断)。如何禁用它?

Long version :

我想确保我的程序不会被中断,所以我尝试使用实时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

指的是从本地计时器接收到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 的任务也是如此。

然而,您可以看到 migration/1 处于 SCHED_FIFO 并且优先级为 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上则会更少。你知道为什么吗?


1
我之前曾遇到过这个问题。如果我没记错,问题源于我使用的英特尔处理器内核间通信 -- 中断功能是内置在硬件中的,无法从软件进行配置。无论我为 Linux 设置了什么配置,问题都不是内核调度问题,而是固有的硬件问题;我可以运行 FreeDOS,仍然会看到 SMI 中断。最终,我们决定利用 FPGA 来实现确定性要求 -- 尽管可以理解这可能不适合你的需求。 - Vilhelm Gray
1
是的,你的答案并没有解决我的问题,但是知道这些还是很好的。谢谢你。 SMI确实是不可屏蔽中断,所以我猜它们包含在“NMI”行中的/proc/interrupts中,而我很幸运,因为我没有太多这些中断。 然而,本地定时器中断不应该在NMI中。 我也在时间上做了一些奇怪的实验结果。我需要继续我的测试,稍后我可能会创建一个新的问题,因为我认为这与本地定时器中断没有真正关系。 - sebastien dontneedtoknowthat
3
据我所知,虽然SMI中断是不可屏蔽的,但是NMI和SMI是两个独立的东西。我认为,SMI中断对操作系统完全透明,并不包括在这些计数器中。 - Evan
你是否配置了 RT throttling(/proc/sys/kernel/sched_rt_period_us)?这可以防止你的 RT 任务完全占用核心并使其他非 RT 任务饿死。理论上,当一个优先级为 99 的 RT 任务正在运行且不自愿放弃核心时,不应该发生 LOC。 - foool
1个回答

6
事实上,一个完全无滴答的CPU(也称为自适应滴答,并配置有nohz_full=)仍会接收到一些滴答。
最值得注意的是,调度程序需要在孤立的完全无滴答CPU上使用定时器每秒更新一些状态。
这是一个已记录的限制(截至2019年):
引用:

某些处理进程操作仍需要偶尔进行调度时钟滴答操作。这些操作包括计算CPU负载、维护调度平均值、计算CFS实体运行时间、计算avenrun并执行负载平衡。目前它们通过每秒进行一次调度时钟滴答来实现。正在进行的工作将消除甚至对这些不频繁的调度时钟滴答的需求。

(来源:Documentation/timers/NO_HZ.txt,参见2013年LWN文章(几乎)完全无滴答操作3.10,了解一些背景)
更准确地测量本地定时器中断(/proc/interrupts中的LOC行)的方法是使用perf。例如:
$ perf stat -a -A -e irq_vectors:local_timer_entry ./my_binary

在这里,my_binary将有线程固定到隔离的CPU上,不停地利用CPU而不会调用系统调用 - 比如连续2分钟。

还有其他来源的本地定时器中断(当只有一个可运行任务时)。

例如,VM统计信息的收集 - 默认情况下每秒收集一次。因此,我可以通过设置更高的值来减少我的LOC中断:

# sysctl vm.stat_interval=60

另一个来源是定期检查不同CPU上的TSC是否漂移-您可以使用以下内核选项禁用这些检查:

tsc=reliable

(只有在您确信您的TSC不漂移时才应用此选项。)

您可以通过记录ftrace跟踪信息(在测试二进制文件运行时)来找到其他来源。

既然评论中提到了它:是的,SMI对内核完全透明。它不会显示为NMI。您只能间接检测SMI。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接