Linux内核分析之内存管理-14

韩乔落

第14章:内存控制组

基于 Linux 6.12.38 源码


14.1 内存控制组概述

14.1.1 什么是 memcg

内存控制组 (Memory cgroup,memcg) 是 Linux 内核提供的资源控制机制,用于限制和统计一组进程的内存使用。

主要功能:

  • 限制内存使用量
  • 统计内存使用
  • OOM 控制
  • 内存 swap 限制

14.1.2 memcg 层次结构

1
2
3
4
5
6
7
8
9
Root cgroup
├── group1 (1GB limit)
│ ├── process1
│ └── process2
├── group2 (2GB limit)
│ ├── process3
│ └── process4
└── group3 (512MB limit)
└── process5

14.2 mem_cgroup 结构

14.2.1 结构定义

位置: include/linux/memcontrol.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct mem_cgroup {
/* cgroup 基础 */
struct cgroup_subsys_state css;

/* 内存限制 */
unsigned long memory; /* 内存限制 */
unsigned long swap; /* swap 限制 */
unsigned long memsw; /* 内存 + swap 限制 */

/* 使用统计 */
unsigned long memory_usage; /* 当前内存使用 */
unsigned long swap_usage; /* 当前 swap 使用 */
unsigned long memsw_usage; /* 当前 memsw 使用 */

/* 事件 */
struct mem_cgroup_events {
unsigned long low; /* 低水位事件 */
unsigned long high; /* 高水位事件 */
unsigned long max; /* 最大使用事件 */
unsigned long oom; /* OOM 事件 */
} events;

/* LRU 链表 */
struct list_head lru; /* LRU 链表 */

/* 更多字段... */
};

14.2.2 创建/删除 memcg

1
2
3
4
5
6
7
/* 创建 memcg */
struct mem_cgroup *mem_cgroup_alloc(void);
void mem_cgroup_free(struct mem_cgroup *memcg);

/* 在线/离线 */
int mem_cgroup_online(struct mem_cgroup *memcg);
void mem_cgroup_offline(struct mem_cgroup *memcg);

14.3 内存分配与 memcg

14.3.1 memcg 分配

位置: mm/memcontrol.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* 分配时检查 memcg 限制 */
bool mem_cgroup_charge(struct page *page, struct mm_struct *mm,
gfp_t gfp_mask)
{
struct mem_cgroup *memcg;
int ret;

/* 获取 memcg */
if (mm) {
memcg = get_mem_cgroup_from_mm(mm);
} else {
memcg = root_mem_cgroup;
}

/* 检查限制 */
ret = try_charge(memcg, gfp_mask, nr_pages);
if (ret)
return false;

/* 收费 */
page->memcg_data = (unsigned long)memcg;

return true;
}

/* 取消收费 */
void mem_cgroup_uncharge(struct page *page)
{
struct mem_cgroup *memcg;

/* 获取 memcg */
memcg = page->memcg_data;

/* 减少使用计数 */
if (mem_cgroup_dec_and_test(memcg, nr_pages)) {
/* 达到限制,触发事件 */
memcg_event(memcg, MEMCG_LOW);
}
}

14.3.2 OOM 处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* OOM 处理 */
void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t gfp_mask)
{
/* 检查是否禁用 OOM killer */
if (memcg->oom_disable)
return;

/* 触发 OOM 事件 */
memcg_event(memcg, MEMCG_OOM);

/* 调用 OOM killer */
mem_cgroup_out_of_memory(memcg, gfp_mask);
}

/* 判断是否超过限制 */
bool mem_cgroup_over_limit(struct mem_cgroup *memcg)
{
/* 检查内存限制 */
if (memcg->memory_usage >= memcg->memory)
return true;

/* 检查 swap 限制 */
if (memcg->swap_usage >= memcg->swap)
return true;

return false;
}

14.4 memcg 统计

14.4.1 统计接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 获取内存使用 */
unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
{
if (swap)
return memcg->swap_usage;
else
return memcg->memory_usage;
}

/* 获取统计信息 */
void mem_cgroup_get_stats(struct mem_cgroup *memcg,
struct mem_cgroup_stats *stats)
{
/* 填充统计信息 */
stats->cache = memcg_page_state(memcg, NR_FILE_PAGES);
stats->rss = memcg_page_state(memcg, NR_ANON_MAPPED);
stats->shmem = memcg_page_state(memcg, NR_SHMEM);
stats->file_mapped = memcg_page_state(memcg, NR_FILE_MAPPED);
}

14.4.2 /proc 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看所有 memcg
ls /sys/fs/cgroup/memory/

