bpf的了解以及bpftrace的简单练习

最近接触到bpf的概念,简单做一些练习,做以下整理,学习笔记。

0:总结

使用ebpf可以实现的功能打开新世界,可以不改变源码的情况下,实现内存,网络,对应接口等各种期望内容的监控。

可以使用bpf直接进行开发,使用clang编译成ebpf字节序后加载进行使用。

使用bcc进行开发实现功能,多是python/lua,对应的demo可以参考githuab.

使用bpftool工具集可以进行加载,查看,卸载等一系列的功能,没有过多研究。

使用bpftrace一行指令已经可以方便实现很多的功能,比如监控文件打开,监控内存申请,监控函数调用次数,在内存,网络,sql调用,以及接口相关都有很多很方便的功能,进行简单的使用测试。

1:了解什么是ebpf,bpf,bcc, bpftool,bpftrace

直接问ai,简单又一些认知。

eBPF 是底层技术,所有这些工具(BPF, BCC, bpftool, BPFtrace)都基于 eBPF 工作。
BPF 是 eBPF 的前身,如今被 eBPF 所取代。
BCC 提供了一套方便的 API 和工具,帮助开发者快速编写和运行 eBPF 程序。
bpftool 用于管理和调试 eBPF 程序,可以查看运行的 eBPF 程序及其相关资源。
BPFtrace 提供了一个高级脚本语言,用于快速编写和运行简单的 eBPF 程序,主要用于追踪和分析。
总之,这些工具和框架都围绕 eBPF 工作,帮助开发者更方便地利用 eBPF 的强大功能。

eBPF(Extended Berkeley Packet Filter)及其相关工具(BPF, BCC, bpftool, BPFtrace)都是用于动态追踪、性能分析和网络调试的技术和工具,尤其是在 Linux 环境中。以下是对它们的介绍以及它们之间的关系:1. eBPF (Extended Berkeley Packet Filter)
eBPF 是 Linux 内核中的一个扩展,它允许用户在内核中运行自定义的字节码程序,而无需修改或重启内核。
最初用于网络数据包过滤,但现在 eBPF 的应用范围已经扩展到了性能监控、安全分析、网络流量控制等多个领域。
eBPF 程序在内核中运行时是安全的,因为它们在执行前会经过内核的验证器验证,以确保不会损坏系统。
2. BPF
BPF 是 Berkeley Packet Filter 的缩写,是 eBPF 的前身。
最早设计用于网络数据包过滤,但功能较为有限,eBPF 则是其增强版。
BPF 程序可以通过系统调用加载到内核中执行,但随着时间的推移,eBPF 逐渐取代了传统 BPF。
3. BCC (BPF Compiler Collection)
BCC 是一个工具集,用于简化 eBPF 程序的编写和运行。
它提供了高级语言(如 Python 和 Lua)的 API,以便用户能够方便地编写 eBPF 程序。
BCC 中包含了许多现成的 eBPF 工具,用于追踪系统事件、网络流量、文件系统等。
使用 BCC 时,用户不需要直接编写 eBPF 字节码,而是通过高级语言和宏来生成和管理 eBPF 程序。
4. bpftool
bpftool 是 eBPF 的管理工具,主要用于查看、加载、卸载和调试 eBPF 程序。
它允许用户列出内核中加载的 eBPF 程序、地图(maps)和统计信息。
bpftool 提供了对内核 eBPF 子系统的细粒度控制和信息查看功能,通常用于开发和调试 eBPF 程序。
5. BPFtrace
BPFtrace 是一个简化的 eBPF 追踪工具,专注于动态追踪和性能分析。
它的语法受 DTrace 启发,更为简洁,用户可以通过简单的脚本编写复杂的追踪逻辑。
相比 BCC,BPFtrace 更加适合快速编写和运行短小的 eBPF 程序,适合于即时性能分析和诊断。

2:使用bpf进行测试,用户在终端上使用ls等指令时,测试demo能进行监控并展示。

使用22.04进行测试时,和已有demo不适配,高版本直接用bcc,bpftrace等进行直接开发吧。

这里用18.04进行环境安装以及demo测试。

2.1 在18.04上安装bpf

不支持直接安装,没有libbpf-dev

ubuntu@ubuntu:~$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.6 LTS
Release:	18.04
Codename:	bionic
ubuntu@ubuntu:~$ sudo apt-get install build-essential
#可以看到 不支持这个库的直接安装
ubuntu@ubuntu:~$ sudo apt install libbpf-dev
E: Unable to locate package libbpf-dev

使用源码安装的方式

#使用源码安装的方式  去linux内核官网找对应系统的源码下载也可以  ()
#方案一  下载linux内核源码,转到对应的版本分治     这个在网络不稳定的情况下,太耗时,分支太多,太大了。
git clone https://github.com/torvalds/linux.git  
cd linux
git checkout v$(uname -r | cut -d'-' -f1)#方案二  发现一个很容易获取系统对应内核源码的方式 这种方式可能获取到的版本比较旧 与当前内核版本有差异 (可以下载指定内核的)
sudo apt-get install linux-source
cd /usr/src
tar xjf linux-source-$(uname -r).tar.bz2
cd linux-source-$(uname -r)

