主要介绍Linux下, 如果对进程的CPU和内存资源的使用情况进行控制的方法。
CPU资源控制每个进程能够占用CPU多长时间, 什么时候能够占用CPU是和系统的调度密切相关的.
Linux系统中有多种调度策略, 各种调度策略有其适用的场景, 也很难说哪种调度策略是最优的.
Linux的调度策略可以参见代码: include/linux/sched.h
/* * Scheduling policies */#define SCHED_NORMAL 0#define SCHED_FIFO 1#define SCHED_RR 2#define SCHED_BATCH 3/* SCHED_ISO: reserved but not implemented yet */#define SCHED_IDLE 5/* Can be ORed in to make sure the PRocess is reverted back to SCHED_NORMAL on fork */#define SCHED_RESET_ON_FORK 0x40000000
Linux 系统也提供了修改调度策略的命令和系统调用接口.
调用接口请查询相关文档, 这里主要介绍一下修改调度策略的命令 - chrt.
# 在一个终端中执行sleep 1000# 打开另一个终端ps -ef | grep sleep # 找出 sleep 1000 的pid, 这里假设是 1234chrt -p 1234 # 可以查看 pid=1234 的进程的 调度策略, 输入如下: pid 1234's current scheduling policy: SCHED_OTHER pid 1234's current scheduling priority: 0chrt -p -f 10 1234 # 修改调度策略为 SCHED_FIFO, 并且优先级为10chrt -p 1234 # 再次查看调度策略 pid 1234's current scheduling policy: SCHED_FIFO pid 1234's current scheduling priority: 10
补充:
所谓的实时进程, 也就是那些对响应时间要求比较高的进程.
这类进程需要在限定的时间内处理用户的请求, 因此, 在限定的这段时间内, 需要占用所有CPU资源, 并且不能被其它进程打断.
在这种情况下, 如果实时进程中出现了类似死循环之类的情况, 就会导致整个系统无响应.
因为实时进程的CPU优先级高, 并且未处理完之前是不会释放CPU资源的.
所以, 内核中需要有一种方式来限制实时进程的CPU资源占用.
系统整体设置1. 获取当前系统的设置
sysctl -n kernel.sched_rt_period_us # 实时进程调度的单位CPU时间 1 秒1000000sysctl -n kernel.sched_rt_runtime_us # 实时进程在 1 秒中实际占用的CPU时间, 0.95秒950000
这个设置说明实时进程在运行时并不是完全占用CPU的, 每1秒中有0.05秒的时间可以给其它进程运行.
这样既不会对实时进程的响应时间造成太大的影响, 也避免了实时进程卡住时导致整个系统无响应.
2. 设置实时进程占用CPU时间
上面的默认设置中, 实时进程占用 95% 的CPU时间. 如果觉得占用的太多或太少, 都是可以调整的.比如:
sysctl -w kernel.sched_rt_runtime_us=900000 # 设置实时进程每1秒中只占0.9秒的CPU时间kernel.sched_rt_runtime_us = 900000sysctl -n kernel.sched_rt_runtime_us 900000cgroup 中的设置
整体设置是针对整个系统的, 我们也可以通过 cgroup 来对一组进程的CPU资源进行控制.
如果想在 cgroup 中对 sched_rt_period_us 和 sched_rt_runtime_us 进行控制, 需要内核编译选项 CONFIG_RT_GROUP_SCHED=y
查看当前系统的内核编译选项方法如下: (debian 7.6 系统)
cat /boot/config-`uname -r`
查看 CONFIG_RT_GROUP_SCHED 是否启用
cat /boot/config-`uname -r` | grep -i rt_group# CONFIG_RT_GROUP_SCHED is not set
debian 7.6 默认没有启动这个选项, 所以挂载cgroup之后, 没有设置 sched_rt_period_us 和 sched_rt_runtime_us 的文件
mkdir /mnt/cgroupmount -t cgroup cgroup /mnt/cgroup/cd /mnt/cgroup/ls -ltotal 0-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_merged-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_queued-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_service_bytes-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_serviced-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_service_time-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_wait_time--w------- 1 root root 0 Aug 28 09:06 blkio.reset_stats-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.sectors-r--r--r-- 1 root root 0 Aug 28 09:06 blkio.time-rw-r--r-- 1 root root 0 Aug 28 09:06 blkio.weight-rw-r--r-- 1 root root 0 Aug 28 09:06 blkio.weight_device-rw-r--r-- 1 root root 0 Aug 28 09:06 cgroup.clone_children--w--w--w- 1 root root 0 Aug 28 09:06 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 28 09:06 cgroup.procs-r--r--r-- 1 root root 0 Aug 28 09:06 cpuacct.stat-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuacct.usage-r--r--r-- 1 root root 0 Aug 28 09:06 cpuacct.usage_percpu-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 28 09:06 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.memory_pressure_enabled-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.mems-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 28 09:06 cpu.shares--w------- 1 root root 0 Aug 28 09:06 devices.allow--w------- 1 root root 0 Aug 28 09:06 devices.deny-r--r--r-- 1 root root 0 Aug 28 09:06 devices.list-rw-r--r-- 1 root root 0 Aug 28 09:06 net_cls.classid-rw-r--r-- 1 root root 0 Aug 28 09:06 notify_on_release-rw-r--r-- 1 root root 0 Aug 28 09:06 release_agent-rw-r--r-- 1 root root 0 Aug 28 09:06 tasks
果然, 只有cpu.share, 没有 cpu.sched_rt_period_us 和 cpu.sched_rt_runtime_us
没办法, 重新编译内核, 编译内核的具体方法参见: 编译Linux内核
为了节约时间, 我们用 make localmodconfig 来创建 .config 文件, 然后修改其中的 CONFIG_RT_GROUP_SCHED=y
下载源码等等参见: 编译Linux内核, 主要步骤如下:
cd /path/to/linux-source-3.2make localmodconfigvim .config # 设置 CONFIG_RT_GROUP_SCHED=y 并保存makemake modules_installmake installreboot # 重启之前看看 /boot/grub/grub.cfg 中, 默认启动的是不是新安装的内核
启动到新内核, 再次查看内核选项 CONFIG_RT_GROUP_SCHED 是否启用
cat /boot/config-`uname -r` | grep -i rt_groupCONFIG_RT_GROUP_SCHED=y # 已启用
再次挂载 cgroup 文件系统, 发现多了2个配置文件, cpu.rt_period_us 和 cpu.rt_runtime_us
mount -t cgroup cgroup /mnt/cgroup/cd /mnt/cgroup/ls -ltotal 0-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_merged-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_queued-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_service_bytes-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_serviced-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_service_time-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_wait_time--w------- 1 root root 0 Aug 28 09:53 blkio.reset_stats-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.sectors-r--r--r-- 1 root root 0 Aug 28 09:53 blkio.time-rw-r--r-- 1 root root 0 Aug 28 09:53 blkio.weight-rw-r--r-- 1 root root 0 Aug 28 09:53 blkio.weight_device-rw-r--r-- 1 root root 0 Aug 28 09:53 cgroup.clone_children--w--w--w- 1 root root 0 Aug 28 09:53 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 28 09:53 cgroup.procs-r--r--r-- 1 root root 0 Aug 28 09:53 cpuacct.stat-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuacct.usage-r--r--r-- 1 root root 0 Aug 28 09:53 cpuacct.usage_percpu-rw-r--r-- 1 root root 0 Aug 28 09:53 cpu.rt_period_us-rw-r--r-- 1 root root 0 Aug 28 09:53 cpu.rt_runtime_us-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 28 09:53 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.memory_pressure_enabled-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.mems-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 28 09:53 cpu.shares--w------- 1 root root 0 Aug 28 09:53 devices.allow--w------- 1 root root 0 Aug 28 09:53 devices.deny-r--r--r-- 1 root root 0 Aug 28 09:53 devices.list-rw-r--r-- 1 root root 0 Aug 28 09:53 net_cls.classid-rw-r--r-- 1 root root 0 Aug 28 09:53 notify_on_release-rw-r--r-- 1 root root 0 Aug 28 09:53 release_agent-rw-r--r-- 1 root root 0 Aug 28 09:53 taskscat cpu.rt_period_us 1000000cat cpu.rt_runtime_us 950000
通过配置 cpu.rt_period_us 和 cpu.rt_runtime_us 就可以对 cgroup 中的进程组中的实时进程进行 CPU使用时间的控制.
资源控制实例上面主要介绍资源的一些理论基础, 下面通过一些实例演示如果通过 cgroup 来控制进程所使用的 CPU和内存 资源.
Linux对CPU 和 内存的控制有对应的 cgroup 子系统 cpuset 和 memory
实例: cgroup 中对其中 *子cgroup* 的CPU资源控制对各个 *子cgroup* 的CPU占用率进行控制主要依靠每个 *子cgroup* 的 cpu.shares 文件
直接用实验过程来说话, 其中加入了一些注释.
# 安装需要的软件apt-get install stress # 让CPU达到 100% 的压力工具apt-get install sysstat # 查看系统CPU, 内存, 磁盘, 网络等资源使用情况的工具实例1 - 默认情况, A 和 B 各占CPU总资源的 1/2
# 挂载 cgroup 文件系统mount -t cgroup -o cpu cgroup /mnt/cgroup/cd /mnt/cgroupls -ltotal 0-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_merged-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_queued-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_service_bytes-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_serviced-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_service_time-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_wait_time--w------- 1 root root 0 Aug 28 11:29 blkio.reset_stats-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.sectors-r--r--r-- 1 root root 0 Aug 28 11:29 blkio.time-rw-r--r-- 1 root root 0 Aug 28 11:29 blkio.weight-rw-r--r-- 1 root root 0 Aug 28 11:29 blkio.weight_device-rw-r--r-- 1 root root 0 Aug 28 11:29 cgroup.clone_children--w--w--w- 1 root root 0 Aug 28 11:29 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 28 11:29 cgroup.procs-r--r--r-- 1 root root 0 Aug 28 11:29 cpuacct.stat-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuacct.usage-r--r--r-- 1 root root 0 Aug 28 11:29 cpuacct.usage_percpu-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 28 11:29 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.memory_pressure_enabled-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.mems-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 28 11:29 cpu.shares--w------- 1 root root 0 Aug 28 11:29 devices.allow--w------- 1 root root 0 Aug 28 11:29 devices.deny-r--r--r-- 1 root root 0 Aug 28 11:29 devices.list-rw-r--r-- 1 root root 0 Aug 28 11:29 net_cls.classid-rw-r--r-- 1 root root 0 Aug 28 11:29 notify_on_release-rw-r--r-- 1 root root 0 Aug 28 11:29 release_agent-rw-r--r-- 1 root root 0 Aug 28 11:29 tasks# 创建 子cgroup A 和 Bmkdir {A,B}cat A/cpu.shares 1024cat B/cpu.shares 1024# 在 A 和 B 中分别通过 stress 工具使其CPU使用率达到 100%echo $$ > A/tasks # 将当前的 SHELL 加入到 cgroup A中stress -c 2 # 这里-c 2 是因为测试机器是双核, 要在2个核上都产生 100% 的CPU 占用率# 另外打开一个 shell 窗口, 并将这个shell 加入到 cgroup B中echo $$ > B/tasks # 将当前的 SHELL 加入到 cgroup B中stress -c 2 # 在2个核上都产生 100% 的CPU 占用率# 再打开一个 shell 窗口, 用top命令查看 CPU占用情况toptop - 14:10:32 up 43 min, 3 users, load average: 2.31, 1.24, 0.62Tasks: 78 total, 5 running, 73 sleeping, 0 stopped, 0 zombie%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 1887872 total, 114744 used, 1773128 free, 10472 buffersKiB Swap: 3982332 total, 0 used, 3982332 free, 45068 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3350 root 20 0 6524 92 0 R 49.9 0.0 0:08.73 stress 3351 root 20 0 6524 92 0 R 49.9 0.0 0:08.67 stress 3353 root 20 0 6524 92 0 R 49.9 0.0 0:07.35 stress 3354 root 20 0 6524 92 0 R 49.9 0.0 0:07.36 stress # 查看这 4 个stress 进程是否分别属于 A 和 Bcat /mnt/cgroup/A/tasks 294533493350 <-- stress 进程3351 <-- stress 进程cat /mnt/cgroup/B/tasks 299633523353 <-- stress 进程3354 <-- stress 进程
可以看出, A和B组中的 2个stress 进程的CPU使用率相加都是 100%,
由于我测试的电脑是双核, top所看到的CPU最大使用率是 200%, 所以和预期一致, A和B组各占CPU总资源的 1/2
实例2 - A group 占用整体CPU资源的 2/3, B group 占用整体CPU资源的 1/3# 在 B 中shell 窗口执行以下命令cat B/cpu.shares 1024echo 512 > B/cpu.shares cat B/cpu.shares 512stress -c 2# 在 A 中 shell 窗口执行以下命令stress -c 2# 在第3个 shell 窗口, 也就是 非A, 非B 的那个 shell 窗口, 用 top 查看cpu使用情况toptop - 14:13:18 up 46 min, 3 users, load average: 2.24, 1.92, 1.01Tasks: 78 total, 5 running, 73 sleeping, 0 stopped, 0 zombie%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 1887872 total, 114744 used, 1773128 free, 10488 buffersKiB Swap: 3982332 total, 0 used, 3982332 free, 45068 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3376 root 20 0 6524 88 0 R 66.6 0.0 0:06.29 stress 3377 root 20 0 6524 88 0 R 66.6 0.0 0:06.30 stress 3373 root 20 0 6524 88 0 R 33.3 0.0 0:04.33 stress 3374 root 20 0 6524 88 0 R 33.3 0.0 0:04.32 stress # 查看这 4 个stress 进程是否分别属于 A 和 Bcat /mnt/cgroup/A/tasks 294533753376 <-- stress 进程3377 <-- stress 进程cat /mnt/cgroup/B/tasks 299633723373 <-- stress 进程3374 <-- stress 进程
很明显, A 组中的2个进程占用了CPU总量的 2/3 左右, B组中的2个进程占用了CPU总量的 1/3 左右.
实例3 - 物理CPU的控制上面的实例中, 虽然能够控制每个组的CPU的总体占用率, 但是不能控制某个组的进程固定在某个物理CPU上运行.
要想将 cgroup 绑定到某个固定的CPU上, 需要使用 cpuset 子系统.
首先, 查看系统是否支持 cpuset 子系统, 也就是看内核编译选项 CONFIG_CPUSETS 是否设为y
cat /boot/config-`uname -r` | grep -i cpusetsCONFIG_CPUSETS=y
我的测试系统是支持的, 如果你的系统不支持, 就需要重新编译内核了.......
然后, 用下面的例子演示将 A 和 B中的 stress 都指定到1个CPU上后的情况
umount /mnt/cgroupmount -t cgroup -o cpuset cgroup /mnt/cgroup/cd /mnt/cgroupls -ltotal 0-rw-r--r-- 1 root root 0 Aug 28 14:39 cgroup.clone_children--w--w--w- 1 root root 0 Aug 28 14:39 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 28 14:39 cgroup.procs-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.cpus <-- 这个就是设置关联物理CPU的文件-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 28 14:39 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.memory_pressure_enabled-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.mems-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 28 14:39 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 28 14:39 notify_on_release-rw-r--r-- 1 root root 0 Aug 28 14:39 release_agent-rw-r--r-- 1 root root 0 Aug 28 14:39 tasks# 创建子cgroup A 和 Bmkdir {A,B}cat A/cpuset.cpus <-- 默认是空的echo 0 > A/cpuset.cpuscat A/cpuset.cpus 0echo 0 > B/cpuset.cpus # 同样, 设置B组也绑定到CPU0# 当前Shell加入到 A组echo $$ > /mnt/cgroup/A/tasks -bash: echo: write error: No space left on device
如果出现上述错误, 只需要再设置 /mnt/cgroup/A/cpuset.mems 即可. (参考: http://serverfault.com/questions/579555/cgroup-no-space-left-on-device)
# 同时设置 A 的 cpuset.cpus 和 cpuset.memsecho 0 > A/cpuset.cpusecho 0 > A/cpuset.mems# B组也同样设置echo 0 > B/cpuset.cpusecho 0 > B/cpuset.mems# 将当前 shell 加入到 A组echo $$ > /mnt/cgroup/A/tasks <-- 设置过 cpuset.mems 后, 就没有出错了stress -c 2# 再打开一个Shell窗口, 并加入到 B组echo $$ > /mnt/cgroup/B/tasksstress -c 2# 再打开第3个 shell 窗口, 用top命令查看CPU使用情况toptop - 15:13:29 up 1:46, 3 users, load average: 1.01, 0.24, 0.12Tasks: 78 total, 5 running, 73 sleeping, 0 stopped, 0 zombie%Cpu(s): 50.0 us, 0.0 sy, 0.0 ni, 50.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 1887872 total, 117216 used, 1770656 free, 11144 buffersKiB Swap: 3982332 total, 0 used, 3982332 free, 47088 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3830 root 20 0 6524 92 0 R 25.0 0.0 0:04.96 stress 3831 root 20 0 6524 92 0 R 25.0 0.0 0:04.97 stress 3834 root 20 0 6524 92 0 R 25.0 0.0 0:03.56 stress 3833 root 20 0 6524 92 0 R 24.6 0.0 0:03.56 stress
从上面的结果可以看出, 虽然 stress 命令指定了 -c 2(意思是在2个CPU上运行), 但是由于A和B都只绑定了CPU0,
所以虽然是双核的机器, 它们所占用的CPU总量却只有 100%, 而不是实例1 中的 200%.
如果将B组的物理CPU绑定到CPU1, 那么应该所有 stress 的进程都占用 50%, CPU资源的总量变为 200%.
下面将B组的物理CPU绑定为CPU1, 看看结果是否和我们的预期一样.
# 在 B组的 shell 窗口中执行以下命令echo 1 > /mnt/cgroup/B/cpuset.cpuscat /mnt/cgroup/B/cpuset.cpus1stress -c 2# 在 A组的 shell 窗口中执行以下命令stress -c 2# 在第3个shell窗口中用top命令查看执行结果toptop - 15:20:07 up 1:53, 3 users, load average: 0.38, 0.83, 0.56Tasks: 78 total, 5 running, 73 sleeping, 0 stopped, 0 zombie%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem: 1887872 total, 117340 used, 1770532 free, 11168 buffersKiB Swap: 3982332 total, 0 used, 3982332 free, 47088 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3854 root 20 0 6524 88 0 R 49.9 0.0 0:03.76 stress 3857 root 20 0 6524 92 0 R 49.9 0.0 0:02.29 stress 3858 root 20 0 6524 92 0 R 49.9 0.0 0:02.29 stress 3855 root 20 0 6524 88 0 R 49.6 0.0 0:03.76 stress
果然, 和预期一致. A组中的 stress 和 B组中的 stress 在各自的物理CPU上都占用了 100% 左右的CPU使用率.
实例4 - cgroup 对使用的内存的控制cgroup 对内存的控制也很简单, 只要挂载cgroup时, 指定 -o memory
# 首先之前挂载的 cpuset 子系统umount /mnt/cgroup# 挂载cgroup 文件系统, 指定 -o memeorymount -o memory -t cgroup memcg /mnt/cgroup/mount: special device memcg does not exist
出现以上错误的原因可能是因为debian系统中, 默认没有启动 cgroup 的memory子系统. 可以通过以下方法确认:
cat /proc/cgroups #subsys_name hierarchy num_cgroups enabledcpuset 0 1 1cpu 0 1 1cpuacct 0 1 1memory 1 1 0 <-- 这里的 enabled 是 0devices 0 1 1freezer 0 1 1net_cls 0 1 1blkio 0 1 1perf_event 0 1 1
为了默认启用memory子系统, 可以设置 grub选项
vim /etc/default/grub# 修改 GRUB_CMDLINE_LINUX="" ==> GRUB_CMDLINE_LINUX="cgroup_enable=memory"# 保存后, 更新grub.cfgupdate-grubreboot
重启之后, 发现 /proc/cgroups 中的memory已经 enabled, 并且也可以挂载 memcg了
cat /proc/cgroups #subsys_name hierarchy num_cgroups enabledcpuset 0 1 1cpu 0 1 1cpuacct 0 1 1memory 1 1 1devices 0 1 1freezer 0 1 1net_cls 0 1 1blkio 0 1 1perf_event 0 1 1# 挂载cgroup 的memory子系统mount -t cgroup -o memory memcg /mnt/cgroupls -l /mnt/cgroup/ <-- 可以看到有很多 memory 相关的配置total 0-rw-r--r-- 1 root root 0 Aug 28 15:54 cgroup.clone_children--w--w--w- 1 root root 0 Aug 28 15:54 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 28 15:54 cgroup.procs-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.failcnt--w------- 1 root root 0 Aug 28 15:54 memory.force_empty-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.limit_in_bytes <-- 限制内存使用的配置文件-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.max_usage_in_bytes-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.move_charge_at_immigrate-r--r--r-- 1 root root 0 Aug 28 15:54 memory.numa_stat-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.oom_control-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.soft_limit_in_bytes-r--r--r-- 1 root root 0 Aug 28 15:54 memory.stat-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.swappiness-r--r--r-- 1 root root 0 Aug 28 15:54 memory.usage_in_bytes-rw-r--r-- 1 root root 0 Aug 28 15:54 memory.use_hierarchy-rw-r--r-- 1 root root 0 Aug 28 15:54 notify_on_release-rw-r--r-- 1 root root 0 Aug 28 15:54 release_agent-rw-r--r-- 1 root root 0 Aug 28 15:54 tasks
开始实验:
# 重启系统reboot# 挂载 memcgmount -t cgroup -o memory memcg /mnt/cgroup# 创建 组Amkdir /mnt/cgroup/A# 将当前 shell 加入到组Aecho $$ > /mnt/cgroup/A/tasks# 测试不限制内存时, 内存的使用情况, 这里不用linux源码也可以, 但最好用个大点的文件夹来压缩, 以便更容易看出内存的变化.free -m; tar czvf linux-source-3.2.tar.gz /path/to/linux-source-3.2/ > /dev/null; free -m; total used free shared buffers cachedMem: 1843 122 1721 0 9 43-/+ buffers/cache: 68 1774Swap: 3888 0 3888 total used free shared buffers cachedMem: 1843 1744 99 0 26 1614-/+ buffers/cache: 104 1739Swap: 3888 0 3888# 重启系统reboot# 挂载 memcgmount -t cgroup -o memory memcg /mnt/cgroup# 创建 组Amkdir /mnt/cgroup/A# 将当前 shell 加入到组Aecho $$ > /mnt/cgroup/A/tasks# 限制 组A 的内存使用量最大为 10MBecho 10M > /mnt/cgroup/A/memory.limit_in_bytes# 测试限制内存为 10MB 时, 内存的使用情况.rm -rf linux-source-3.2.tar.gzfree -m; tar czvf linux-source-3.2.tar.gz /path/to/linux-source-3.2/ > /dev/null; free -m; total used free shared buffers cachedMem: 1843 122 1721 0 10 43-/+ buffers/cache: 68 1774Swap: 3888 0 3888 total used free shared buffers cachedMem: 1843 194 1649 0 14 48-/+ buffers/cache: 131 1712Swap: 3888 0 3888
从上面的结果可以看出限制内存是起了作用的.
不限制内存时, tar 压缩前后 buffer + cache 内存从 (9MB + 43MB) ==> (26MB + 1614MB) 增大了 1588MB
限制内存后, tar 压缩前后 buffer + cache 内存从 (10MB + 43MB) ==> (14MB + 48MB) 增大了 9MB
总结简单的实验就发现 cgroup 如此强大的控制能力(而且配置也很简单), 这也就难怪LXC等容器技术能如此强大, 如此流行.
cgroup 的配置文件很多, 上面的实例中只简单使用了其中的几个配置文件, 如果想深入了解 cgroup, 更好的利用cgroup的话,
还得找个介绍cgroup配置文件的文档来研究一下, 这篇博客提供的内容还远远不够.
新闻热点
疑难解答