主要介绍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
# 打开另一个终端
ps -ef | grep sleep # 找出 sleep 的pid, 这里假设是
chrt -p # 可以查看 pid= 的进程的 调度策略, 输入如下:
pid 's current scheduling policy: SCHED_OTHER
pid 's current scheduling priority: 0 chrt -p -f # 修改调度策略为 SCHED_FIFO, 并且优先级为10
chrt -p # 再次查看调度策略
pid 's current scheduling policy: SCHED_FIFO
pid 's current scheduling priority: 10

补充:

  1. chrt 也可以直接指定一条命令, 并设置这条命令的优先级的调度策略, 具体查看 chrt --help
  2. 查看一个进程的调度策略, 除了使用 chrt 命令之外, 还可以 cat /proc/<PID>/sched

实时进程的CPU控制

所谓的实时进程, 也就是那些对响应时间要求比较高的进程.

这类进程需要在限定的时间内处理用户的请求, 因此, 在限定的这段时间内, 需要占用所有CPU资源, 并且不能被其它进程打断.

在这种情况下, 如果实时进程中出现了类似死循环之类的情况, 就会导致整个系统无响应.

因为实时进程的CPU优先级高, 并且未处理完之前是不会释放CPU资源的.

所以, 内核中需要有一种方式来限制实时进程的CPU资源占用.

系统整体设置

1. 获取当前系统的设置

sysctl -n kernel.sched_rt_period_us   # 实时进程调度的单位CPU时间  秒

sysctl -n kernel.sched_rt_runtime_us  # 实时进程在  秒中实际占用的CPU时间, .95秒

这个设置说明实时进程在运行时并不是完全占用CPU的, 每1秒中有0.05秒的时间可以给其它进程运行.

这样既不会对实时进程的响应时间造成太大的影响, 也避免了实时进程卡住时导致整个系统无响应.

2. 设置实时进程占用CPU时间

上面的默认设置中, 实时进程占用 95% 的CPU时间. 如果觉得占用的太多或太少, 都是可以调整的.比如:

sysctl -w kernel.sched_rt_runtime_us=    # 设置实时进程每1秒中只占0.9秒的CPU时间
kernel.sched_rt_runtime_us =
sysctl -n kernel.sched_rt_runtime_us

cgroup 中的设置

整体设置是针对整个系统的, 我们也可以通过 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/cgroup
mount -t cgroup cgroup /mnt/cgroup/
cd /mnt/cgroup/
ls -l
total
-r--r--r-- root root Aug : blkio.io_merged
-r--r--r-- root root Aug : blkio.io_queued
-r--r--r-- root root Aug : blkio.io_service_bytes
-r--r--r-- root root Aug : blkio.io_serviced
-r--r--r-- root root Aug : blkio.io_service_time
-r--r--r-- root root Aug : blkio.io_wait_time
--w------- root root Aug : blkio.reset_stats
-r--r--r-- root root Aug : blkio.sectors
-r--r--r-- root root Aug : blkio.time
-rw-r--r-- root root Aug : blkio.weight
-rw-r--r-- root root Aug : blkio.weight_device
-rw-r--r-- root root Aug : cgroup.clone_children
--w--w--w- root root Aug : cgroup.event_control
-rw-r--r-- root root Aug : cgroup.procs
-r--r--r-- root root Aug : cpuacct.stat
-rw-r--r-- root root Aug : cpuacct.usage
-r--r--r-- root root Aug : cpuacct.usage_percpu
-rw-r--r-- root root Aug : cpuset.cpu_exclusive
-rw-r--r-- root root Aug : cpuset.cpus
-rw-r--r-- root root Aug : cpuset.mem_exclusive
-rw-r--r-- root root Aug : cpuset.mem_hardwall
-rw-r--r-- root root Aug : cpuset.memory_migrate
-r--r--r-- root root Aug : cpuset.memory_pressure
-rw-r--r-- root root Aug : cpuset.memory_pressure_enabled
-rw-r--r-- root root Aug : cpuset.memory_spread_page
-rw-r--r-- root root Aug : cpuset.memory_spread_slab
-rw-r--r-- root root Aug : cpuset.mems
-rw-r--r-- root root Aug : cpuset.sched_load_balance
-rw-r--r-- root root Aug : cpuset.sched_relax_domain_level
-rw-r--r-- root root Aug : cpu.shares
--w------- root root Aug : devices.allow
--w------- root root Aug : devices.deny
-r--r--r-- root root Aug : devices.list
-rw-r--r-- root root Aug : net_cls.classid
-rw-r--r-- root root Aug : notify_on_release
-rw-r--r-- root root Aug : release_agent
-rw-r--r-- root root Aug : 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.2
make localmodconfig
vim .config # 设置 CONFIG_RT_GROUP_SCHED=y 并保存
make
make modules_install
make install
reboot # 重启之前看看 /boot/grub/grub.cfg 中, 默认启动的是不是新安装的内核
 