实际操作如下:

ubuntu@ubuntu:~$ cd /usr/src/
ubuntu@ubuntu:/usr/src$ ls
linux-headers-4.15.0-213  linux-headers-4.15.0-213-genericubuntu@ubuntu:/usr/src$ sudo apt-cache search linux-source
ubuntu@ubuntu:/usr/src$ sudo apt-get install linux-source
ubuntu@ubuntu:/usr/src$ ls
linux-headers-4.15.0-213  linux-headers-4.15.0-213-generic  linux-source-4.15.0  linux-source-4.15.0.tar.bz2
ubuntu@ubuntu:/usr/src$ sudo tar xf linux-source-4.15.0.tar.bz2#遇到问题 处理问题  这里直到最后编译成功  连bpftool也编译成功了。
ubuntu@ubuntu:/usr/src/linux-source-4.15.0/tools/bpf$ sudo apt-get install binutils-dev
ubuntu@ubuntu:/usr/src/linux-source-4.15.0/tools/bpf$ sudo apt-get install libreadline-dev
ubuntu@ubuntu:/usr/src/linux-source-4.15.0/tools/bpf$ sudo apt-get install bison
ubuntu@ubuntu:/usr/src/linux-source-4.15.0/tools/bpf$ sudo apt-get install binutils elfutilsroot@ubuntu:/usr/src/linux-source-4.15.0/tools/lib/bpf# makeAuto-detecting system features:
...                        libelf: [ on  ]
...                           bpf: [ on  ]Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h'CC       libbpf.oCC       bpf.oLD       libbpf-in.oLINK     libbpf.aLINK     libbpf.so
root@ubuntu:/usr/src/linux-source-4.15.0/tools/lib/bpf# make install
Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h'INSTALL  libbpf.aINSTALL  libbpf.so#看起来默认安装在 /usr/local/lib64
root@ubuntu:/# find -name libbpf.a
./usr/local/lib64/libbpf.a
./usr/src/linux-source-4.15.0/tools/lib/bpf/libbpf.a

2.2 进行测试,首先要实现ebpf程序。(目标:使用clang把该程序编译成ebpf字节码。)

eBPF 程序通常是内核态的代码,使用 clang 编译为特定格式的字节码(BPF 字节码),然后加载到内核中。

//bpf_program.c
#include <linux/bpf.h>
#define SEC(NAME) __attribute__((section(NAME), used))static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = (void *)BPF_FUNC_trace_printk;SEC("tracepoint/syscalls/sys_enter_execve")
int bpf_prog(void *ctx) {char msg[] = "Hello, BPF World!";bpf_trace_printk(msg, sizeof(msg));
return 0;
}char _license[] SEC("license") = "GPL";

使用clang把该程序编译成ebpf字节码:

ubuntu@ubuntu:~/bpf_test/bpf$ sudo apt-get install clang
ubuntu@ubuntu:~/bpf_test/bpf$ clang -O2 -target bpf -c bpf_program.c -I /usr/include/x86_64-linux-gnu/ -o bpf_program.o

2.3 编写用户空间程序,加载上面的ebpf程序,并执行。

这里的内核版本提供了bpf_load.h,使用这个接口进行使用。(高版本已经不提供了,实现可能有差异,不研究了)

#include "bpf_load.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>#define DEBUGFS "/sys/kernel/debug/tracing/"void myread_trace_pipe(void)
{int trace_fd;trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0);if (trace_fd < 0)return;while (1) {static char buf[4096];ssize_t sz;sz = read(trace_fd, buf, sizeof(buf) - 1);if (sz > 0) {buf[sz] = 0;puts(buf);}}
}int main(int argc, char **argv) {if (load_bpf_file("bpf_program.o") != 0) {printf("The kernel didn't load the BPF program\\n");return -1;}myread_trace_pipe();return 0;
}

2.4 借助对应makefile进行编译

注意:这里使用了内核下的 bpf_load.c

CLANG = clangEXECABLE = monitor-exec#这里之际使用了内核提供给的bpf_load.c 借助libbpf
BPFCODE = bpf_program
BPFTOOLS = /usr/src/linux-source-4.15.0/samples/bpf
BPFLOADER = $(BPFTOOLS)/bpf_load.c
BPFLIB = /usr/src/linux-source-4.15.0/tools/lib/bpf/libbpf.c #/usr/include/linux/types.h:5:10: fatal error: 'asm/types.h' file not found  这个与我ubuntu有关吧
CCINCLUDE += -I/usr/include/x86_64-linux-gnu/CCINCLUDE += -I/usr/src/linux-source-4.15.0/tools/testing/selftests/bpfLOADINCLUDE += -I/usr/src/linux-source-4.15.0/samples/bpf
LOADINCLUDE += -I/usr/src/linux-source-4.15.0/tools/lib
LOADINCLUDE += -I/usr/src/linux-source-4.15.0/tools/perf
LOADINCLUDE += -I/usr/src/linux-source-4.15.0/tools/include
LIBRARY_PATH = -L/usr/local/lib64
BPFSO = -lbpfCFLAGS += $(shell grep -q "define HAVE_ATTR_TEST 1" /usr/src/linux-source-4.15.0/tools/perf/perf-sys.h && echo "-DHAVE_ATTR_TEST=0").PHONY: clean $(CLANG) bpfload buildclean:rm -f *.o *.so $(EXECABLE)build: ${BPFCODE.c} ${BPFLOADER}$(CLANG) -O2 -target bpf -c $(BPFCODE:=.c) $(CCINCLUDE) -o ${BPFCODE:=.o}bpfload: buildclang $(CFLAGS) -o $(EXECABLE) -lelf $(LOADINCLUDE) $(LIBRARY_PATH) $(BPFSO) $(BPFLIB) $(BPFLOADER)  loader.c$(EXECABLE): bpfload.DEFAULT_GOAL := $(EXECABLE)

