1 Star 0 Fork 0

CookieYang / bpf_practice

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

bcc 开发练习

追踪sync

  1. bpf_txt:BPF C 程序,包含一个函数hello_world_printk。
  2. void *ctx: ctx有参数(如struct pt_regs *ctx),但由于我们在本例中没有使用它们,所以我们可以将其转换为void *
  3. bpf_trace_printk():一个简单的内核工具,用于printf()到公共trace_pipe ( /sys/kernel/debug/tracing/trace_pipe )。
  4. bpf_ctx = BPF(text=bpf_txt):这本质上加载 BPF C 程序并通过编译器、验证器等运行它,并返回我们用来启用事件的 BPF 对象。
  5. Attach_kprobe(event='...', fn_name='...') :使用函数入口的内核动态跟踪来检测由event的值指定的内核函数,并附加我们的 C 定义的函数(由fn_name的值,在执行命中该事件时调用。
  6. trace_print(fmt='...'):一个 BCC 例程,读取trace_pipe并以指定格式打印输出(可选)(与bpf_trace_printk一起使用)。

默认情况下(即仅trace_print()),从trace_pipe读取的每个数据都带有以下字段: {1}:进程 ID (PID) {2}:CPU# {3}:标志 {4}:Unix 时间戳 {5}、{6}、{7}:可选字段(如果使用这些字段)

在我们的例子中,我们只想打印消息“Hello World!”,因此我们只指定第 5 个 ( {5} ) 字段,其中包含我们的消息 跟踪打印

  • while 1:我们在这里使用无限 while 循环(就像大多数 BPF 程序一样),这样我们就可以连续轮询trace_pipe(或任何其他输出流)并检查另一端是否有数据要读取。 使用try:和except:进行更安全的处理

BPF_PERF_OUTPUT sync_hello_world

  1. BPF_PERF_OUTPUT(events):创建一个 BPF 表,用于通过 perf 环形缓冲区将自定义事件数据推送到用户空间。
  • 将每个事件数据推送到用户空间的首选方法
  • 在我们的示例中,输出表名为events,自定义事件数据(在struct data_t data中)通过以下方式推送到用户空间。events.perf_submit()
  • BPF_PERF_输出
  • struct data_t:定义自定义 C 数据结构以将数据(通过 perf 的环形缓冲区)从内核传递到用户空间.在我们的示例中,我们发送的唯一数据是“Hello World!” string,所以我们定义一个长度>=字符串实际长度的char数组
  1. __builtin_memcpy() : memcpy()的内置版本。 回想一下,BPF C 代码中不允许有循环,因此不允许memcpy()

  2. events.perf_submit() :使用BPF_PERF_OUTPUT表将自定义事件数据提交到用户空间的方法。

  3. open_perf_buffer bpf_ctx["events"].open_perf_buffer(handle_event):将 Python handle_event函数与BPF_PERF_OUTPUT(events)输出流关联。

  4. perf_buffer_poll():轮询任何打开的性能缓冲区以获取新数据。

  5. handle_event(cpu, data, size):处理从事件流中读取事件的Python函数。

  • 函数参数cpu、data、size是必需的参数
  • bpf_ctx["events"].event(data)将事件数据作为 Python 对象抓取,该对象是从 C 数据结构struct data_t自动生成的
  • Python事件对象的字段与BPF C程序中定义的完全相同(例如output.str)

追踪sync-fields

(task, pid, cpu, flags, ts, msg) = b.trace_fields()

TIME(s)            COMM             PID    MESSAGE
19701.696061000    postgres         880    Hello, World!
19739.556299000    systemd-logind   680    Hello, World!
19739.557980000    systemd-udevd    325    Hello, World!
19745.895216000    systemd-logind   680    Hello, World!
19745.896988000    systemd-udevd    325    Hello, World!

bite_hist

直方图编译BPF出错

sync_timing fields

控制台sync;sync;sync 触发

  1. bpf_ktime_get_ns():返回以纳秒为单位的时间。
  2. BPF_HASH(last):创建一个BPF映射对象,它是一个散列(关联数组),称为“last”。我们没有指定任何进一步的参数,因此它默认为 u64 的键和值类型。
  3. key = 0:我们只会在此哈希中存储一个键/值对,其中键被硬连接为零。
  4. last.lookup(&key):在哈希中查找键,如果存在则返回指向其值的指针,否则返回NULL。我们将密钥作为地址传递给指针。
  5. if (tsp != NULL) {:验证程序要求必须检查从映射查找派生的指针值是否为空值,然后才能取消引用和使用它们。
  6. last.delete(&key):从哈希中删除密钥。由于4.8.10中的内核错误.update()(已在 4.8.10 中修复),目前需要这样做。
  7. last.update(&key, &ts):将第二个参数中的值与键关联,覆盖任何先前的值。这记录了时间戳。

sync_count

不能使用*curct++,可能是因为内核数据的原因,只能通过count.update更新;

disksnoop

TODO

execve_data

TODO

内核动态追踪

空文件

简介

练习学习bpf 展开 收起
Python
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/yangrudan/bpf_practice.git
git@gitee.com:yangrudan/bpf_practice.git
yangrudan
bpf_practice
bpf_practice
master

搜索帮助