seb*_*hat 5 real-time timer interrupt scheduler linux-kernel
TL; DR:将Linux内核实时与NO_HZ_FULL一起使用,我需要隔离一个进程才能获得确定的结果,但是/ 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
Run Code Online (Sandbox Code Playgroud)
然后我重新启动计算机,以使用以下选项在此实时内核上启动:
nmi_watchdog=0
rcu_nocbs=1
nohz_full=1
isolcpus=1
Run Code Online (Sandbox Code Playgroud)
我还禁用了BIOS中的以下选项:
C state
intel speed step
turbo mode
VTx
VTd
hyperthreading
Run Code Online (Sandbox Code Playgroud)
我的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
Run Code Online (Sandbox Code Playgroud)
过载过程在哪里:
***overload.c:***
int main()
{
for(int i=0;i<100;++i)
for(int j=0;j<100000000;++j);
}
Run Code Online (Sandbox Code Playgroud)
该文件overload_cpu1
包含结果:
LOC: 234328 488 12091 11299 Local timer interrupts
LOC: 239072 651 12215 11323 Local timer interrupts
Run Code Online (Sandbox Code Playgroud)
含义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
Run Code Online (Sandbox Code Playgroud)
我的问题之一是为什么没有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
Run Code Online (Sandbox Code Playgroud)
如您所见,CPU1上有线程。是否可以禁用这些进程?我想这是因为如果不是这种情况,NO_HZ_FULL将永远无法正常工作吗?
TS类的任务不会打扰我,因为它们在SCHED_FIFO中没有优先级,我可以为我的程序设置此策略。FF级和优先级小于99的任务也是如此。
但是,您会看到位于SCHED_FIFO和优先级99中的migration / 1。也许这些进程在运行时可能会导致中断。这解释了当我的进程进入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
Run Code Online (Sandbox Code Playgroud)
在这种配置下,如果我的进程在CPU1上使用SCHED_FIFO策略,则中断更多,而在其他CPU上,中断更少。你知道为什么吗 ?
问题是,一个完全无滴答的 CPU(又名自适应滴答,配置为nohz_full=
)仍然会收到一些滴答。
最值得注意的是,调度程序需要在隔离的完全无滴答 CPU 上有一个计时器,以便每秒左右更新一些状态。
这是已记录的限制(截至 2019 年):
一些进程处理操作仍然需要偶尔的调度时钟滴答。这些操作包括计算CPU负载、维护sched平均值、计算CFS实体vruntime、计算avenrun以及进行负载均衡。目前,它们是通过每秒左右的调度时钟滴答来容纳的。正在进行的工作将消除对这些不频繁的调度时钟滴答的需要。
(来源:Documentation/timers/NO_HZ.txt,参见 LWN 文章(接近)3.10 中的完全无滴答操作了解一些背景)
测量本地定时器中断(LOC row in /proc/interrupts
)的更准确方法是使用perf
. 例如:
$ perf stat -a -A -e irq_vectors:local_timer_entry ./my_binary
Run Code Online (Sandbox Code Playgroud)
在哪里my_binary
,在不调用系统调用的情况下不间断地使用 CPU(例如 2 分钟)。
还有其他额外的本地计时器滴答源(当只有 1 个可运行任务时)。
例如,VM 统计信息的收集 - 默认情况下每秒收集一次。因此,我可以通过设置更高的值来减少 LOC 中断,例如:
# sysctl vm.stat_interval=60
Run Code Online (Sandbox Code Playgroud)
另一个来源是定期检查不同 CPU 上的 TSC 是否没有漂移 - 您可以使用以下内核选项禁用它们:
tsc=reliable
Run Code Online (Sandbox Code Playgroud)
(仅当您确实知道 TSC 不会漂移时才应用此选项。)
您可以通过使用ftrace记录跟踪来找到其他来源(当您的测试二进制文件正在运行时)。
因为它出现在评论中:是的,SMI 对内核是完全透明的。它不显示为 NMI。您只能间接检测 SMI。
归档时间: |
|
查看次数: |
2605 次 |
最近记录: |