2.4 运行测试(运行ls时触发到监控打印Hello, BPF World)

ubuntu@ubuntu:~/bpf_test/bpf$ make
clang -O2 -target bpf -c bpf_program.c -I/usr/include/x86_64-linux-gnu/ -I/usr/src/linux-source-4.15.0/tools/testing/selftests/bpf -o bpf_program.o
clang  -o monitor-exec -lelf -I/usr/src/linux-source-4.15.0/samples/bpf -I/usr/src/linux-source-4.15.0/tools/lib -I/usr/src/linux-source-4.15.0/tools/perf -I/usr/src/linux-source-4.15.0/tools/include -L/usr/local/lib64 -lbpf /usr/src/linux-source-4.15.0/tools/lib/bpf/libbpf.c  /usr/src/linux-source-4.15.0/samples/bpf/bpf_load.c  loader.c#默认安装在/usr/local/lib64
ubuntu@ubuntu:~/bpf_test/bpf$ sudo ./monitor-exec 
./monitor-exec: error while loading shared libraries: libbpf.so: cannot open shared object file: No such file or directory
ubuntu@ubuntu:~/bpf_test/bpf$ ldconfig /usr/local/lib64
/sbin/ldconfig.real: Can't create temporary cache file /etc/ld.so.cache~: Permission denied
ubuntu@ubuntu:~/bpf_test/bpf$ sudo ldconfig /usr/local/lib64
ubuntu@ubuntu:~/bpf_test/bpf$ sudo ./monitor-exec <...>-11425 [000] ....  4464.404847: 0x00000001: Hello, BPF World!<...>-11426 [000] ....  4466.860991: 0x00000001: Hello, BPF World!bash-11427 [001] ....  4470.069820: 0x00000001: Hello, BPF World!#这里执行后,在另外的终端上 执行ls 就会触发上面的逻辑,其他的逻辑可以扩展。

3:bcc和bpftool

基于libbpf进行调用外,可以使用bcc调用python/lua脚本进行实现。 安装后,bcc其实有一些可以直接使用的功能。可以参考开源库bcc下对应的example。

bpftool是一个工具,可以用于查看、加载、卸载、和调试 eBPF 程序的功能。(最好从github上源码入手) ubuntu@ubuntu:/$ sudo apt install -y linux-tools-$(uname -r)

ubuntu@ubuntu:~$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 22.04.2 LTS
Release:	22.04
Codename:	jammyubuntu@ubuntu:~$ sudo apt-get install build-essential #可以使用源码进行安装  git clone https://github.com/libbpf/libbpf.git   
#可以在内核源码中直接安装吧?
ubuntu@ubuntu:/usr/lib$ sudo apt install libbpf-dev
ubuntu@ubuntu:~$ cd /usr/lib
ubuntu@ubuntu:/usr/lib$ sudo find /usr/lib -name libbpf.so
/usr/lib/x86_64-linux-gnu/libbpf.so
ubuntu@ubuntu:/usr/lib$ ls -ls /usr/include/bpf/
total 28820 -rw-r--r-- 1 root root  17992 Dec  1  2022 bpf_core_read.h4 -rw-r--r-- 1 root root   3750 Dec  1  2022 bpf_endian.h12 -rw-r--r-- 1 root root  10066 Dec  1  2022 bpf.h
148 -rw-r--r-- 1 root root 149473 Dec  1  2022 bpf_helper_defs.h8 -rw-r--r-- 1 root root   7679 Dec  1  2022 bpf_helpers.h20 -rw-r--r-- 1 root root  19194 Dec  1  2022 bpf_tracing.h16 -rw-r--r-- 1 root root  12856 Dec  1  2022 btf.h4 -rw-r--r-- 1 root root   1421 Dec  1  2022 libbpf_common.h36 -rw-r--r-- 1 root root  33279 Dec  1  2022 libbpf.h4 -rw-r--r-- 1 root root   1525 Dec  1  2022 libbpf_legacy.h4 -rw-r--r-- 1 root root   2894 Dec  1  2022 skel_internal.h12 -rw-r--r-- 1 root root   8608 Dec  1  2022 xsk.h#终于搞清楚了 ,内核一些低版本,提供了使用bpf_load.h对ebpf的一些封装,可以使用,高一些的版本,是没有这个文件的,可以直接用ebpf来实现。
#bpf_load.h 是内核中的一个头文件,常见于 samples/bpf 和 tools/testing/selftests/bpf 目录中,提供了简化加载 eBPF 程序并管理 eBPF maps 的 API。#这使得用户空间程序可以更轻松地与 eBPF 程序交互并加载到内核中#本来想基于22.04试试bpf的安装后运行,发现和18.04有点差异,18.04有已有demo,可正常运行,但22.04相关高版本内核不提供bpf_load.h,主要了解逻辑,不关注了。sudo apt install build-essential \libelf-dev \libz-dev \libcap-dev \binutils-dev \pkg-config#终于知道这几个库用在哪里用了  make报错依次解决  手动编译流程~   git clone https://github.com/libbpf/bpftool.git 下载?        
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# sudo apt-get install binutils-dev
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# sudo apt-get install libcap-dev
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# sudo apt-get install llvm
#直接在刚才下载linux源码的位置处编译bpftool
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# makeAuto-detecting system features:
...                        libbfd: [ on  ]
...        disassembler-four-args: [ on  ]
...                          zlib: [ on  ]
...                        libcap: [ on  ]
...               clang-bpf-co-re: [ on  ]
。。。
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# ./bpftool --version
./bpftool v5.15.163
features: libbfd, skeletons#上面bpf的测试在22.04 编译不过啊   高版本已经不提供用bpf_load.h 了 

