之前的例子我们都是通过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()
Lesson 7. hello_perf_output.py
最新推荐文章于 2024-03-29 00:37:01 发布