jason的笔记:cgroup 架构
作者:[db:作者]
时间:2021-09-14 10:25
网上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的时间.cs