Red Hat Training

A Red Hat training course is available for Red Hat Linux

附录 A. 子系统和可调参数

“子系统” 是识别 cgroup 的 kernel 模块。通常,它们被看做资源管控器,为不同 cgroup 分配不同级别的系统资源。但是当不同的进程组需要被区别对待时,可以改写子系统与 kernel 间的互动。用于开发新子系统的 “应用程序编程界面”(API)记载于 kernel 文档的 cgroups.txt 中,该文件安装在您系统的 /usr/share/doc/kernel-doc-kernel-version/Documentation/cgroups/ 中(由 kernel-doc 软件包提供)。cgroup 文档的最新版本可在 http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt 中找到。请注意:最新文档所述功能可能不与您系统中已安装的 kernel 功能匹配。
包含 cgroup 子系统参数的“状态对象”在 cgroup 的虚拟文件系统中,被描述为 “伪文件”。这些伪文件可由 shell 命令或者与其对等的系统呼叫来操作。例如:cpuset.cpus 是一份指定 cgroup可以存取哪个 CPU 的伪文件。如果 /cgroup/cpuset/webserver 是系统中运行的网页服务器的 cgroup,那么以下命令会被执行:
~]# echo 0,2 > /cgroup/cpuset/webserver/cpuset.cpus
因为 cpuset.cpus 伪文件中写入了 0,2 值,所以任何任务的 PID 一旦被列入 /cgroup/cpuset/webserver/tasks/,那么此任务将仅能在系统中使用 CPU 0 和 CPU 2。

A.1. blkio

块 I/O(blkio)子系统可以控制并监控 cgroup 中的任务对块设备 I/O 的存取。对一些伪文件写入值可以限制存取次数或带宽,从伪文件中读取值可以获得关于 I/O 操作的信息。
blkio 子系统给出两种方式来控制对 I/O 的存取:
  • “权重分配” — 用于完全公平列队 I/O 调度程序 (Completely Fair Queuing I/O scheduler),用此方法,让您可以给指定的 cgroup 设定权重。这意味着每个 cgroup 都有一个预留的 I/O 操作设定比例(根据 cgroup 的权重)。详情请参阅〈第 A.1.1 节 “权重分配的可调参数”〉。
  • “I/O 节流(上限)” — 当一个指定设备执行 I/O 操作时,此方法可为其操作次数设定上限。这意味着一个设备的 “读” 或者 “写” 的操作次数是可以限定的。详情请参阅第 A.1.2 节 “I/O 节流可调参数”

重要

目前,block I/O 子系统不支持已缓冲的 “写” 操作。虽然可以支持已缓冲的 “读” 操作,但它主要针对直接 I/O。

A.1.1. 权重分配的可调参数

blkio.weight
此参数用于指定一个 cgroup 在默认情况下可存取块 I/O 的相对比例(加权),范围是 1001000。该值可被指定设备的 blkio.weight_device 参数覆盖。例如:如要将 cgroup 存取块设备的默认权重设定为 500,请运行:
echo 500 > blkio.weight
blkio.weight_device
此参数用于设定 cgroup 中指定设备 I/O 存取的相对比例(加权),范围是 1001000。对于指定的设备,此参数值可覆盖 blkio.weight 参数值。值的格式为 major:minor weight。其中 majorminor 是〈Linux 分配的设备〉所指定的设备类型和节点数,我们也称之为〈Linux 设备列表〉,可从 http://www.kernel.org/doc/Documentation/devices.txt 中找到。例如:如果设定 cgroup 访问 /dev/sda 的权重为 500,请运行:
echo 8:0 500 > blkio.weight_device
在〈Linux 分配的设备〉标记法中,8:0 代表 /dev/sda

A.1.2. I/O 节流可调参数