# 查看特定 memcg 统计
cat /sys/fs/cgroup/memory/<cgroup>/memory.usage_in_bytes
cat /sys/fs/cgroup/memory/<cgroup>/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/<cgroup>/memory.max_usage_in_bytes

# 查看 OOM 控制
cat /sys/fs/cgroup/memory/<cgroup>/memory.oom_control

# 查看 swap 使用
cat /sys/fs/cgroup/memory/<cgroup>/memory.memsw.usage_in_bytes
cat /sys/fs/cgroup/memory/<cgroup>/memory.memsw.max_usage_in_bytes

14.5 memcg 与 swap

14.5.1 swap 控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* swap 限制 */
bool mem_cgroup_swappiness(struct mem_cgroup *memcg)
{
/* 检查 swap 使用策略 */
return memcg->swappiness;
}

/* 限制 swap 使用 */
int mem_cgroup_charge_swap(struct page *page, int nr_pages)
{
struct mem_cgroup *memcg;

/* 获取 memcg */
memcg = page->memcg_data;

/* 增加 swap 使用 */
if (!mem_cgroup_try_charge_swap(memcg, nr_pages)) {
/* 超过限制 */
return -ENOMEM;
}

return 0;
}

14.5.2 swap 配置

1
2
3
4
5
6
7
8
# 禁用 swap
echo 0 > /sys/fs/cgroup/memory/<cgroup>/memory.swappiness

# 启用 swap
echo 60 > /sys/fs/cgroup/memory/<cgroup>/memory.swappiness

# 设置 swap 限制
echo 1G > /sys/fs/cgroup/memory/<cgroup>/memory.memsw.limit_in_bytes

14.6 memcg 与内核内存

14.6.1 内核内存限制

1
2
3
CONFIG_MEMCG_KMEM            # memcg 内核内存
CONFIG_MEMCG_SWAP # memcg swap
CONFIG_MEMCG_SWAP_ENABLED # 启用 memcg swap

14.6.2 内核内存分配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 内核内存分配 */
void *kmalloc_memcg(size_t size, gfp_t gfp,
struct mem_cgroup *memcg)
{
/* 检查 memcg 限制 */
if (!mem_cgroup_charge(memcg, size, gfp))
return NULL;

/* 分配内存 */
return kmalloc(size, gfp);
}

/* 释放内核内存 */
void kfree_memcg(void *ptr, struct mem_cgroup *memcg)
{
/* 释放内存 */
kfree(ptr);

/* 取消收费 */
mem_cgroup_uncharge(memcg, size);
}

14.7 memcg 事件

14.7.1 事件类型

1
2
3
4
5
6
7
8
9
10
11
/* memcg 事件 */
enum memcg_memory_event {
MEMCG_LOW, /* 低水位 */
MEMCG_HIGH, /* 高水位 */
MEMCG_MAX, /* 最大使用 */
MEMCG_OOM, /* OOM */
MEMCG_OOM_KILL, /* OOM kill */
MEMCG_SWAP_MAX, /* Swap 最大 */
MEMCG_SWAP_FAIL, /* Swap 失败 */
MEMCG_NR_EVENTS,
};

14.7.2 事件通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 触发事件 */
void mem_cgroup_event(struct mem_cgroup *memcg,
enum memcg_memory_event event)
{
/* 更新事件计数 */
atomic64_inc(&memcg->events[event]);

/* 通知用户空间 */
cgroup_file_notify(memcg->css.cgroup, event);
}

/* OOM 控制 */
void mem_cgroup_oom_control(struct mem_cgroup *memcg,
struct mem_cgroup_event *event)
{
if (event->type == MEMCG_OOM) {
/* 处理 OOM */
mem_cgroup_out_of_memory(memcg, event->gfp_mask);
}
}

14.8 本章小结

本章介绍了 Linux 6.12 的内存控制组:

  1. memcg 概述: 限制和统计进程组内存使用
  2. mem_cgroup: 核心数据结构,限制、统计、事件
  3. 内存分配: 分配时检查限制,charge/uncharge
  4. OOM 处理: 超过限制时触发 OOM killer
  5. memcg 统计: 使用统计、/proc 接口
  6. swap 控制: swap 使用限制和策略
  7. 内核内存: memcg 对内核内存的支持
  8. memcg 事件: 低水位、高水位、OOM 等事件

下一章将介绍内存统计与调试。

  • Title: Linux内核分析之内存管理-14
  • Author: 韩乔落
  • Created at : 2026-01-20 21:39:50
  • Updated at : 2026-02-24 14:04:45
  • Link: https://jelasin.github.io/2026/01/20/Linux内核分析之内存管理-14/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments