BPF学习笔记(二)-- 基于BCC的BPF示例程序

        结合前面一篇针对BPF的学习,本篇文章重点介绍编写一个对内核系统调用exec的例子。本测试例子基本上包含了全部的,syscall类别系统调用的BPF的框架。

#!/usr/bin/python
from __future__ import print_function
from bcc import BPF
from collections import defaultdict

bpf_text = """
#include
#include
#include

#define ARGSIZE 256
struct data_t {
      u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
      char comm[TASK_COMM_LEN];
      char argv[ARGSIZE];
 };

BPF_PERF_OUTPUT(events);

int syscall__execve(struct pt_regs *ctx,
                   const char __user *filename,
                   const char __user *const __user *__argv,
                   const char __user *const __user *__envp)
{
    struct data_t data = {};


    bpf_trace_printk("Hello, World!222%s\\n",filename);
    data.pid = bpf_get_current_pid_tgid();
    bpf_get_current_comm(&data.comm,sizeof(data.comm));

    bpf_probe_read_user(data.argv, sizeof(data.argv), filename);

    events.perf_submit(ctx, &data, sizeof(struct data_t));

    return 0;
}

"""
b = BPF(text=bpf_text)
execve_fnname = b.get_syscall_fnname("execve")
b.attach_kprobe(event=execve_fnname, fn_name="syscall__execve")
print("%-18s %-16s %-14s" % ("COMM", "PID","ARGS"))


argv = defaultdict(list)

def print_event(cpu, data, size):
    event = b["events"].event(data)
    argv[event.pid].append(event.argv)

    argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n')

    print("%-18s %-16d %-14s" % (event.comm, event.pid,argv_text))


b["events"].open_perf_buffer(print_event)
while 1:
    try:
        b.perf_buffer_poll()
    except KeyboardInterrupt:
        exit()

主要注意点:

1. BPF_PERF_OUTPUT   创建BPF的table,通过Perf 的环形缓存区,把用户定义的event事件的数据推送到用户空间,这是把事件数据推送到用户空间的首选的方式。 也就是如果把从内核中获取到的数据,push到用户空间进行处理和展示,在代码中添加该宏。

2. b.attach_kprobe(event=execve_fnname, fn_name="syscall__execve") 这里的fn_name="syscal__execve"函数名,保持格式的绝对一致,也就是syscall__ 后面两个下划线,execve名字和内核中syscall保持一致。
3.  在内核中插桩syscall__execve 函数时,这里的第一个参数struct pt_regs *ctx 保持固定,其余的参数是syscall类函数保持一致的,下面是调用execve的参数。

 int execve(const char *pathname, char *const argv[], char *const envp[]);

4.  其实整个程序包含了两个部分,一个是python的客户端,一个是以字符串的形式bpf_text出现的插桩函数,使用C语言编写,整个测试程序包含了,用户空间和内核空间的代码。

5  bpf_trace_printk函数,类似于C语言中printf,编写bpf程序时,可以用来调试打印相关信息。注意该打印函数会将信息输出到下面的文件中:/sys/kernel/debug/tracing/trace_pipe,通过跟踪该文件进行查看。

6. print_even 函数时对内核中获取的数据和信息的统一展示。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值