启动到新内核, 再次查看内核选项 CONFIG_RT_GROUP_SCHED 是否启用

cat /boot/config-`uname -r` | grep -i rt_group
CONFIG_RT_GROUP_SCHED=y # 已启用

再次挂载 cgroup 文件系统, 发现多了2个配置文件, cpu.rt_period_us 和 cpu.rt_runtime_us

mount -t cgroup cgroup /mnt/cgroup/
cd /mnt/cgroup/
ls -l
total
-r--r--r-- root root Aug : blkio.io_merged
-r--r--r-- root root Aug : blkio.io_queued
-r--r--r-- root root Aug : blkio.io_service_bytes
-r--r--r-- root root Aug : blkio.io_serviced
-r--r--r-- root root Aug : blkio.io_service_time
-r--r--r-- root root Aug : blkio.io_wait_time
--w------- root root Aug : blkio.reset_stats
-r--r--r-- root root Aug : blkio.sectors
-r--r--r-- root root Aug : blkio.time
-rw-r--r-- root root Aug : blkio.weight
-rw-r--r-- root root Aug : blkio.weight_device
-rw-r--r-- root root Aug : cgroup.clone_children
--w--w--w- root root Aug : cgroup.event_control
-rw-r--r-- root root Aug : cgroup.procs
-r--r--r-- root root Aug : cpuacct.stat
-rw-r--r-- root root Aug : cpuacct.usage
-r--r--r-- root root Aug : cpuacct.usage_percpu
-rw-r--r-- root root Aug : cpu.rt_period_us
-rw-r--r-- root root Aug : cpu.rt_runtime_us
-rw-r--r-- root root Aug : cpuset.cpu_exclusive
-rw-r--r-- root root Aug : cpuset.cpus
-rw-r--r-- root root Aug : cpuset.mem_exclusive
-rw-r--r-- root root Aug : cpuset.mem_hardwall
-rw-r--r-- root root Aug : cpuset.memory_migrate
-r--r--r-- root root Aug : cpuset.memory_pressure
-rw-r--r-- root root Aug : cpuset.memory_pressure_enabled
-rw-r--r-- root root Aug : cpuset.memory_spread_page
-rw-r--r-- root root Aug : cpuset.memory_spread_slab
-rw-r--r-- root root Aug : cpuset.mems
-rw-r--r-- root root Aug : cpuset.sched_load_balance
-rw-r--r-- root root Aug : cpuset.sched_relax_domain_level
-rw-r--r-- root root Aug : cpu.shares
--w------- root root Aug : devices.allow
--w------- root root Aug : devices.deny
-r--r--r-- root root Aug : devices.list
-rw-r--r-- root root Aug : net_cls.classid
-rw-r--r-- root root Aug : notify_on_release
-rw-r--r-- root root Aug : release_agent
-rw-r--r-- root root Aug : tasks cat cpu.rt_period_us cat cpu.rt_runtime_us

通过配置 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达到 % 的压力工具
apt-get install sysstat # 查看系统CPU, 内存, 磁盘, 网络等资源使用情况的工具
实例1 - 默认情况, A 和 B 各占CPU总资源的 1/2
  1. 挂载 cgroup 文件系统 (注意加上 -o cpu 的选项)
  2. 在 cgroup中创建 2个子cgroup A 和 B
  3. 默认情况下, cgroup A 和 cgroup B 中的 cpu.shares 中的数值都是 1024
  4. 在 A 和 B 中用 stress 工具使其 CPU占用率达到 100%
  5. top 命令查看 A 和 B 中进程分别占用的 CPU (应该都是 50%)
