首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实时Linux:禁用本地计时器中断

实时Linux:禁用本地计时器中断
EN

Stack Overflow用户
提问于 2017-09-06 14:15:30
回答 1查看 6.6K关注 0票数 10

TL;DR:使用Linux内核实时地使用NO_HZ_FULL,我需要隔离一个进程才能有确定性的结果,但是/proc/告诉我仍然存在本地定时器中断(除其他外)。怎么让它失效?

长版本:

我想确保我的程序没有被中断,所以我尝试使用一个实时Linux内核。我使用的是实时版本的arch Linux (linux-rt on AUR),并修改了内核的配置,以选择以下选项:

代码语言:javascript
复制
CONFIG_NO_HZ_FULL=y
CONFIG_NO_HZ_FULL_ALL=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_ALL=y

然后,我重新启动我的计算机,以便在这个实时内核上启动,并使用以下选项:

代码语言:javascript
复制
nmi_watchdog=0
rcu_nocbs=1
nohz_full=1
isolcpus=1

我还在BIOS中禁用了以下选项:

代码语言:javascript
复制
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)就足以做到这一点,我试图通过运行这些命令来检查:

代码语言:javascript
复制
cat /proc/interrupts | grep LOC > ~/tmp/log/overload_cpu1
taskset -c 1 ./overload
cat /proc/interrupts | grep LOC >> ~/tmp/log/overload_cpu1

其中过载过程是:

代码语言:javascript
复制
***overload.c:***
int main()
{
  for(int i=0;i<100;++i)
    for(int j=0;j<100000000;++j);
}

文件overload_cpu1包含结果:

代码语言:javascript
复制
LOC:     234328        488      12091      11299   Local timer interrupts
LOC:     239072        651      12215      11323   Local timer interrupts

意思是651-488 = 163来自本地计时器的中断,而不是0.

作为比较,我做了同样的实验,但我改变了进程overload运行的核心(我一直在CPU1上观察中断):

代码语言:javascript
复制
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发送调度时钟中断”(HZ.txt)

也许可以解释一下,在CPU1上还有其他的进程在运行。我使用ps命令进行检查:

代码语言:javascript
复制
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和优先级99中的迁移/1。也许这些进程在运行时会导致中断。这解释了当我的进程在CPU0、CPU2和CPU3 (分别为8、7和8次中断)上运行时出现的几次中断,但这也意味着这些进程并不经常运行,然后也不能解释为什么当我的进程在CPU1上运行(163个中断)时会有很多中断。

我也做了同样的实验,但是使用过载过程的SCHED_FIFO,我得到:

代码语言:javascript
复制
taskset -c 0 : 1
taskset -c 1 : 4063
taskset -c 2 : 1
taskset -c 3 : 0

在这种配置中,在我的进程在CPU1上使用CPU1策略,在其他CPU上使用更少的中断时,会出现更多的中断。你知道为什么吗?

EN

回答 1

Stack Overflow用户

发布于 2019-09-15 10:06:07

问题是,一个完全不挠痒痒的CPU。使用nohz_full=配置的自适应滴答(Adaptive)仍然会收到一些滴答。

最值得注意的是,调度程序需要在一个独立的、完全没有滴答的CPU上设置一个计时器,以便每一秒左右更新一次状态。

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

一些进程处理操作仍然需要偶尔的调度时钟滴答。这些操作包括计算CPU负载、维护sched平均值、计算CFS实体v运行时、计算avenrun和执行负载平衡。他们目前被安排时钟滴答每一秒左右。正在进行的工作将消除这种需要,即使是这些罕见的调度时钟滴答声。

(资料来源:HZ.txt,参比)LWN文章“(几乎) 3.10中的全无痒操作从2013年开始”作为背景)

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

代码语言:javascript
复制
$ perf stat -a -A -e irq_vectors:local_timer_entry ./my_binary

其中,my_binary将线程固定在独立的CPU上,这些CPU不间断地使用CPU,而不调用syscalls --比如2分钟。

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

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

代码语言:javascript
复制
# sysctl vm.stat_interval=60

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

代码语言:javascript
复制
tsc=reliable

(只有当你真正知道你的TSC不会漂移时,才应用这个选项。)

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

因为它出现在评论中:是的,SMI对内核是完全透明的。不会以NMI的形式出现。您只能间接地检测到SMI。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46077582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档