HugeTLB 控制器
HugeTLB 控制器可以通过首先挂载 cgroup 文件系统来创建。
# mount -t cgroup -o hugetlb none /sys/fs/cgroup
通过上述步骤,初始或父 HugeTLB 组将在 /sys/fs/cgroup 中可见。在启动时,此组包括系统中的所有任务。/sys/fs/cgroup/tasks 列出了此 cgroup 中的任务。
可以在父组 /sys/fs/cgroup 下创建新组:
# cd /sys/fs/cgroup # mkdir g1 # echo $$ > g1/tasks
上述步骤创建了一个新组 g1,并将当前 shell 进程(bash)移入其中。
控制文件的简要摘要:
- hugetlb.<hugepagesize>.rsvd.limit_in_bytes # 设置/显示“hugepagesize”巨大页保留的限制 - hugetlb.<hugepagesize>.rsvd.max_usage_in_bytes # 显示“hugepagesize”巨大页保留和无保留故障的最大使用量 - hugetlb.<hugepagesize>.rsvd.usage_in_bytes # 显示“hugepagesize”巨大页的当前保留和无保留故障 - hugetlb.<hugepagesize>.rsvd.failcnt # 显示由于 HugeTLB 保留限制而导致的分配失败次数 - hugetlb.<hugepagesize>.limit_in_bytes # 设置/显示“hugepagesize”巨大页故障的限制 - hugetlb.<hugepagesize>.max_usage_in_bytes # 显示记录的“hugepagesize”巨大页的最大使用量 - hugetlb.<hugepagesize>.usage_in_bytes # 显示“hugepagesize”巨大页的当前使用量 - hugetlb.<hugepagesize>.failcnt # 显示由于 HugeTLB 使用限制而导致的分配失败次数 - hugetlb.<hugepagesize>.numa_stat # 显示分配给此 cgroup 的巨大页内存的 numa 信息
对于支持三种巨大页大小(64k、32M 和 1G)的系统,控制文件包括:
- hugetlb.1GB.limit_in_bytes
- hugetlb.1GB.max_usage_in_bytes
- hugetlb.1GB.numa_stat
- hugetlb.1GB.usage_in_bytes
- hugetlb.1GB.failcnt
- hugetlb.1GB.rsvd.limit_in_bytes
- hugetlb.1GB.rsvd.max_usage_in_bytes
- hugetlb.1GB.rsvd.usage_in_bytes
- hugetlb.1GB.rsvd.failcnt
- hugetlb.64KB.limit_in_bytes
- hugetlb.64KB.max_usage_in_bytes
- hugetlb.64KB.numa_stat
- hugetlb.64KB.usage_in_bytes
- hugetlb.64KB.failcnt
- hugetlb.64KB.rsvd.limit_in_bytes
- hugetlb.64KB.rsvd.max_usage_in_bytes
- hugetlb.64KB.rsvd.usage_in_bytes
- hugetlb.64KB.rsvd.failcnt
- hugetlb.32MB.limit_in_bytes
- hugetlb.32MB.max_usage_in_bytes
- hugetlb.32MB.numa_stat
- hugetlb.32MB.usage_in_bytes
- hugetlb.32MB.failcnt
- hugetlb.32MB.rsvd.limit_in_bytes
- hugetlb.32MB.rsvd.max_usage_in_bytes
- hugetlb.32MB.rsvd.usage_in_bytes
- hugetlb.32MB.rsvd.failcnt
- 页面故障记账
hugetlb.<hugepagesize>.limit_in_bytes hugetlb.<hugepagesize>.max_usage_in_bytes hugetlb.<hugepagesize>.usage_in_bytes hugetlb.<hugepagesize>.failcnt
HugeTLB 控制器允许用户限制每个控制组的 HugeTLB 使用(页面故障),并在页面故障期间强制执行限制。由于 HugeTLB 不支持页面回收,在页面故障时强制执行限制意味着,如果应用程序尝试超出其限制故障 HugeTLB 页面,应用程序将收到 SIGBUS 信号。因此,应用程序需要事先准确知道自己使用了多少 HugeTLB 页面,并且系统管理员需要确保机器上有足够的可用页面以满足所有用户的请求,以避免进程收到 SIGBUS。
- 保留记账
hugetlb.<hugepagesize>.rsvd.limit_in_bytes hugetlb.<hugepagesize>.rsvd.max_usage_in_bytes hugetlb.<hugepagesize>.rsvd.usage_in_bytes hugetlb.<hugepagesize>.rsvd.failcnt
HugeTLB 控制器允许限制每个控制组的 HugeTLB 保留,并在保留时和对没有保留的 HugeTLB 内存的故障时强制执行控制器限制。由于保留限制是在保留时(在 mmap 或 shget 上)强制执行的,如果内存在事先保留,保留限制永远不会导致应用程序收到 SIGBUS 信号。对于 MAP_NORESERVE 分配,保留限制的行为与故障限制相同,强制在故障时使用内存,并导致应用程序在超出其限制时收到 SIGBUS。
保留限制优于上述页面故障限制,因为保留限制是在保留时(在 mmap 或 shget 上)强制执行的,并且如果内存在事先保留,永远不会导致应用程序收到 SIGBUS 信号。这允许更容易地回退到其他选择,例如非 HugeTLB 内存。在页面故障记账的情况下,要避免进程收到 SIGBUS 是非常困难的,因为系统管理员需要准确知道系统中所有任务的 HugeTLB 使用量,并确保有足够的页面来满足所有请求。在过度分配的系统上避免任务收到 SIGBUS 几乎是不可能的。
- 共享内存的注意事项
对于共享的 HugeTLB 内存,首次导致内存被保留或故障的任务将对其进行记账,而随后对此保留或故障内存的所有使用将不再进行记账。
只有在取消保留或释放 HugeTLB 文件时,共享的 HugeTLB 内存才会取消记账。通常情况下,这是在导致保留或故障的任务退出时而不是在其退出时。
- HugeTLB cgroup 下线的注意事项
当 HugeTLB cgroup 下线时,仍然对其进行保留或故障记账时的行为如下:
- 故障记账会记入父 HugeTLB cgroup(重新分配),
- 保留记账仍留在下线的 HugeTLB cgroup 上。
这意味着,如果一个 HugeTLB cgroup 在仍然有 HugeTLB 保留记账的情况下下线,该 cgroup 将持续存在为僵尸,直到所有 HugeTLB 保留取消记账。HugeTLB 保留的行为方式与内存控制器相匹配,其 cgroup 也会持续存在为僵尸,直到所有记账内存取消记账。此外,与 HugeTLB 故障的跟踪相比,HugeTLB 保留的跟踪更加复杂,因此在下线时重新分配保留是相当困难的。