# 挂载 cgroup 文件系统
mount -t cgroup -o cpu cgroup /mnt/cgroup/
cd /mnt/cgroup
ls -l
total
-r--r--r-- root root Aug : blkio.io_merged
-r--r--r-- root root Aug : blkio.io_queued
-r--r--r-- root root Aug : blkio.io_service_bytes
-r--r--r-- root root Aug : blkio.io_serviced
-r--r--r-- root root Aug : blkio.io_service_time
-r--r--r-- root root Aug : blkio.io_wait_time
--w------- root root Aug : blkio.reset_stats
-r--r--r-- root root Aug : blkio.sectors
-r--r--r-- root root Aug : blkio.time
-rw-r--r-- root root Aug : blkio.weight
-rw-r--r-- root root Aug : blkio.weight_device
-rw-r--r-- root root Aug : cgroup.clone_children
--w--w--w- root root Aug : cgroup.event_control
-rw-r--r-- root root Aug : cgroup.procs
-r--r--r-- root root Aug : cpuacct.stat
-rw-r--r-- root root Aug : cpuacct.usage
-r--r--r-- root root Aug : cpuacct.usage_percpu
-rw-r--r-- root root Aug : cpuset.cpu_exclusive
-rw-r--r-- root root Aug : cpuset.cpus
-rw-r--r-- root root Aug : cpuset.mem_exclusive
-rw-r--r-- root root Aug : cpuset.mem_hardwall
-rw-r--r-- root root Aug : cpuset.memory_migrate
-r--r--r-- root root Aug : cpuset.memory_pressure
-rw-r--r-- root root Aug : cpuset.memory_pressure_enabled
-rw-r--r-- root root Aug : cpuset.memory_spread_page
-rw-r--r-- root root Aug : cpuset.memory_spread_slab
-rw-r--r-- root root Aug : cpuset.mems
-rw-r--r-- root root Aug : cpuset.sched_load_balance
-rw-r--r-- root root Aug : cpuset.sched_relax_domain_level
-rw-r--r-- root root Aug : cpu.shares
--w------- root root Aug : devices.allow
--w------- root root Aug : devices.deny
-r--r--r-- root root Aug : devices.list
-rw-r--r-- root root Aug : net_cls.classid
-rw-r--r-- root root Aug : notify_on_release
-rw-r--r-- root root Aug : release_agent
-rw-r--r-- root root Aug : tasks # 创建 子cgroup A 和 B
mkdir {A,B}
cat A/cpu.shares cat B/cpu.shares # 在 A 和 B 中分别通过 stress 工具使其CPU使用率达到 %
echo $$ > A/tasks # 将当前的 SHELL 加入到 cgroup A中
stress -c # 这里-c 是因为测试机器是双核, 要在2个核上都产生 % 的CPU 占用率
# 另外打开一个 shell 窗口, 并将这个shell 加入到 cgroup B中
echo $$ > B/tasks # 将当前的 SHELL 加入到 cgroup B中
stress -c # 在2个核上都产生 % 的CPU 占用率
# 再打开一个 shell 窗口, 用top命令查看 CPU占用情况
top
top - :: up min, users, load average: 2.31, 1.24, 0.62
Tasks: total, running, sleeping, stopped, 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 st
KiB Mem: total, used, free, buffers
KiB Swap: total, used, free, cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
root R 49.9 0.0 :08.73 stress
root R 49.9 0.0 :08.67 stress
root R 49.9 0.0 :07.35 stress
root R 49.9 0.0 :07.36 stress # 查看这 个stress 进程是否分别属于 A 和 B
cat /mnt/cgroup/A/tasks <-- stress 进程
<-- stress 进程
cat /mnt/cgroup/B/tasks <-- stress 进程
<-- 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
  1. 环境同 实例1, 不再重新挂载 cgroup 文件系统, 也不在重建 A 和 B
  2. A group 的 cpu.shares 文件不变, 值为 1024
  3. B group 的 cpu.shares 文件中的值改为 512, 这样, 相当于B占用CPU总资源的 1/3 (因为 512 / (512+1024) = 1/3)
  4. 同实例1, 通过2个shell窗口, 分别是 A 和 B 的CPU使用率达到 100%, 然后通过 top 查看CPU使用情况
# 在 B 中shell 窗口执行以下命令
cat B/cpu.shares echo > B/cpu.shares
cat B/cpu.shares stress -c # 在 A 中 shell 窗口执行以下命令
stress -c # 在第3个 shell 窗口, 也就是 非A, 非B 的那个 shell 窗口, 用 top 查看cpu使用情况
top
top - :: up min, users, load average: 2.24, 1.92, 1.01
Tasks: total, running, sleeping, stopped, 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 st
KiB Mem: total, used, free, buffers
KiB Swap: total, used, free, cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
root R 66.6 0.0 :06.29 stress
root R 66.6 0.0 :06.30 stress
root R 33.3 0.0 :04.33 stress
root R 33.3 0.0 :04.32 stress # 查看这 个stress 进程是否分别属于 A 和 B
cat /mnt/cgroup/A/tasks <-- stress 进程
<-- stress 进程
cat /mnt/cgroup/B/tasks <-- stress 进程
<-- 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 cpusets
CONFIG_CPUSETS=y

