Linux内核笔记 -- Events

来源:互联网 发布:网站快速排名软件 编辑:程序博客网 时间:2024/05/29 14:43

Events

下面两块代码是Perf中CallChain实现时使用的,在callchain中使用__weak来描述弱符号(Weak Symbol),在具体平台中具体实现。

__weak void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,                  struct pt_regs *regs){}__weak void perf_callchain_user(struct perf_callchain_entry_ctx *entry,                struct pt_regs *regs){}

[:linux/kernel/events/callchain.c]

voidperf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs){    struct stackframe fr;    if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {        /* We don't support guest os callchain now */        return;    }    arm_get_current_stackframe(regs, &fr);    walk_stackframe(&fr, callchain_trace, entry);}

[:linux/arch/arm/kernel/perf_callchain.c]

Call Chain 主要实现对perf处的调用栈进行回溯,列出perf处对应用户栈的调用栈。perf主要实现在多CPU环境下对各个task实现性能监控。

pmu: performance monitor uint。性能监控单元,通过编写pmu可以实现不同的性能监控,下面是perf_event_init 中列出的支持的性能监控事件组件

    perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);    perf_pmu_register(&perf_cpu_clock, NULL, -1);    perf_pmu_register(&perf_task_clock, NULL, -1);    perf_tp_register();     // -> perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);    ret = init_hw_breakpoint();    // -> perf_pmu_register(&perf_breakpoint, "breakpoint", PERF_TYPE_BREAKPOINT);

[:/linux4.13.12/kernel/events/core.c]
通过维护pmus可以初始化各个pmu的events对象,通过event上下文可以代表一个pmu的实例,对于task而言,由于可能使用多个pmu在多处理器监控性能,因此需要维护一个上下文,在创建新的task时要根据实际情况继承该上下文,在cgroup perf子系统中也要实现对任务上下文的管理。

`/** * struct perf_event_context - event context structure * * Used as a container for task events and CPU events as well: */`
struct cgroup_subsys perf_event_cgrp_subsys = {    .css_alloc  = perf_cgroup_css_alloc,    .css_free   = perf_cgroup_css_free,    .attach     = perf_cgroup_attach,    /*     * Implicitly enable on dfl hierarchy so that perf events can     * always be filtered by cgroup2 path as long as perf_event     * controller is not mounted on a legacy hierarchy.     */    .implicit_on_dfl = true,};

[:/linux4.13.12/kernel/events/core.c]
在读取event信息时,会拉取用户task对应的寄存器,调用栈等信息。结果会存储到相应的Buffer中,通过文件(use User Space Buffer)接口和mmap(use RingBuffer)反馈给用户。

static const struct vm_operations_struct perf_mmap_vmops = {    .open       = perf_mmap_open,    .close      = perf_mmap_close, /* non mergable */    .fault      = perf_mmap_fault,    .page_mkwrite   = perf_mmap_fault,};static const struct file_operations perf_fops = {    .llseek         = no_llseek,    .release        = perf_release,    .read           = perf_read,    .poll           = perf_poll,    .unlocked_ioctl     = perf_ioctl,    .compat_ioctl       = perf_compat_ioctl,    .mmap           = perf_mmap,    .fasync         = perf_fasync,};

[:/linux4.13.12/kernel/events/core.c]
hw_breakpoint是上面提到的硬件断点的下层抽象实现,会根据具体架构调用perf函数控制断点。

uprobe是一套在内核实现的用户task跟踪工具,可以用来对用户task进行调试跟踪。主要实现方法是对task注册uprobe,获取task运行环境并适时插入软件断点以实现单步,步入和调用栈跟踪等。

原创粉丝点击