4:bpftrace的安装练习

bpftrace 一行指令已经实现很多功能,可以参考github进行学习。

bpftrace 可以说实现监控网络,内存等各种功能,根据业务可以思考。

思考探测内核函数,用户可执行程序中接口,so接口,静态库接口。

在这里插入图片描述

4.1 安装bpftrace (ubuntu 22.04)

#基于前面已经安装过一系列的组件   可以参考网络或者源码安装 这里初入门了解
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# apt install bpftrace
root@ubuntu:/usr/src/linux-source-5.15.0/tools/bpf/bpftool# bpftrace --version
bpftrace v0.14.0

4.2 简单了解bpftrace 相关语法。

4.2.1 结构语法及参数介绍

在这里插入图片描述

在这里插入图片描述

4.2.2 常用内置变量
内置变量
bpftrace 脚本常用变量如下:uid:用户 id。tid:线程 idpid:进程 id。cpu:cpu id。cgroup:cgroup id.probe:当前的 trace 点。comm:进程名字。nsecs:纳秒级别的时间戳。kstack:内核栈描述curtask:当前进程的 task_struct 地址。args:获取该 kprobe 或者 tracepoint 的参数列表arg0:获取该 kprobe 的第一个变量,tracepoint 不可用arg1:获取该 kprobe 的第二个变量,tracepoint 不可用arg2:获取该 kprobe 的第三个变量,tracepoint 不可用retval: kretprobe 中获取函数返回值args->ret: kretprobe 中获取函数返回值自定义变量以'$'标志起来定义与引用变量,例如:$idx = 0;
Map 变量Map 变量是用于内核向用户空间传递数据的一种存储结构,定义方式是以'@'符号作为标志@path[tid] = nsecs;@path[pid, $fd] = nsecs;Bpftrace 默认在结束时会打印从内核接收到的 map 变量
内置函数exit():退出 bpftrace 程序str(char *):转换一个指针到 string 类型system(format[, arguments ...]):运行一个 shell 命令join(char *str[]):打印一个字符串列表并在每个前面加上空格,比如可以用 来输出 args->argvksym(addr):用于转换一个地址到内核 symbolkaddr(char *name):通过 symbol 转换为内核地址print(@m [, top [, div]]):可选择参数打印 map 中的 top n 个数据,数据可选择除以一个 div 值buf(void *p [, int length])strncmp(char *s1, char *s2, int length)sizeof(expression)ustack([limit])ksym(void *p)kstack([limit])usym(void *p)kaddr(char *name)uaddr(char *name)ntop([int af,]int|char[4:16] addr)reg(char *name)cgroupid(char *path)bpftrace 内置了 map 对象操作函数,用于传递数据给 map 变量。count():用于计算次数sum(int n):用于累加计算avg(int n):用于计算平均值min(int n):用于计算最小值max(int n):用于计算最大值hist(int n):数据分布直方图(范围为 2 的幂次增长)lhist(int n):数据线性直方图delete(@m[key]):删除 map 中的对应的 key 数据clear(@m):删除 map 中的所有数据zero(@m):map 中的所有值设置为 0

4.3 简单练习bpf的相关一行指令

