【问题标题】:Real time Linux: disable local timer interrupts实时 Linux:禁用本地定时器中断
【发布时间】: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


【解决方案1】:

问题是一个完整的无滴答声 CPU(也称为自适应滴答声,配置为 nohz_full=)仍然会收到一些滴答声。

最值得注意的是,调度程序需要一个独立的完整无滴答 CPU 上的计时器,以便每秒左右更新一些状态。

这是一个记录在案的限制(截至 2019 年):

一些流程处理操作仍然需要偶尔 调度时钟滴答。这些操作包括计算 CPU 负载,维护计划平均值,计算 CFS 实体 vruntime, 计算 avenrun,进行负载均衡。他们是 当前由调度时钟每秒刻度容纳 或者。正在进行的工作将消除对这些的需求 不频繁的调度时钟滴答声。

(来源:Documentation/timers/NO_HZ.txt,参考 2013 年的 LWN 文章 (Nearly) full tickless operation in 3.10 了解一些背景)

测量本地定时器中断(/proc/interrupts 中的 LOC 行)的更准确方法是使用perf。例如:

$ perf stat -a -A -e irq_vectors:local_timer_entry ./my_binary

my_binary 将线程固定到隔离的 CPU,这些线程在不调用系统调用的情况下不间断地使用 CPU - 比如说 2 分钟。

还有其他额外的本地计时器计时来源(当只有 1 个可运行任务时)。

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

# sysctl vm.stat_interval=60

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

tsc=reliable

(仅当您确实知道您的 TSC 不会漂移时才应用此选项。)

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

自从它出现在 cmets 中:是的,SMI 对内核是完全透明的。它不会显示为 NMI。您只能间接检测 SMI。

【讨论】:

    猜你喜欢
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 2016-05-30
    相关资源
    最近更新 更多