Lesson 7. hello_perf_output.py

之前的例子我们都是通过bpf_trace_printk()来打印log,这种方式打印的log的格式是固定的
下面这个例子的就是告诉自定义要打印的成员
其输出的log类似。可以看到和前面完全不同的打印
TIME(s)            COMM             PID    MESSAGE
0.000000000        bash             22986  Hello, perf_output!
0.021080275        systemd-udevd    484    Hello, perf_output!
0.021359520        systemd-udevd    484    Hello, perf_output!
0.021590610        systemd-udevd    484    Hello, perf_output!


#!/usr/bin/env python
#
# This is a Hello World example that uses BPF_PERF_OUTPUT.

from bcc import BPF
#导入ctypes 这个第三方库,这样就可以在python中使用c语言定义的基本数据类型
import ctypes as ct

# define BPF program
prog = """
#include <linux/sched.h>
// define output data structure in C
#定义一个要打印的结构体,从这里看可以打印pid.时间ts,和正在执行程序的名字 comm
struct data_t {
    u32 pid;
    u64 ts;
    char comm[TASK_COMM_LEN];
};
#定义一个output,c语言的log 打印到这个output中,就可以在python中拿到
BPF_PERF_OUTPUT(events);
#定义一个触发后要执行的函数
int hello(struct pt_regs *ctx) {
    #定义要打印的数据结构,并赋值
    struct data_t data = {};
    data.pid = bpf_get_current_pid_tgid();
    data.ts = bpf_ktime_get_ns();
    bpf_get_current_comm(&data.comm, sizeof(data.comm));
    #通过perf ring buffer将这个event submit到user space
    events.perf_submit(ctx, &data, sizeof(data));
    return 0;
}
"""

# load BPF program
#装载这个BPF程序到kernel space
b = BPF(text=prog)
#设置出触发函数为sys_clone。
b.attach_kprobe(event="sys_clone", fn_name="hello")

# define output data structure in Python
#引用kernel中的全局变量
TASK_COMM_LEN = 16    # linux/sched.h
#这里定义了一个python 类继承ct.Structure
class Data(ct.Structure):
    #类中定义一个变量,这个变量的取值和c 语言中定义的struct data_t 的数据结构一致,因此这样用了第三方库ctypes
    #中的值
    _fields_ = [("pid", ct.c_uint),
                ("ts", ct.c_ulonglong),
                ("comm", ct.c_char * TASK_COMM_LEN)]

# header
print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE"))

# process event
start = 0
#定义一个python 函数
def print_event(cpu, data, size):
    #生命这个start是全局变量
    global start
   #当行惨data 专程python中定义的Data类
    event = ct.cast(data, ct.POINTER(Data)).contents
    if start == 0:
            start = event.ts
    time_s = (float(event.ts - start)) / 1000000000
    #这样就可以像在c语言中一样,调用event的成员变量
    print("%-18.9f %-16s %-6d %s" % (time_s, event.comm, event.pid,
        "Hello, perf_output!"))

# loop with callback to print_event
#指明b代表的events 使用print_event 来打印log
b["events"].open_perf_buffer(print_event)
while 1:
	#阻塞,等待sys_clone 这个系统调用被调用
	b.kprobe_poll()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值