#统计调用read的次数
root@ubuntu:/home/ubuntu# bpftrace -e 't:syscalls:sys_enter_read {@[probe]=count(); }'
Attaching 1 probe...
^C@[tracepoint:syscalls:sys_enter_read]: 94#统计write调用的次数
root@ubuntu:/home/ubuntu#  bpftrace -e 't:syscalls:sys_enter_write {@[probe]=count();}'
Attaching 1 probe...
^C@[tracepoint:syscalls:sys_enter_write]: 22#统计调用read 按参数 输出 数据分布直方图展示   ssize_t read(int fd, void *buf, size_t count);
root@ubuntu:/home/ubuntu# bpftrace -e 't:syscalls:sys_enter_read {@=hist(args->count);}'
Attaching 1 probe...
^C@: 
[1K, 2K)              29 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2K, 4K)               0 |                                                    |
[4K, 8K)               0 |                                                    |
[8K, 16K)              0 |                                                    |
[16K, 32K)             4 |@@@@@@@                                             |
[32K, 64K)             0 |                                                    |
[64K, 128K)            0 |                                                    |
[128K, 256K)           0 |                                                    |
[256K, 512K)           4 |@@@@@@@                                             |#追踪openat 系统调用  打开文件的入口   统计进程名和打开的文件 
root@ubuntu:/home/ubuntu# bpftrace -e 't:syscalls:sys_enter_openat { printf("%s–> %s\n", comm,str(args->filename)); }'
Attaching 1 probe...
irqbalance–> /proc/interrupts
irqbalance–> /proc/stat
vmtoolsd–> /proc/meminfo
vmtoolsd–> /proc/vmstat
vmtoolsd–> /proc/stat
vmtoolsd–> /proc/zoneinfo
vmtoolsd–> /proc/uptime
vmtoolsd–> /proc/diskstats#需要查找文件时触发  追踪内核函数 lookup_fast 的调用次数
root@ubuntu:/home/ubuntu#  bpftrace -e 'kprobe:lookup_fast { @[comm, pid] = count(); }'
Attaching 1 probe...
^C@[systemd-network, 847]: 3
@[systemd, 1]: 6
@[irqbalance, 879]: 8
@[cron, 871]: 15
@[vmtoolsd, 762]: 24
@[snapd, 885]: 148#统计阻塞 io 事件   表示捕获所有与块设备相关的 tracepoint 事件 并记录每个 tracepoint 被触发的次数
root@ubuntu:/home/ubuntu#  bpftrace -e 't:block:* { @[probe] = count(); }'
Attaching 18 probes...
^C@[tracepoint:block:block_rq_complete]: 17
@[tracepoint:block:block_rq_issue]: 17#统计 阻塞 io 操作数据大小     block_rq_issue用于捕获块设备的 I/O 请求被发出的事件
root@ubuntu:/home/ubuntu#  bpftrace -e 't:block:block_rq_issue { @bytes = hist(args->bytes); }'
Attaching 1 probe...
^C@bytes: 
[8, 16)                4 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|#追踪块设备的 I/O 请求完成事件 block_rq_complete,并打印出那些包含错误的请求的相关信息
root@ubuntu:/home/ubuntu#  bpftrace -e 't:block:block_rq_complete /args->error/ {printf("dev %d type %s error %d\n", args->dev, args->rwbs, args->error); }'
Attaching 1 probe...
^C
root@ubuntu:/home/ubuntu#  bpftrace -e 't:block:block_rq_complete {printf("dev %d type %s error %d\n", args->dev, args->rwbs, args->error); }'
Attaching 1 probe...
dev 0 type N error 0
dev 0 type N error 0
dev 0 type N error 0#启动的进程名与命令行参数
root@ubuntu:/home/ubuntu# bpftrace -e 'tracepoint:syscalls:sys_enter_execve { join(args->argv); }'
Attaching 1 probe...
ls --color=auto
ls --color=auto
ls --color=auto
ls --color=auto
cat 1#追踪所有系统调用的进入点 统计次数
root@ubuntu:/home/ubuntu# bpftrace -e 'tracepoint:raw_syscalls:sys_enter{ @[pid, comm] = count(); }'
Attaching 1 probe...
^C@[882, rsyslogd]: 3
@[871, cron]: 6
@[889, pool-udisksd]: 6
@[889, udisksd]: 12
@[887, systemd-logind]: 15
@[749, systemd-timesyn]: 15
@[849, systemd-resolve]: 15
@[847, systemd-network]: 20
@[1316, sshd]: 24
@[1627, bash]: 33
@[1, systemd]: 46
@[762, HangDetector]: 52
@[879, irqbalance]: 70
@[1593, sshd]: 74
@[1594, bash]: 76
@[1627, ls]: 121
@[885, snapd]: 181
@[569, multipathd]: 324
@[1620, bpftrace]: 525
@[762, vmtoolsd]: 3969#追踪进程上下文切换事件,并统计每个上下文切换期间的内核堆栈信息的出现次数 
root@ubuntu:/home/ubuntu# bpftrace -e 'tracepoint:sched:sched_switch { @[kstack] = count(); }'
Attaching 1 probe...
^C@[__schedule+855__schedule+855schedule+105schedule_timeout+135msleep+45usb_port_suspend+908usb_generic_driver_suspend+67usb_suspend_both+506usb_runtime_suspend+47__rpm_callback+74rpm_callback+103rpm_suspend+356__pm_runtime_suspend+73usb_runtime_idle+58rpm_idle+195pm_runtime_work+141process_one_work+552worker_thread+83kthread+295ret_from_fork+31
]: 1bpftrace -e 'u:/lib/x86_64-linux-gnu/libpthread2.31.so:pthread_create { printf("%s by %s (%d)\n", probe, comm, pid ); }'
sudo find -name libpthread*
ldd ./usr/lib32/libpthread.so.0
ldd ./usr/lib/x86_64-linux-gnu/libpthread.so.0
nm -D ./usr/lib/x86_64-linux-gnu/libpthread.so.0
ldd ./usr/lib/x86_64-linux-gnu/libpthread.so.0
nm -D lib/x86_64-linux-gnu/libc.so.6|grep thread_createroot@ubuntu:/# ldconfig -p | grep libpthreadlibpthread.so.0 (libc6,x86-64, OS ABI: Linux 3.2.0) => /lib/x86_64-linux-gnu/libpthread.so.0libpthread.so.0 (libc6, OS ABI: Linux 3.2.0) => /lib32/libpthread.so.0#进程创建 pthread_create	探测  (写了个测试代码调用pthread_create)
root@ubuntu:/# bpftrace -e 'u:/lib/x86_64-linux-gnu/libc.so.6:pthread_create { printf("%s by %s (%d)\n", probe, comm, pid ); }'
Attaching 1 probe...
uprobe:/lib/x86_64-linux-gnu/libc.so.6:pthread_create by pthread (17916)
uprobe:/lib/x86_64-linux-gnu/libc.so.6:pthread_create by pthread (17918)
uprobe:/lib/x86_64-linux-gnu/libc.so.6:pthread_create by pthread (17920)#内核堆栈跟踪的内存分配情况 统计内存分配总字节数root@ubuntu:/# bpftrace -e 't:kmem:kmem_cache_alloc { @bytes[kstack] = sum(args->bytes_alloc); }'
Attaching 1 probe...
^C^C@bytes[kmem_cache_alloc+623kmem_cache_alloc+623__sigqueue_alloc+123__send_signal+614send_signal+233do_send_sig_info+96__kill_pgrp_info+133kill_pgrp+53isig+150n_tty_receive_signal_char+27n_tty_receive_char_special+1086n_tty_receive_buf_standard+326__receive_buf+507n_tty_receive_buf_common+139n_tty_receive_buf2+20tty_ldisc_receive_buf+31tty_port_default_receive_buf+66flush_to_ldisc+170process_one_work+552worker_thread+83kthread+295ret_from_fork+31
]: 80#统计malloc的调用次数  
root@ubuntu:/#  bpftrace -e 'u:/lib/x86_64-linux-gnu/libc.so.6:malloc {@[ustack, comm] = sum(arg0); }'
Attaching 1 probe...
^C@[__libc_malloc+0
, bpftrace]: 4
@[__libc_malloc+00x55e8989dbcc00x55e8989d74000x8148535554415541
, bpftrace]: 8
@[__libc_malloc+0
, bpftrace]: 8
@[__libc_malloc+0
, bpftrace]: 24
@[__libc_malloc+00x5618bcac89f00x20
, sshd]: 448#统计进程发生缺页中断  写了个mmap 分配内存并访问 触发缺页中断
root@ubuntu:/# bpftrace -e 't:exceptions:page_fault_user { @[ustack, comm] = count(); }'
Attaching 1 probe...
^CERROR: failed to look up stack id -17 (pid -1): -1
@[0x7fc0b22a57e1
, bash]: 1
@[0x7f5cafa996100x69622f3d4c4c4548
, mmap]: 1