我的测试系统是支持的, 如果你的系统不支持, 就需要重新编译内核了.......

然后, 用下面的例子演示将 A 和 B中的 stress 都指定到1个CPU上后的情况

  1. 卸载当前的 cgroup
  2. 再次挂载 cgroup 文件系统, 并指定 -o cpuset
  3. 指定 A 的物理CPU为 0 (双核CPU的每个核编号分别是 CPU0, CPU1)
  4. 指定 B 的物理CPU也为 0
  5. 重复 实例1 中的步骤, 观察发生的变化
umount /mnt/cgroup
mount -t cgroup -o cpuset cgroup /mnt/cgroup/
cd /mnt/cgroup
ls -l
total
-rw-r--r-- root root Aug : cgroup.clone_children
--w--w--w- root root Aug : cgroup.event_control
-rw-r--r-- root root Aug : cgroup.procs
-rw-r--r-- root root Aug : cpuset.cpu_exclusive
-rw-r--r-- root root Aug : cpuset.cpus <-- 这个就是设置关联物理CPU的文件
-rw-r--r-- root root Aug : cpuset.mem_exclusive
-rw-r--r-- root root Aug : cpuset.mem_hardwall
-rw-r--r-- root root Aug : cpuset.memory_migrate
-r--r--r-- root root Aug : cpuset.memory_pressure
-rw-r--r-- root root Aug : cpuset.memory_pressure_enabled
-rw-r--r-- root root Aug : cpuset.memory_spread_page
-rw-r--r-- root root Aug : cpuset.memory_spread_slab
-rw-r--r-- root root Aug : cpuset.mems
-rw-r--r-- root root Aug : cpuset.sched_load_balance
-rw-r--r-- root root Aug : cpuset.sched_relax_domain_level
-rw-r--r-- root root Aug : notify_on_release
-rw-r--r-- root root Aug : release_agent
-rw-r--r-- root root Aug : tasks # 创建子cgroup A 和 B
mkdir {A,B}
cat A/cpuset.cpus
<-- 默认是空的
echo > A/cpuset.cpus
cat A/cpuset.cpus echo > 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.mems
echo > A/cpuset.cpus
echo > A/cpuset.mems
# B组也同样设置
echo > B/cpuset.cpus
echo > B/cpuset.mems # 将当前 shell 加入到 A组
echo $$ > /mnt/cgroup/A/tasks <-- 设置过 cpuset.mems 后, 就没有出错了
stress -c # 再打开一个Shell窗口, 并加入到 B组
echo $$ > /mnt/cgroup/B/tasks
stress -c # 再打开第3个 shell 窗口, 用top命令查看CPU使用情况
top
top - :: up :, users, load average: 1.01, 0.24, 0.12
Tasks: total, running, sleeping, stopped, 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 st
KiB Mem: total, used, free, buffers
KiB Swap: total, used, free, cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
root R 25.0 0.0 :04.96 stress
root R 25.0 0.0 :04.97 stress
root R 25.0 0.0 :03.56 stress
root R 24.6 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 > /mnt/cgroup/B/cpuset.cpus
cat /mnt/cgroup/B/cpuset.cpus stress -c # 在 A组的 shell 窗口中执行以下命令
stress -c # 在第3个shell窗口中用top命令查看执行结果
top
top - :: up :, users, load average: 0.38, 0.83, 0.56
Tasks: total, running, sleeping, stopped, 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 st
KiB Mem: total, used, free, buffers
KiB Swap: total, used, free, cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
root R 49.9 0.0 :03.76 stress
root R 49.9 0.0 :02.29 stress
root R 49.9 0.0 :02.29 stress
root R 49.6 0.0 :03.76 stress

果然, 和预期一致. A组中的 stress 和 B组中的 stress 在各自的物理CPU上都占用了 100% 左右的CPU使用率.

实例4 - cgroup 对使用的内存的控制

cgroup 对内存的控制也很简单, 只要挂载cgroup时, 指定 -o memory

# 首先之前挂载的 cpuset 子系统
umount /mnt/cgroup # 挂载cgroup 文件系统, 指定 -o memeory
mount -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 enabled
cpuset
cpu
cpuacct
memory <-- 这里的 enabled 是
devices
freezer
net_cls
blkio
perf_event

