我使用具有相对较新内核的 Linux cgroup 安装了两个双核 Linux 系统;一个运行 Debian Squeeze,另一个运行 Ubuntu 11.04 Natty Narwhal。尽管 Debian 系统的内核较旧,但我已经通过 cgroups 实现了 CPU 负载平衡,在 Debian 系统上工作得更好一些。但它并不适合所有情况,我在这里询问的具体奇怪现象发生在两个系统上。
如果你读过Linux 中的资源管理与控制组它给出了一个示例,展示了如何重现该问题。这是 Ubuntu 版本(以 root 身份运行):
cd /sys/fs/cgroup/cpu
[On Debian Squeeze start at /mnt/cgroups/cpu instead]
mkdir low high
echo 512 > low/cpu.shares
echo 2048 > high/cpu.shares
yes low > /dev/null &
echo $! > low/tasks
yes high > /dev/null &
echo $! > high/tasks
ps -C yes -opid,%cpu,psr,args
[repeat that a few times]
killall -9 yes
我预计“高”进程会比“低”进程分配更多的时间;这个测试用例实际发生的情况总是更像这样:
root@black:/sys/fs/cgroup/cpu# ps -C yes -opid,%cpu,psr,args
PID %CPU PSR COMMAND
3105 88.3 1 yes low
3106 94.5 0 yes high
时间几乎相等的地方。这是我的问题:为什么会发生这种情况?
在演示中,通过将每个进程固定到同一个 CPU,这个问题就会消失。额外的行来测试:
taskset -c 1 yes high > /dev/null &
echo $! > high/tasks
taskset -c 1 yes low > /dev/null &
echo $! > low/tasks
ps -C yes -opid,%cpu,psr,args
[later, rinse, repeat]
killall -9 yes
结果就是我一直期望看到的:“高”进程获得了更高的 CPU 百分比:
root@black:/sys/fs/cgroup/cpu# ps -C yes -opid,%cpu,psr,args
PID %CPU PSR COMMAND
3128 83.3 1 yes high
3129 20.7 1 yes low
解释为什么这个有效将是一个有用的步骤,可以帮助我们弄清楚为什么之前的一个也不起作用。
答案1
我从 Stefan Seyfried 那里得到了关于这个测试用例的初步解释,他撰写了这个示例的论文。这里的问题是 cgroup 的 CPU 调度程序部分始终旨在保持任何可用的 CPU 忙碌;如果一切都能同时满足,它就不会强制执行硬性限制。
如果两个进程(此处为高进程和低进程)在 >=2 个内核上运行,则它只会在一个内核上保持高电平,在另一个内核上保持低电平。然后,两者都会以接近 100% 的使用率一直运行,因为它们可以这样做,而不会遇到调度程序没有为它们提供足够的 CPU 时间的情况。 cpu.share 调度仅在出现短缺时才会发生。
在第二种情况下,两个进程都固定在同一个 CPU 上。然后,CPU 共享逻辑必须对相对 cpu.shares 数字执行一些有用的操作来平衡它们,并且它按照希望做到了这一点。
对 CPU 使用率的硬限制只有在以下情况之后才会出现:CFS 带宽控制补丁命中。到那时,可能会得到更像我所希望的东西。