4.4 使用脚本进行练习

4.4.1 探测打开文件 输出对应文件名
#脚本进行测试  首先测试 探测打开文件的名称或者路径 
root@ubuntu:/# bpftrace -e '
kprobe:vfs_open {$path = (struct path *)arg0;$dentry = $path->dentry;printf("open path: %s\n", str($dentry->d_name.name));
}'
#写入文件
ubuntu@ubuntu:~/test$ cat fs.bt 
#include <linux/path.h>
#include <linux/dcache.h>kprobe:vfs_open {// printf("open path :%s \n",str((struct path*)arg0)->dentry->d_name.name); //不能直接打印 要提取到用户空间$path = (struct path *)arg0;$dentry = $path->dentry;printf("open path: %s\n", str($dentry->d_name.name));
}root@ubuntu:/home/ubuntu/test# bpftrace fs.bt 
Attaching 1 probe...
open path: interrupts
open path: stat
open path: smp_affinity
open path: smp_affinity
4.4.2 探测tcp连接的网络五元组。
//探测五元组   除了accept  还可以其他相关 比如tcp的状态,比如connect recv send按需求处理#include <linux/socket.h>
#include <net/sock.h>
#include <linux/types.h>// BEGIN 
// { 
// 	printf("hello\n"); 
// }//梳理 kprobe和kretprobe区别 
kprobe:inet_csk_accept
{printf("inet_csk_accept\n"); 
}kretprobe:inet_csk_accept
{$sk = (struct sock*)retval;$inet_family = $sk->__sk_common.skc_family;$daddr = ntop(0);$saddr = ntop(0);if ($inet_family == AF_INET) {$daddr = ntop($sk->__sk_common.skc_daddr);$saddr = ntop($sk->__sk_common.skc_rcv_saddr);		}$sport = $sk->__sk_common.skc_num;$dport = $sk->__sk_common.skc_dport; //大小端转换 不提供类型 自处理$dport_num = ((($dport <<8) &0xFF00 )| (($dport>>8)&0xFF)) &0xFFFF;printf(" tcp_accept: %-16s:%d %d--> %-16s:%d\n", $daddr, $dport, $dport_num, $saddr, $sport);
}