blkio.throttle.read_bps_device
此参数用于设定设备执行“读”操作字节的上限。“读”的操作率以每秒的字节数来限定。条目有三种字段:majorminorbytes_per_secondmajorminor 是〈Linux 分配的设备〉所指定的设备类型和节点数。bytes_per_second“读”操作可被执行的上限率。例如,让 /dev/sda 设备运行“读”操作的最大速率是 10 MBps,请运行:
~]# echo "8:0 10485760" > /cgroup/blkio/test/blkio.throttle.read_bps_device
blkio.throttle.read_iops_device
此参数用于设定设备执行“读”操作次数的上限。“读”的操作率以每秒的操作次数来表示。条目有三个字段:majorminoroperations_per_secondmajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数。operations_per_second“读”可被执行的上限率。例如:如要设定 /dev/sda 设备执行“读”的最大比率为 10 次/秒,请运行:
~]# echo "8:0 10" > /cgroup/blkio/test/blkio.throttle.read_iops_device
blkio.throttle.write_bps_device
此参数用于设定设备执行“写”操作次数的上限。“写”的操作率用“字节/秒”来表示。条目有三个字段:majorminorbytes_per_secondmajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数。bytes_per_second“写”操作可被执行的上限率。例如,让 /dev/sda 设备执行“写”操作的最大比率为 10 MBps,请运行:
~]# echo "8:0 10485760" > /cgroup/blkio/test/blkio.throttle.write_bps_device
blkio.throttle.write_iops_device
此参数用于设定设备执行 “写” 操作次数的上限。“写”的操作率以每秒的操作次数来表示。条目有三个字段:majorminoroperations_per_secondmajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数。operations_per_second“写” 操作可被执行的上限率。例如:如要让 /dev/sda 设备执行“写”操作的最大比率为 10 次/秒,请运行:
~]# echo "8:0 10" > /cgroup/blkio/test/blkio.throttle.write_iops_device
blkio.throttle.io_serviced
此参数用于报告 cgroup 根据节流方式在具体设备中执行的 I/O 操作数。条目有四个字段:majorminoroperationnumbermajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,operation 代表操作类型(readwritesync 或者 async),number 代表操作数。
blkio.throttle.io_service_bytes
此参数用于报告 cgroup 传送到具体设备或者由具体设备中传送出的字节数。blkio.io_service_bytesblkio.throttle.io_service_bytes 之间的唯一区别是:CFQ 调度程序在请求队列中操作时,前者不会被更新。条目有四个字段:majorminoroperationbytesmajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数。operation 代表操作类型(readwritesync 或者 async)。bytes 是被传送的字节数。

A.1.3. blkio 的通用可调参数

以下参数可用于〈第 A.1 节 “blkio”〉所列方法的任意一个。
blkio.reset_stats
此参数用于重设其它伪文件记录的统计数据。请在此文件中写入整数来为 cgroup 重设统计数据。
blkio.time
此参数用于报告 cgroup 对具体设备的 I/O 访问时间。条目有三个字段:majorminortimemajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,time 表示时间长度,单位为毫秒(ms)。
blkio.sectors
此参数用于报告 cgroup 转换到具体设备或者由具体设备转换出的扇区数。条目有三个字段:majorminorsectorsmajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,sectors 是磁盘扇区数。
blkio.avg_queue_size
此参数用于报告:群组存在的整个过程中,cgroup I/O 操作的平均队列大小。每当此 cgroup 队列获得一个 timeslice 时,该队列大小都将被采样。请注意,只有系统设定了 CONFIG_DEBUG_BLK_CGROUP=y 后,此报告才可用。
blkio.group_wait_time
此参数用于报告 cgroup 中每一个队列等待 timeslice 的总时间(单位为纳秒:ns)。每当 cgroup 队列获得一个 timeslice 时,此报告就会被更新,因此如果您在 cgroup 等待 timeslice 时读取伪文件,该报告将不会包含当前队列等待操作的时间。请注意,只有系统设定了 CONFIG_DEBUG_BLK_CGROUP=y 后,此报告才可用。
blkio.empty_time
此参数用于报告:没有任何等待处理的请求时,cgroup 花费的总时间(单位为纳秒:ns)。每当 cgroup 的列队有等待处理的请求时,报告都会被更新,因此如果您在 cgroup 没有任何等待处理的请求时读取此伪文件,该报告将不会包含消耗在当前空状态中的时间。请注意,只有系统设定了 CONFIG_DEBUG_BLK_CGROUP=y 后,此报告才可用。
blkio.idle_time
此参数用于报告:当一个请求比其它队列或者其它群组的请求更好时,调度程序让 cgroup 闲置所消耗的总时间(单位为纳秒:ns)。每当该群组不处于闲置状态时,该报告就会被更新。因此如果您在 cgroup 闲置时读取该伪文件,该报告将不会包含消耗在当前闲置状态的时间。请注意,只有系统设定了 CONFIG_DEBUG_BLK_CGROUP=y 后,此报告才可用。
blkio.dequeue
此参数用于报告 cgroup 的 I/O 操作请求被具体设备从队列中移除的次数。条目有三个字段:majorminornumbermajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,number 是该群组的请求被移除的次数。请注意,只有系统设定了 CONFIG_DEBUG_BLK_CGROUP=y 后,此报告才可用。
blkio.io_serviced
此参数用于报告 cgroup 根据 CFQ 调度程序在具体设备中执行的 I/O 操作数。条目有四个字段:majorminoroperationnumbermajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,operation 代表操作类型(readwritesync 或者 async),number 代表操作次数。
blkio.io_service_bytes
此参数用于报告 cgroup 根据 CFQ 调度程序转换到具体设备或者由具体设备中转出的字节数。条目有四个字段:majorminoroperationbytesmajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,operation 代表操作类型(readwritesync 或者 async),bytes 表示转换的字节数。
blkio.io_service_time
此参数用于报告 cgroup 根据 CFQ 调度程序在具体设备中执行 I/O 操作时,发送请求到完成请求的时间。条目有四个字段:majorminoroperationtimemajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数。operation 表示操作类型(readwritesync 或者 async),time 表示时间长度,单位为纳秒(ns)。此处使用纳秒而不是较大的单位,是为了对固态设备报告也有意义。
blkio.io_wait_time
此参数用于报告 cgroup 在指定设备中执行 I/O 操作时,在调度程序队列中等待服务的总时间。当您解读该报告时,请注意:
  • 报告的时间可能比消耗的时间长,因为报告的时间是该 cgroup 所有 I/O 操作的总和,而不是该 cgroup 本身等待 I/O 操作的时间。要查找该群组作为整体的等待时间,请使用 blkio.group_wait_time 参数。
  • 如果设备包含 queue_depth > 1,则报告只包括向该设备发送请求之前的时间,而不包括该设备将请求重新排序时等待服务的时间。