为了默认启用memory子系统, 可以设置 grub选项

vim /etc/default/grub
# 修改 GRUB_CMDLINE_LINUX="" ==> GRUB_CMDLINE_LINUX="cgroup_enable=memory"
# 保存后, 更新grub.cfg
update-grub
reboot

重启之后, 发现 /proc/cgroups 中的memory已经 enabled, 并且也可以挂载 memcg了

cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset
cpu
cpuacct
memory
devices
freezer
net_cls
blkio
perf_event # 挂载cgroup 的memory子系统
mount -t cgroup -o memory memcg /mnt/cgroup
ls -l /mnt/cgroup/ <-- 可以看到有很多 memory 相关的配置
total
-rw-r--r-- root root Aug : cgroup.clone_children
--w--w--w- root root Aug : cgroup.event_control
-rw-r--r-- root root Aug : cgroup.procs
-rw-r--r-- root root Aug : memory.failcnt
--w------- root root Aug : memory.force_empty
-rw-r--r-- root root Aug : memory.limit_in_bytes <-- 限制内存使用的配置文件
-rw-r--r-- root root Aug : memory.max_usage_in_bytes
-rw-r--r-- root root Aug : memory.move_charge_at_immigrate
-r--r--r-- root root Aug : memory.numa_stat
-rw-r--r-- root root Aug : memory.oom_control
-rw-r--r-- root root Aug : memory.soft_limit_in_bytes
-r--r--r-- root root Aug : memory.stat
-rw-r--r-- root root Aug : memory.swappiness
-r--r--r-- root root Aug : memory.usage_in_bytes
-rw-r--r-- root root Aug : memory.use_hierarchy
-rw-r--r-- root root Aug : notify_on_release
-rw-r--r-- root root Aug : release_agent
-rw-r--r-- root root Aug : tasks

开始实验:

  1. 重启系统 (为了保证内存的干净)
  2. 挂载 memcg
  3. 在挂载的 /mnt/cgroup 中创建 组A
  4. 将当前shell 加入到 组A
  5. 不限制组A的内存, 压缩内核源码包, 并观察压缩前后内存的变化
  6. 重复步骤 1 ~ 4
  7. 限制组A的内存为 10MB, 再次压缩内核源码包, 并观察压缩前后内存的变化
# 重启系统
reboot # 挂载 memcg
mount -t cgroup -o memory memcg /mnt/cgroup # 创建 组A
mkdir /mnt/cgroup/A # 将当前 shell 加入到组A
echo $$ > /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 cached
Mem:
-/+ buffers/cache:
Swap:
total used free shared buffers cached
Mem:
-/+ buffers/cache:
Swap: # 重启系统
reboot # 挂载 memcg
mount -t cgroup -o memory memcg /mnt/cgroup # 创建 组A
mkdir /mnt/cgroup/A # 将当前 shell 加入到组A
echo $$ > /mnt/cgroup/A/tasks # 限制 组A 的内存使用量最大为 10MB
echo 10M > /mnt/cgroup/A/memory.limit_in_bytes # 测试限制内存为 10MB 时, 内存的使用情况.
rm -rf linux-source-3.2.tar.gz
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 cached
Mem:
-/+ buffers/cache:
Swap:
total used free shared buffers cached
Mem:
-/+ buffers/cache:
Swap:

从上面的结果可以看出限制内存是起了作用的.

不限制内存时, tar 压缩前后 buffer + cache 内存从 (9MB + 43MB) ==> (26MB + 1614MB)  增大了 1588MB

限制内存后, tar 压缩前后 buffer + cache 内存从 (10MB + 43MB) ==> (14MB + 48MB)  增大了 9MB

总结

简单的实验就发现 cgroup 如此强大的控制能力(而且配置也很简单), 这也就难怪LXC等容器技术能如此强大, 如此流行.

cgroup 的配置文件很多, 上面的实例中只简单使用了其中的几个配置文件, 如果想深入了解 cgroup, 更好的利用cgroup的话,

还得找个介绍cgroup配置文件的文档来研究一下, 这篇博客提供的内容还远远不够.