使用网络助手进行连接 测试结果:

测试结果: 写了一个tcp的服务端程序  用网络助手进行连接,测试可以打印: 注意大小端转换。
root@ubuntu:/home/ubuntu/test# bpftrace accept.bt 
Attaching 2 probes...
inet_csk_accepttcp_accept: 192.168.40.1    :1782 62982--> 192.168.40.137  :6666
inet_csk_accepttcp_accept: 192.168.40.1    :2038 62983--> 192.168.40.137  :6666
inet_csk_accepttcp_accept: 192.168.40.1    :6902 63002--> 192.168.40.137  :6666
4.4.3 探测mysql执行的语句 以及对应的耗时。

mysql.bt

uprobe:/usr/sbin/mysqld:*dispatch_command*
{@start = nsecs;@sql = str(*arg1);
}uretprobe:/usr/sbin/mysqld:*dispatch_command*
/@start/
{$dur = nsecs - @start;printf("%u %s \n", $dur, @sql);
}

mysql执行结果: 可以看到对应的mysql执行语句 以及对应的耗时

root@ubuntu:/home/ubuntu/test# bpftrace mysql.bt 
WARNING: Addrspace is not set
Attaching 2 probes...
1175223 show databases 
12474975 CREATE DATABASE `mytest2` 
12438296 CREATE DATABASE mytest3 
541816 CREATE DATABASE 'mytest3'    #这种正常的单引号 创建会失败#mysql创建后,第一次登录mysql可以直接登录,要给root手动设置密码。    set password for root@localhost = password('123456');  #这次用的这个密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;

参考,手头已有文档以及网络:

eBPF 入门开发实践教程一:Hello World,基本框架和开发流程 - eunomia

如何在 Ubuntu 上配置 eBPF 开发环境 | YaoYao’s Blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/54138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王者荣耀改重复名(java源码)

王者荣耀改重复名 项目简介 “王者荣耀改重复名”是一个基于 Spring Boot 的应用程序&#xff0c;用于生成王者荣耀游戏中的唯一名称。通过简单的接口和前端页面&#xff0c;用户可以输入旧名称并获得一个新的、不重复的名称。 功能特点 生成新名称&#xff1a;提供一个接口…

C++基础知识7 list

list 1. list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.5 list modifiers1.2.6 list的迭代器失效 2.1 模拟实现list 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 l…

aspcms 获取webshell漏洞复现

1.通过访问/admin_aspcms/login.asp来到后台 使用admin 123456 登录 2.点击扩展功能-幻灯片设置-保存&#xff0c;同时进行抓包 3.修改数据包中的slideTextStatus字段&#xff0c;将其更改为 1%25><%25Eval(Request (chr(65)))%25><%25 密码为a 4.访问木马的地…

面试官:讲一讲Spring MVC源码解析

好看的皮囊千篇一律、有趣的灵魂万里挑一 文章持续更新&#xff0c;可以微信搜索【小奇JAVA面试】第一时间阅读&#xff0c;回复【资料】获取福利&#xff0c;回复【项目】获取项目源码&#xff0c;回复【简历模板】获取简历模板&#xff0c;回复【学习路线图】获取学习路线图。…

Android 使用scheme唤起app本地打开

记录一下近期任务。。。 以下操作全部基于手机本地已经安装对应app方可执行。 没安装建议web前端校验一下跳动app下载页吧。 AndroidManifest配置如下&#xff1a; <activity android:name".RouterActivity"><intent-filter><dataandroid:host&quo…

wopop靶场漏洞挖掘练习

1、SQL注入漏洞 1、在搜索框输入-1 union select 1,2,3# 2、输入-1 union select 1,2,database()# &#xff0c;可以得出数据库名 3、输入-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schematest#&#xff0c;可以得出数据库中…

八股文知识汇总(常考)

八股文知识汇总&#xff08;常考&#xff09; 语言特性相关 JAVA知识 - JDK动态代理为什么只能代理有接口的类&#xff1f; 说一下对象创建的过程&#xff1f;ThreadLocal是什么&#xff1f;他的实现原理是什么&#xff1f;ThreadLocal会出现内存泄露吗&#xff1f;String、…

注册建造师执业工程规模标准(房屋建筑工程)

注册建造师执业工程规模标准&#xff08;房屋建筑工程&#xff09;序号工程类别项目名称单位规 模备 注大型中型小型1 一般房屋建筑工程工业、民用与公共建筑工程层≥255&#xff5e;25<5建筑物层数米≥10015&#xff5e;100<15建筑物高度米≥3015&#xff5e;30&l…

