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            # set/show limit of "hugepagesize" hugetlb reservations
hugetlb.<hugepagesize>.rsvd.max_usage_in_bytes        # show max "hugepagesize" hugetlb reservations and no-reserve faults
hugetlb.<hugepagesize>.rsvd.usage_in_bytes            # show current reservations and no-reserve faults for "hugepagesize" hugetlb
hugetlb.<hugepagesize>.rsvd.failcnt                   # show the number of allocation failure due to HugeTLB reservation limit
hugetlb.<hugepagesize>.limit_in_bytes                 # set/show limit of "hugepagesize" hugetlb faults
hugetlb.<hugepagesize>.max_usage_in_bytes             # show max "hugepagesize" hugetlb  usage recorded
hugetlb.<hugepagesize>.usage_in_bytes                 # show current usage for "hugepagesize" hugetlb
hugetlb.<hugepagesize>.failcnt                        # show the number of allocation failure due to HugeTLB usage limit
hugetlb.<hugepagesize>.numa_stat                      # show the numa information of the hugetlb memory charged to this cgroup

对于支持三种巨页大小(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
  1. 页面错误记账

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。

  1. 预留记账

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。

  1. 共享内存的注意事项

对于共享的 HugeTLB 内存,HugeTLB 预留和页面错误都由导致内存被预留或错误的第一个任务承担,并且此后对预留或错误内存的所有后续使用都不收费。

仅当取消预留或取消分配时,共享的 HugeTLB 内存才会不收费。这通常在删除 HugeTLB 文件时发生,而不是在导致预留或错误的任务退出时发生。

  1. HugeTLB cgroup 脱机的注意事项。

当 HugeTLB cgroup 脱机并且仍有一些预留或错误费用时,行为如下

  • 错误费用计入父 HugeTLB cgroup(重新父化),

  • 预留费用保留在脱机的 HugeTLB cgroup 上。

这意味着如果 HugeTLB cgroup 在仍有 HugeTLB 预留费用时脱机,则该 cgroup 将一直作为僵尸存在,直到所有 HugeTLB 预留费用都被取消。HugeTLB 预留以这种方式运行以匹配内存控制器,其 cgroup 也作为僵尸存在,直到所有已计费的内存都被取消计费。此外,与跟踪 HugeTLB 错误相比,跟踪 HugeTLB 预留稍微复杂一些,因此在脱机时重新父化预留要困难得多。