网上Cgroup的资料一大堆,我就写一下自己的心得.希望可以抛砖引玉.
每一个cgroup 对应一个cgroup_subsys 类型,这个类型中最重要的是cftype。
我们以cpuacct为例
348 struct cgroup_subsys cpuacct_cgrp_subsys = {
349 .css_alloc = cpuacct_css_alloc,
350 .css_free = cpuacct_css_free,
351 .legacy_cftypes = files,
352 .early_init = true,
353 };
最终要的cftype = files.
278 static struct cftype files[] = {
279 {
280 .name = "usage",
281 .read_u64 = cpuusage_read,
282 .write_u64 = cpuusage_write,
283 },
284 {
285 .name = "usage_user",
286 .read_u64 = cpuusage_user_read,
287 },
288 {
289 .name = "usage_sys",
290 .read_u64 = cpuusage_sys_read,
291 },
292 {
293 .name = "usage_percpu",
294 .seq_show = cpuacct_percpu_seq_show,
295 },
296 {
297 .name = "usage_percpu_user",
298 .seq_show = cpuacct_percpu_user_seq_show,
299 },
300 {
301 .name = "usage_percpu_sys",
302 .seq_show = cpuacct_percpu_sys_seq_show,
303 },
304 {
305 .name = "stat",
306 .seq_show = cpuacct_stats_show,
307 },
308 { } /* terminate */
309 };
从files 可以,可以在cpuacct.usage/cpuacct.usage_percpu_sys等目录。我们以 cat cpuacct.usage 会调用cpuacct_stats_show函数。
static int cpuacct_stats_show(struct seq_file *sf, void *v)
251 {
252 struct cpuacct *ca = css_ca(seq_css(sf));
253 int cpu;
254 s64 val = 0;
255
256 for_each_possible_cpu(cpu) {
257 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
258 val += kcpustat->cpustat[CPUTIME_USER];
259 val += kcpustat->cpustat[CPUTIME_NICE];
260 }
261 val = cputime64_to_clock_t(val);
262 seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val);
263
264 val = 0;
265 for_each_possible_cpu(cpu) {
266 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
267 val += kcpustat->cpustat[CPUTIME_SYSTEM];
268 val += kcpustat->cpustat[CPUTIME_IRQ];
269 val += kcpustat->cpustat[CPUTIME_SOFTIRQ];
270 }
271
272 val = cputime64_to_clock_t(val);
273 seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
274
275 return 0;
276 }
其中最终要的262行的seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val);
和273行的seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
其中
245 static const char * const cpuacct_stat_desc[] = {
246 [CPUACCT_STAT_USER] = "user",
247 [CPUACCT_STAT_SYSTEM] = "system",
248 };
可以先显示进程在user 和system的时间.
每一个cgroup 对应一个cgroup_subsys 类型,这个类型中最重要的是cftype。
我们以cpuacct为例
348 struct cgroup_subsys cpuacct_cgrp_subsys = {
349 .css_alloc = cpuacct_css_alloc,
350 .css_free = cpuacct_css_free,
351 .legacy_cftypes = files,
352 .early_init = true,
353 };
最终要的cftype = files.
278 static struct cftype files[] = {
279 {
280 .name = "usage",
281 .read_u64 = cpuusage_read,
282 .write_u64 = cpuusage_write,
283 },
284 {
285 .name = "usage_user",
286 .read_u64 = cpuusage_user_read,
287 },
288 {
289 .name = "usage_sys",
290 .read_u64 = cpuusage_sys_read,
291 },
292 {
293 .name = "usage_percpu",
294 .seq_show = cpuacct_percpu_seq_show,
295 },
296 {
297 .name = "usage_percpu_user",
298 .seq_show = cpuacct_percpu_user_seq_show,
299 },
300 {
301 .name = "usage_percpu_sys",
302 .seq_show = cpuacct_percpu_sys_seq_show,
303 },
304 {
305 .name = "stat",
306 .seq_show = cpuacct_stats_show,
307 },
308 { } /* terminate */
309 };
从files 可以,可以在cpuacct.usage/cpuacct.usage_percpu_sys等目录。我们以 cat cpuacct.usage 会调用cpuacct_stats_show函数。
static int cpuacct_stats_show(struct seq_file *sf, void *v)
251 {
252 struct cpuacct *ca = css_ca(seq_css(sf));
253 int cpu;
254 s64 val = 0;
255
256 for_each_possible_cpu(cpu) {
257 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
258 val += kcpustat->cpustat[CPUTIME_USER];
259 val += kcpustat->cpustat[CPUTIME_NICE];
260 }
261 val = cputime64_to_clock_t(val);
262 seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val);
263
264 val = 0;
265 for_each_possible_cpu(cpu) {
266 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
267 val += kcpustat->cpustat[CPUTIME_SYSTEM];
268 val += kcpustat->cpustat[CPUTIME_IRQ];
269 val += kcpustat->cpustat[CPUTIME_SOFTIRQ];
270 }
271
272 val = cputime64_to_clock_t(val);
273 seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
274
275 return 0;
276 }
其中最终要的262行的seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val);
和273行的seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
其中
245 static const char * const cpuacct_stat_desc[] = {
246 [CPUACCT_STAT_USER] = "user",
247 [CPUACCT_STAT_SYSTEM] = "system",
248 };
可以先显示进程在user 和system的时间.