cgroup之 memory cgroup(一)

如前文所述,memcg的整體框架如下:

對於memcg,作爲一個cgroup的subsystem,它遵循hierarchy的所有規則,另外,對於hierarchy中cgroup的層級對memcg管理規則的影響,主要分兩方面:

1、 如果不啓用hierarchy,即mem_cgroup->use_hierarchy =false,則所有的memcg之間都是互相獨立,互不影響的,即使是父子cgroup之間,也跟兩個單獨創建的cgroup一樣。

2、 如果啓用hierarchy,即mem_cgroup->use_hierarchy =true,則memcg的統計需要考慮hierarchy中的層級關係,其影響因素主要有:

a.     Charge/uncharge如果子cgroup中charge/uncharge了一個page,則其父cgroup和所有祖先cgroup都要charge/uncharge該page。

b.    Reclaim因爲父cgroup的統計中包含了所有子cgroup中charge的page,所以在回收父cgroup中使用的內存時,也可以回收子cgroup中進程使用的內存。

c.     Oom因爲父cgroup的統計中包含了所有子cgroup中charge的page,所以如果父cgroup需要出發oom,則oom可以考慮殺死子cgroup中的進程,達到釋放內存的效果。

前面已經講過初始化cgroup的基本流程,下面將初始化過程中文件目錄以及節點的創建:

在系統初始化過程中會mount一個路徑/dev/memcg/,同時創建兩個路徑/dev/memcg/apps/和/dev/memcg/system/:

# root memory control cgroup, used by lmkd
mkdir /dev/memcg 0700 root system                                                                                                                    
mount cgroup none /dev/memcg nodev noexec nosuid memory
# app mem cgroups, used by activity manager, lmkd and zygote
mkdir /dev/memcg/apps/ 0755 system system
# cgroup for system_server and surfaceflinger
mkdir /dev/memcg/system 0550 system system

其中/dev/memcg爲root目錄。

mount的主要流程如下:

sys_mount(fs/namespace.c)

  -->do_mount(kernel_dev, dir_name, kernel_type, flags, (void *)data_pate)

    -->do_new_mount (&path, type_page, flags, mnt_flags,dev_name, data_page)

      --> vfs_kern_mount(type, flags, name, data)

        --> mount_fs(type, flags, name, data)

          --> type->mount(type, flags, name, data)

            --> cgroup_mount(fs_type, flags, unused_dev_name, data)
mkdir的流程如下:

sys_mkdir(fs/namei.c)

 -->sys_mkdirat(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)

  -->vfs_mkdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode)

   -->dir->i_op->mkdir(dir, dentry, mode)

    -->cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, umode_t mode)

     -->kernfs_create_dir(parent->kn, name, mode, cgrp)

cgroup在創建目錄的同時,會在該目錄下創建相關的文件節點:

cgroup.clone_children              
cgroup.event_control               
cgroup.procs                       
cgroup.sane_behavior

注:相關節點的創建與否,創建在哪個目錄下,根目錄能否創建,與節點描述結構體struct cftype的flags有關。

memory cgroup以 cgroup爲單位,每個cgroup下面會有很多的文件節點和目錄:

 目錄的創建流程前面已經說明,大部分的節點的創建流程如下:

cgroup_init()①-->cgroup_add_cftypes()-->cgroup_apply_cftypes()-->cgroup_addrm_files()-->cgroup_add_file()

                    ②-->cgroup_add_dfl_cftypes()-->cgroup_add_cftypes()-->cgroup_apply_cftypes()-->cgroup_addrm_files()

                    -->cgroup_add_file()

                    ③-->cgroup_add_legacy_cftypes()-->cgroup_add_cftypes()-->cgroup_apply_cftypes()-->cgroup_addrm_files()

                    -->cgroup_add_file()

cgroup節點分爲默認節點和從父目錄繼承,如果這兩者不相同,則走第一條線,否則分別走第二和第三條線,memory cgroup不一致,故走第二和第三條:

tatic struct cftype memory_files[] = {
	{
		.name = "current",
		.flags = CFTYPE_NOT_ON_ROOT,
		.read_u64 = memory_current_read,
	},
	{
		.name = "low",
		.flags = CFTYPE_NOT_ON_ROOT,
		.seq_show = memory_low_show,
		.write = memory_low_write,
	},
	{
		.name = "high",
		.flags = CFTYPE_NOT_ON_ROOT,
		.seq_show = memory_high_show,
		.write = memory_high_write,
	},
……………………………………
}
static struct cftype mem_cgroup_legacy_files[] = {
	{
		.name = "usage_in_bytes",
		.private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
		.read_u64 = mem_cgroup_read_u64,
	},
	{
		.name = "max_usage_in_bytes",
		.private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE),
		.write = mem_cgroup_reset,
		.read_u64 = mem_cgroup_read_u64,
	},
……………………
}
struct cgroup_subsys memory_cgrp_subsys = {
……………………
	.dfl_cftypes = memory_files,
	.legacy_cftypes = mem_cgroup_legacy_files,
	.early_init = 0,
};

還有一部分cgroup共有的一些節點的創建流程如下:

cgroup_mkdir()-->css_populate_dir()-->cgroup_addrm_files()-->cgroup_add_file()

共有節點特指如下節點:

cgroup.clone_children              
cgroup.event_control               
cgroup.procs                       
cgroup.sane_behavior

以上是目錄和節點的創建全過程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章