> For the complete documentation index, see [llms.txt](https://richardweiyang-2.gitbook.io/kernel-exploring/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://richardweiyang-2.gitbook.io/kernel-exploring/nei-cun-guan-li/00-index-2/03-charge_memcg.md).

# 对memcg记账

既然是要限制内存使用，自然需要一个办法来对内存使用记账。也就是将内存的消耗对应到memcg，这样才有可能知道内存是否超过限制并采取行动。

## 两个入口

经过调研，当前内核5.17一共有两个对外的入口做memcg记账

* mem\_cgroup\_charge
* mem\_cgroup\_swapin\_charge\_page

前者是在做page fault时，而后者是在swapin时。别看就这两个入口，但在内核里要找全安插这两个入口的点可真是不容易。没有对内核全面的了解，真是做不到。所以在现在内核的框架下，能统一这个入口是不是也是一个改进方向呢？

## 核心函数 charge\_memcg

不论是从哪个入口对memcg做记账，都会调用到函数charge\_memcg()。

```
  charge_memcg(folio, memcg, gfp)
      try_charge(memcg, gfp, nr_pages)
          page_counter_try_charge(&memcg->memsw, batch, &counter)
          page_counter_try_charge(&memcg->memory, batch, &counter)
          mem_over_limit = mem_cgroup_from_counter(counter, memory);
          memcg_memory_event(mem_over_limit, MEMCG_MAX)
          try_to_free_mem_cgroup_pages(mem_over_limit, )
          mem_cgroup_oom(mem_over_limit, gfp)
      css_get(memcg->css)
      commit_charge(folio, memcg)
          folio->memcg_data = memcg
      mem_cgroup_charge_statistics(memcg, nr_pages)
      memcg_check_events(memcg, folio_nid(folio))
```

简单来说就是尝试用page\_counter\_try\_charge()做记账，如果没成功就用try\_to\_free\_mem\_cgroup\_pages()或者mem\_cgroup\_oom()回收一些资源然后再尝试。