Linux资源控制-CPU和内存的更多相关文章

  1. Linux资源控制-CPU和内存【转】

    转自:http://www.cnblogs.com/wang_yb/p/3942208.html 主要介绍Linux下, 如果对进程的CPU和内存资源的使用情况进行控制的方法. CPU资源控制 每个进 ...

  2. linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试  要远程测试其实很简单了,把结果放到一个微服务里直接在web里查看就可以了,或者同步到其他服务器上 一.对CPU进行简单测试: 1.通过bc命令计算特 ...

  3. Linux 查看物理 CPU、内存信息

    可以通过本文如下方法查看云服务器 Linux 系统的 CPU.内存相关信息: 说明: 总核数 = 物理CPU个数 × 每颗物理CPU的核数 总逻辑CPU数 = 物理CPU个数 × 每颗物理CPU的核数 ...

  4. [转帖]linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试 https://www.cnblogs.com/zhuochong/p/10185881.html 一.对CPU进行简单测试: 1.通过bc命令计算特 ...

  5. 利用cgroup控制进程使用的资源(cpu、内存等)

    实验环境:centos 6.10 1.安装libcgroup yum install -y libcgroup 2.进入资源控制器默认挂载目录/cgroup [root@hadoop1 cgroup] ...

  6. Cgroups控制cpu,内存,io示例

    Cgroups是control groups的缩写,最初由Google工程师提出,后来编进linux内核. Cgroups是实现IaaS虚拟化(kvm.lxc等),PaaS容器沙箱(Docker等)的 ...

  7. 写代码如何合理使用和优化我们的机器资源(CPU、内存、网络、磁盘)

    写代码脑子一定要绷紧一根弦,认知到我们所在的机器资源是有限的.机器资源有哪些?CPU.内存.网络.磁盘等,如果不做好保护控制工作,一旦某一资源满负荷,很容易导致出现线上问题. 1 CPU 资源怎么限制 ...

  8. Linux下查看CPU型号,内存大小,硬盘空间,进程等的命令(详解)

    转自:http://www.jb51.net/article/97157.htm 1 查看CPU 1.1 查看CPU个数 # cat /proc/cpuinfo | grep "physic ...

  9. Linux下查看CPU型号,内存大小,硬盘空间的命令

    1 查看CPU 1.1 查看CPU个数 # cat /proc/cpuinfo | grep "physical id" | uniq | wc -l 2 **uniq命令:删除重 ...

随机推荐

  1. ELK+Kafka集群日志分析系统

    ELK+Kafka集群分析系统部署 因为是自己本地写好的word文档复制进来的.格式有些出入还望体谅.如有错误请回复.谢谢! 一. 系统介绍 2 二. 版本说明 3 三. 服务部署 3 1) JDK部 ...

  2. 学习 React(jsx语法) + es2015 + babel + webpack

    视频学习地址: http://www.jtthink.com/course/play/575 官方地址 https://facebook.github.io/react/ 神坑: 1.每次this.s ...

  3. 赵文豪 GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 使用gdb调 ...

  4. USACO翻译:USACO 2012 JAN三题(3)

    USACO 2012JAN(题目三) 一.题目概览 中文题目名称 放牧 登山 奶牛排队 英文题目名称 grazing climb lineup 可执行文件名 grazing climb lineup ...

  5. C# RabbitMq .net 使用

    本文转载来自 [http://www.cnblogs.com/yangecnu/p/Introduce-RabbitMQ.html]写的很详细. 文件安装包官方DEMO下载地址是:http://pan ...

  6. 导向矢量(Steering Vector)

    导向矢量是阵列天线的所有阵元对具有单位能量窄带信源的响应. 由于阵列响应在不同方向上是不同的,导向矢量与信源的方向是相互关联的,这种关联的独特性依赖于阵列的几何结构.对于同一阵元阵列,导向矢量的每一个 ...

  7. 安装jdk

    检查已安装jdk,如果有,先删除 rpm -qa|grep java rpm -e --nodeps filename 从oracle官方网站下载jdk安装包:jdk-8u111-linux-x64. ...

  8. docfx组件介绍--MarkdownLite

    在docfx中,最重要的就是生成文档,把markdown文件(gfm语法)转换成html. 为了这一步,我们找了N个.net开源项目,发现要么是common markdown的,要么不容易扩展,没有一 ...

  9. Code First系列之视图,存储过程和异步API

    返回<8天掌握EF的Code First开发>总目录 本篇目录 视图View 存储过程 使用存储过程CRUD 异步API 本章小结 自我测试 本系列的源码本人已托管于coding上:点击查 ...

  10. ASP.NET MVC 5 Web编程1 -- 入门

    开篇引言 说起ASP.NET MVC,我想作为WebForms开发者第一点要问的是:为什么要使用它?我的理解是:MVC是更细节化的框架,“细节可控”意味着你的系统更精致.具体体现在应用上.MVC的出现 ...