C++ | Leetcode C++题解之第405题数字转换为十六进制数

题目&#xff1a; 题解&#xff1a; class Solution { public:string toHex(int num) {if (num 0) {return "0";}string sb;for (int i 7; i > 0; i --) {int val (num >> (4 * i)) & 0xf;if (sb.length() > 0 || val > 0) {char digit val …

Codeforces Round 299 (Div. 2) B. Tavas and SaDDas(组合数学)

题目链接&#xff1a;题目 大意&#xff1a; 给出一个“幸运数”&#xff0c;每一位都是4或7&#xff0c;问这是从1开始第几个幸运数。 思路&#xff1a; 直接暴力数复杂度太高&#xff0c;实际上就是看有多少种4和7组合。当然数组合也不能乱数&#xff0c;为了思路清晰我是…

Iptables命令常用命令

前言:下是一些非常实用的 iptables 命令合集&#xff0c;涵盖网络攻击防护和日常网络安全防护 1. 查看当前规则 iptables -L -v -n查看现有的所有规则&#xff0c;-v 显示详细信息&#xff0c;-n 禁止解析IP地址和端口以加快显示速度。 2. 清空所有规则 iptables -F清除所有已…

JDBC实现对单表数据增、删、改、查

文章目录 API介绍获取 Statement 对象Statement的API介绍使用步骤案例代码 JDBC实现对单表数据查询ResultSet的原理ResultSet获取数据的API使用JDBC查询数据库中的数据的步骤案例代码 API介绍 获取 Statement 对象 在java.sql.Connection接口中有如下方法获取到Statement对象…

运维工程师面试整理-操作系统

在运维工程师的面试中,操作系统相关的知识通常是重中之重,尤其是Linux/Unix系统。以下是针对操作系统部分的一些详细内容,帮助你更好地准备面试。 1. Linux/Unix 基础 ● 常用命令 ○ 文件和目录管理:ls, cd, cp, mv, rm, mkdir, rmdir, find, grep, awk, sed

汽车电子笔记之-013:旋变硬解码ADI芯片AD2S1210使用记录(从零开始到软件实现)

目录 1、概述 2、技术规格 3、芯片引脚 4、旋变信号格式 5、使用过程只是要点分析 5.1、程序注意点分析 5.1.1、SPI配置时序 5.1.2、问题一&#xff1a;SPI时序问题 5.1.3、问题二&#xff1a;SPI读取时序&#xff08;配置模式&#xff09; 5.1.4、问题三&#xff1a…

削峰+限流:秒杀场景下的高并发写请求解决方案

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! 哈喽,大家好!我是小米,一个29岁、活泼积极、热衷分享技术的码农。今天和大家聊一聊应对高并发的写请求这个主题,尤其是在大促、秒杀这种场景下,系统…

vulnhub(8):pWnOS(还没信息收集就已经成功打点)

端口 nmap主机发现 nmap -sn 192.168.89.0/24 ​ Nmap scan report for 192.168.89.116 Host is up (0.00020s latency). ​ 116是新出现的机器&#xff0c;他就是靶机 nmap端口扫描 nmap -Pn 192.168.89.116 -p- --min-rate 10000 -oA nmap/scan 扫描开放端口保存到 nmap/sca…

手势开关灯

太久没水&#xff0c;那可不行。今日又来写一段专业程序员看了也皱眉的垃圾全屋智能雏形代码。应该是笑掉大牙级别吧。下面进入正题。首先思路就是通过cvzone那个手势识别&#xff0c;判断开关灯指令。接下来是通过mqtt局域网里发布一下&#xff08;注意打开防火墙&#xff09;…

非线性规划及其MATLAB实现

目录 引言 非线性规划的基本模型 非线性规划的求解方法 非线性规划的MATLAB实现 例子&#xff1a;多目标优化问题的非线性规划求解 表格总结&#xff1a;MATLAB常用非线性规划函数 实例&#xff1a;使用MATLAB求解非线性投资决策问题 结论 引言 非线性规划&#xff08;…

【STM32系统】基于STM32设计的智能垃圾桶(语音、颜色识别、称重、光强、烟雾、人体识别、步进电机、水泵)——文末资料下载

基于STM32设计的智能垃圾桶 演示视频: 基于STM32设计的智能垃圾桶 功能简介: 四个按键可分别打开四个垃圾桶(可回收垃圾、厨余垃圾、有害垃圾、其他垃圾) oled显示屏显示四个垃圾桶的打开/关闭状态、烟雾浓度、光照强度、称重的重量和识别到的颜色(白色、红色、绿色、蓝…

ES6解构赋值详解;全面掌握:JavaScript解构赋值的终极指南

目录 全面掌握&#xff1a;JavaScript解构赋值的终极指南 一、数组解构赋值 1、基本用法 2、跳过元素 3、剩余元素 4、默认值 二、对象解构赋值 1、基本用法 2、变量重命名 3、默认值 4、嵌套解构 三、复杂的嵌套结构解构 四、函数参数解构赋值 1、对象解构作为函…