本文共 2600 字,大约阅读时间需要 8 分钟。
readprofile 是一个跟踪内核性能的工具,其主要分析schedule/sleep/kvm 这三方面的性能。要使能这个性能需要通过kernel command line传递__setup("profile=", profile_setup);int profile_setup(char *str){ static const char schedstr[] = "schedule"; static const char sleepstr[] = "sleep"; static const char kvmstr[] = "kvm"; int par; #检查用于是要跟踪哪一个性能,目前只支持三个且同时只能支持一个 if (!strncmp(str, sleepstr, strlen(sleepstr))) {#ifdef CONFIG_SCHEDSTATS force_schedstat_enabled(); prof_on = SLEEP_PROFILING; if (str[strlen(sleepstr)] == ',') str += strlen(sleepstr) + 1; if (get_option(&str, &par)) prof_shift = par; pr_info("kernel sleep profiling enabled (shift: %ld)\n", prof_shift);#else pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n");#endif /* CONFIG_SCHEDSTATS */ } else if (!strncmp(str, schedstr, strlen(schedstr))) { prof_on = SCHED_PROFILING; if (str[strlen(schedstr)] == ',') str += strlen(schedstr) + 1; if (get_option(&str, &par)) prof_shift = par; pr_info("kernel schedule profiling enabled (shift: %ld)\n", prof_shift); } else if (!strncmp(str, kvmstr, strlen(kvmstr))) { prof_on = KVM_PROFILING; if (str[strlen(kvmstr)] == ',') str += strlen(kvmstr) + 1; if (get_option(&str, &par)) prof_shift = par; pr_info("kernel KVM profiling enabled (shift: %ld)\n", prof_shift); } else if (get_option(&str, &par)) { prof_shift = par; prof_on = CPU_PROFILING; pr_info("kernel profiling enabled (shift: %ld)\n", prof_shift); } return 1;}这个函数是profile的初始化的入口函数,可见收集到的数据都是保存在proc/profile 这个目录下int __ref create_proc_profile(void){ entry = proc_create("profile", S_IWUSR | S_IRUGO, NULL, &proc_profile_operations); if (!entry) goto err_state_onl; proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t)); return err;}static const struct file_operations proc_profile_operations = { .read = read_profile, .write = write_profile, .llseek = default_llseek,};static ssize_tread_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos){ unsigned long p = *ppos; ssize_t read; char *pnt; unsigned int sample_step = 1 << prof_shift; profile_flip_buffers(); if (p >= (prof_len+1)*sizeof(unsigned int)) return 0; if (count > (prof_len+1)*sizeof(unsigned int) - p) count = (prof_len+1)*sizeof(unsigned int) - p; read = 0; while (p < sizeof(unsigned int) && count > 0) { if (put_user(*((char *)(&sample_step)+p), buf)) return -EFAULT; buf++; p++; count--; read++; } pnt = (char *)prof_buffer + p - sizeof(atomic_t); if (copy_to_user(buf, (void *)pnt, count)) return -EFAULT; read += count; *ppos += read; return read;}我们从read_profile 函数中可以看到保存已经收集的数据是以binary的形式保存的,无法直接分析,因此要用用户态工具readprofile来解析
转载地址:http://kinmi.baihongyu.com/