内核调度程序如何通过定时器中断保持时间量子精度?
How does the kernel scheduler maintain time quanta precision with timer interrupts?
根据我的阅读,硬件调用了一个计时器中断,它经常执行并将控制权从 运行ning 进程转移回 kernel/scheduler,然后该 kernel/scheduler 能够确定 运行ning 进程已超过其时间量,如果是,则 运行 另一个任务。
这似乎不准确。
例如:
如果定时器中断是每 1 个单位
并且调度程序算法确定 cpu 绑定进程时间份额为 1.5 个单位,它实际上会获得 2 个单位的 CPU 时间。
或者调度程序是否仅以中断计时器为单位向进程提供时间份额?
Linux的调度程序(CFS)通过首先定义一个时间段来为线程分配时间片,在该时间段内每个线程都会运行一次。此时间段由 sched_slice() 函数计算,取决于 CPU 上的线程数,以及可从用户 space 设置的 2 个变量(sysctl_sched_latency
和 sysctl_sched_min_granularity
):
如果线程数大于sysctl_sched_latency / sysctl_sched_min_granularity
;那么周期将是nr_threads * sysctl_sched_min_granularity
;否则周期将是 sysctl_sched_latency
.
例如,在我的笔记本电脑上,我有以下值:
% cat /proc/sys/kernel/sched_latency_ns
18000000
% cat /proc/sys/kernel/sched_min_granularity_ns
2250000
因此,sysctl_sched_latency / sysctl_sched_min_granularity = 8
。现在,如果 CPU 上的线程少于 8 个,那么每个线程将分配 18.000.000 纳秒(即 18 毫秒);否则,每个将分配 2.250.000 ns(2.25 ms)。
现在,考虑到这些值,如果我们使用此命令查看节拍频率(在内核编译时定义):
% zcat /proc/config.gz | grep CONFIG_HZ
# CONFIG_HZ_PERIODIC is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
CONFIG_HZ_300=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=300
所以,在我的笔记本电脑上,我每秒有 300 个滴答声,这意味着每 3 毫秒一个滴答声。这意味着在我的例子中,CPU 上有超过 8 个线程,我会在我的时间片中失去一点精度(一个应该 运行 2.25 毫秒的线程将 运行 3 毫秒),但我可以通过更频繁地重新编译我的内核来修复它。
不过需要注意的是,这其实不是问题,因为CFS(Completely Fair Scheduler)正如其名,其目标就是公平,这里也将是这样。
根据我的阅读,硬件调用了一个计时器中断,它经常执行并将控制权从 运行ning 进程转移回 kernel/scheduler,然后该 kernel/scheduler 能够确定 运行ning 进程已超过其时间量,如果是,则 运行 另一个任务。
这似乎不准确。
例如: 如果定时器中断是每 1 个单位
并且调度程序算法确定 cpu 绑定进程时间份额为 1.5 个单位,它实际上会获得 2 个单位的 CPU 时间。
或者调度程序是否仅以中断计时器为单位向进程提供时间份额?
Linux的调度程序(CFS)通过首先定义一个时间段来为线程分配时间片,在该时间段内每个线程都会运行一次。此时间段由 sched_slice() 函数计算,取决于 CPU 上的线程数,以及可从用户 space 设置的 2 个变量(sysctl_sched_latency
和 sysctl_sched_min_granularity
):
如果线程数大于sysctl_sched_latency / sysctl_sched_min_granularity
;那么周期将是nr_threads * sysctl_sched_min_granularity
;否则周期将是 sysctl_sched_latency
.
例如,在我的笔记本电脑上,我有以下值:
% cat /proc/sys/kernel/sched_latency_ns
18000000
% cat /proc/sys/kernel/sched_min_granularity_ns
2250000
因此,sysctl_sched_latency / sysctl_sched_min_granularity = 8
。现在,如果 CPU 上的线程少于 8 个,那么每个线程将分配 18.000.000 纳秒(即 18 毫秒);否则,每个将分配 2.250.000 ns(2.25 ms)。
现在,考虑到这些值,如果我们使用此命令查看节拍频率(在内核编译时定义):
% zcat /proc/config.gz | grep CONFIG_HZ
# CONFIG_HZ_PERIODIC is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
CONFIG_HZ_300=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=300
所以,在我的笔记本电脑上,我每秒有 300 个滴答声,这意味着每 3 毫秒一个滴答声。这意味着在我的例子中,CPU 上有超过 8 个线程,我会在我的时间片中失去一点精度(一个应该 运行 2.25 毫秒的线程将 运行 3 毫秒),但我可以通过更频繁地重新编译我的内核来修复它。
不过需要注意的是,这其实不是问题,因为CFS(Completely Fair Scheduler)正如其名,其目标就是公平,这里也将是这样。