下面这个例子会在每次调用finish_task_switch的时候调用count_sched
from bcc import BPF
from time import sleep
#load 一个文件到kernel space
b = BPF(src_file="task_switch.c")
b.attach_kprobe(event="finish_task_switch", fn_name="count_sched")
# generate many schedule events
for i in range(0, 100): sleep(0.01)
#由于前面的for循环,b中已经保存了一下信息
#从for询函的打印看b["stats"].items() 包含前一个进程和当前进程的pid和值。
for k, v in b["stats"].items():
print("task_switch[%5d->%5d]=%u" % (k.prev_pid, k.curr_pid, v.value))
task_switch.c的源码如下:
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
#前面要打印key的值,
struct key_t {
u32 prev_pid;
u32 curr_pid;
};
// map_type, key_type, leaf_type, table_name, num_entry
#这里定义stats 表,则可以通过b["stats"] 来访问
BPF_HASH(stats, struct key_t, u64, 1024);
// attach to finish_task_switch in kernel/sched/core.c, which has the following
// prototype:
// struct rq *finish_task_switch(struct task_struct *prev)
int count_sched(struct pt_regs *ctx, struct task_struct *prev) {
struct key_t key = {};
u64 zero = 0, *val;
#分别赋值
key.curr_pid = bpf_get_current_pid_tgid();
key.prev_pid = prev->pid;
val = stats.lookup_or_init(&key, &zero);
(*val)++;
return 0;
}
总结一下。BPF 可以debug kernel/user space/pid/c库 。这几个例子就能看出针对
这里用到的所有的BPF函数都可以在kernel 源码中找到
Lesson 16. task_switch.c
最新推荐文章于 2023-07-25 08:00:38 发布