条目有四个字段:majorminoroperationtimemajorminor 是〈Linux 分配的设备〉指定的设备类型和节点数,operation 表示操作类型(readwritesync 或者 async),time 表示时间长度,单位为纳秒(ns)。此处使用纳秒而不是较大的单位,是为了对固态设备报告也有意义。
blkio.io_merged
此参数用于报告 cgroup 将 BIOS 请求合并到 I/O 操作请求的次数。条目有两个字段:numberoperationnumber 是请求次数,operation 表示操作类型(readwritesync 或者 async)。
blkio.io_queued
此参数用于报告 cgroup 排队请求 I/O 操作的次数。条目有两个字段:numberoperationnumber 是请求次数,operation 表示操作类型(readwritesync 或者 async)。

A.1.4. 示例应用

如想简单测试在两个不同 cgroup 中,使用不同 blkio.weight 值运行两个 dd 线程,请参阅例 A.1 “blkio 权重分配”

例 A.1. blkio 权重分配

  1. 挂载 blkio 子系统:
    ~]# mount -t cgroup -o blkio blkio /cgroup/blkio/
  2. blkio 子系统创建两个 cgroup:
    ~]# mkdir /cgroup/blkio/test1/
    ~]# mkdir /cgroup/blkio/test2/
  3. 在之前创建的 cgroup 设定不同 blkio 权重:
    ~]# echo 1000 > /cgroup/blkio/test1/blkio.weight
    ~]# echo 500 > /cgroup/blkio/test2/blkio.weight
  4. 创建两个大文件:
    ~]# dd if=/dev/zero of=file_1 bs=1M count=4000
    ~]# dd if=/dev/zero of=file_2 bs=1M count=4000
    以上指令所建的文件大小是 4 GB(file_1file_2)。
  5. 对每个测试 cgroup ,在一个大文件中执行 dd 指令(该指令可以读取文件内容,并将其输出到空设备):
    ~]# cgexec -g blkio:test1 time dd if=file_1 of=/dev/null
    ~]# cgexec -g blkio:test2 time dd if=file_2 of=/dev/null
    两个指令在结束后都会输出完成时间。
  6. 您可以使用 iotop 实用工具实时监控两个同时运行的 dd 线程。要安装 iotop 实用工具,请以 root 身份执行 yum install iotop 指令。运行之前启动的 dd 线程时,您可以在 iotop 实用工具中看到以下结果示例:
    Total DISK READ: 83.16 M/s | Total DISK WRITE: 0.00 B/s
        TIME  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
    15:18:04 15071 be/4 root       27.64 M/s    0.00 B/s  0.00 % 92.30 % dd if=file_2 of=/dev/null
    15:18:04 15069 be/4 root       55.52 M/s    0.00 B/s  0.00 % 88.48 % dd if=file_1 of=/dev/null
    
为获得例 A.1 “blkio 权重分配”最准确的结果,请优先执行 dd 指令、清除所有文件系统缓存并使用下列指令释放缓存页、目录项和索引节点:
~]# sync
~]# echo 3 > /proc/sys/vm/drop_caches
您可以启用“群组隔离”,它能使用吞吐量来提供更稳定的群组隔离。当群组隔离被禁用,只有工作量是顺序时,公平才能实现。默认情况下,群组隔离是启用状态,这样即便 I/O 工作量随机也可以保证公平。如要启用群组隔离,请执行下列指令:
~]# echo 1 > /sys/block/<disk_device>/queue/iosched/group_isolation
其中,<disk_device> 代表所需设备名称,例如:sda