当前位置: 首页 > news >正文

做动态网站的用工具栏电商培训班

做动态网站的用工具栏,电商培训班,北京、广州最新发布,网上做网站怎么赚钱吗简介 uprobe是一种用户空间探针,允许在用户空间程序中动态插桩,插桩位置包括: 函数入口 特定偏移处 函数出口 当我们定义uprobe时,内核会在附加的指令上创建快速断点指令(X86机器位int3指令)&#xff…

简介

uprobe是一种用户空间探针,允许在用户空间程序中动态插桩,插桩位置包括:

  • 函数入口

  • 特定偏移处

  • 函数出口

当我们定义uprobe时,内核会在附加的指令上创建快速断点指令(X86机器位int3指令),当程序执行到该指令时,内核将触发时间,程序陷入内核态,并以回调函数的方式调用探针函数,执行完探针函数再返回到用户态继续执行后续代码。

uprobe基于文件,当一个二进制文件中的一个函数被跟踪时,所有使用到这个文件的进程都会被插桩,包括那些尚未启动的进程,这样就可以在全系统范围内跟踪系统调用。

libbpf uprobe相关函数

bpf_program__attach_uprobe

该函数可以将BPF程序附加到通过二进制路径和偏移量找到的用户空间函数中。可以选择指定要附加的特定进程,还可以选择将程序附加到函数出口或入口。

原型:

struct bpf_link *bpf_program__attach_uprobe(const struct bpf_program *prog,bool retprobe,pid_t pid,const char *binary_path,size_t func_offset);

参数:

  • prog:要附加的BPF程序

  • retprobe:附加到函数出口

  • pid:附加uprobe的进程ID(0表示自身进程,-1表示所有进程)

  • binary_path:包含函数符号的二进制文件的路径

  • func_offset:函数符号二进制内的偏移量

返回值:

  • 新创建的BPF链接引用

  • 出错时返回NULL,错误代码存储在errno中

bpf_program__attach_uprobe_opts

该函数与上一个函数类似,只是具有用于各种配置的选项结构。

原型:

struct bpf_link *bpf_program__attach_uprobe_opts(const struct bpf_program *prog,pid_t pid,const char *binary_path,size_t func_offset,const struct bpf_uprobe_opts *opts);

参数:

  • prog:要附加的BPF程序

  • pid:附加uprobe的进程ID(0表示自身进程,-1表示所有进程)

  • binary_path:包含函数符号的二进制文件的路径

  • func_offset:函数符号二进制内的偏移量

  • opts:更改程序附件的选项

返回值:

  • 新创建的BPF链接引用

  • 出错时返回NULL,错误代码存储在errno中

bpf_program__attach_usdt

该函数与上一个函数类似,只不过它覆盖了USDT(用户空间静态定义跟踪点)附件,而不是附加到用户控件函数入口和出口。

原型:

struct bpf_link *bpf_program__attach_usdt(const struct bpf_program *prog,pid_t pid,const char *binary_path,const char *usdt_provider,const char *usdt_name,const struct bpf_uprobe_opts *opts);

参数:

  • prog:要附加的BPF程序

  • pid:附加uprobe的进程ID(0表示自身进程,-1表示所有进程)

  • binary_path:包含函数符号的二进制文件的路径

  • usdt_provider:USDT提供商名称

  • usdt_name:USDT探针名称

  • opts:更改程序附件的选项

返回值:

  • 新创建的BPF链接引用

  • 出错时返回NULL,错误代码存储在errno中

实践

准备被打桩的用户程序

用户程序源码

编写一个简单的程序,循环调用test_addtest_sub函数。

/* src/other/main.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int test_add(int a, int b)
{return a + b;
}int test_sub(int a, int b)
{return a - b;
}int main(int argc, char *argv[])
{int a = 0, b = 1;for (;;a += 1, b += 1) {printf("test_add(%d, %d) = %d\n", a, b, test_add(a, b));sleep(1);printf("test_sub(%d, %d) = %d\n", a, b, test_sub(a, b));sleep(1);}return 0;
}

编译

在编译用户程序时,必须加上-g -dynamic参数,确保二进制文件中包含了所有调试信息和符号信息,BPF程序需要通过这些信息进行打桩,否则不能正常打桩。

查看符号函数

objdump -T build/other | grep test_add00000000004011a0 g    DF .text	0000000000000004  Base        test_addobjdump -T build/other | grep test_sub00000000004011b0 g    DF .text	0000000000000005  Base        test_sub

命令最后输出的符号test_addtest_sub便是我们需要打桩的符号名称。

重要:某些情况下函数名称和符号表中的名称可能不一致,在后续BPF打桩时,需要使用符号表中函数名称。

uprobe ebpf程序

内核程序

在内核中我们使用SEC宏定义要打桩的函数,使用BPF_KPROBE宏定义函数探针函数。

SEC有两种模式:

  • 指定要捕获的二进制文件路径和要捕获的函数符号名,在用户程序中只需要使用xxx_bpf__attach(skel)即可

  • 不指定要捕获的二进制文件路径和要捕获的函数符号名,用户程序中则需要使用bpf_program__attach_uprobe进行指定参数附加

BPF_KPROBE定义探针函数,需要注意每个函数名需要不同。

/* src/kernle/main.bpf.c */
#include "kernel/bpf_kernel.h"char LICENSE[] SEC("license") = "GPL";/*** 在 SEC 宏中指定了要捕获的二进制文件路径和要捕获的函数符号名,* 则在用户程序中只需要使用xxx_bpf__attach(skel)即可*/
SEC("uprobe//root/project/bpf_user_core/build/other:test_add")
int BPF_KPROBE(test_add, int a, int b)
{/* 捕获 test_add 入口 */bpf_printk("test_add entry: a = %d b = %d\n", a, b);return 0;
}SEC("uretprobe//root/project/bpf_user_core/build/other:test_add")
int BPF_KRETPROBE(ret_test_add, int ret)    /* 这里的函数名不能更入口点的函数名相同 */
{/* 捕获 test_add 出口 */bpf_printk("test_add exit: return = %d\n", ret);return 0;
}/*** 没有在 SEC 宏中指定二进制路径和函数名称时,* 在用户程序中则需要使用bpf_program__attach_uprobe进行指定参数附加*/
SEC("uprobe")
int BPF_KPROBE(test_sub, int a, int b)
{/* 捕获 test_sub 入口 */bpf_printk("test_sub entry: a = %d b = %d\n", a, b);return 0;
}SEC("uretprobe")
int BPF_KRETPROBE(ret_test_sub, int ret)
{/* 捕获 test_sub 出口 */bpf_printk("test_sub exit: return = %d\n", ret);return 0;
}

用户程序

在用户程序中,使用bpf_program__attach_uprobe_optsbpf_program__attach_uprobe加载探针程序

/* src/user/load_bpf.c */#include <stdio.h>#include "user/load_bpf.h"
#include "user/parse_arg.h"static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{/* 完成调式信息控制 */if (!user_args.debug_log) {return 0;}return vfprintf(stderr, format, args);
}struct kernel_bpf *load_bpf_to_kernel(void)
{struct kernel_bpf *skel;int err;LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);libbpf_set_print(libbpf_print_fn);skel = kernel_bpf__open();if (!skel) {fprintf(stderr, "Failed to open and load BPF skeleton\n");return NULL;}err = kernel_bpf__load(skel);if (err) {fprintf(stderr, "Failed to load and verify BPF skeleton\n");kernel_bpf__destroy(skel);return NULL;}/* 进行 uprobe 插桩 *//* 插桩入口点 */uprobe_opts.func_name = "test_sub";uprobe_opts.retprobe = false;skel->links.test_sub = bpf_program__attach_uprobe_opts(skel->progs.test_sub,-1, /* 所有进程 */"/root/project/bpf_user_core/build/other",0,&uprobe_opts);if (!skel->links.test_sub) {err = -errno;fprintf(stderr, "Failed to attach uprobe: %d\n", err);kernel_bpf__destroy(skel);return NULL;}/* 插桩出口点 */uprobe_opts.func_name = "test_sub";uprobe_opts.retprobe = true;skel->links.ret_test_sub = bpf_program__attach_uprobe_opts(skel->progs.ret_test_sub,-1, /* 所有进程 */"/root/project/bpf_user_core/build/other",0,&uprobe_opts);if (!skel->links.ret_test_sub) {err = -errno;fprintf(stderr, "Failed to attach uprobe: %d\n", err);kernel_bpf__destroy(skel);return NULL;}err = kernel_bpf__attach(skel);if (err) {fprintf(stderr, "Failed to attach BPF skeleton\n");kernel_bpf__destroy(skel);return NULL;}return skel;
}

获取代码

git clone https://github.com/zhutouwangzha/eBPF.git

编译

cd 002-ebpf-uprobe && make

运行

# 运行自定义用户程序,循环调用test_add,test_sub
./build/other# 加载BPF程序
./build/user# 查看BPF程序输出
sudo cat /sys/kernel/debug/tracing/trace_pipe

成功执行后,能看到如下输出:

           other-4815    [004] ....1  6587.022754: bpf_trace_printk: test_add entry: a = 2 b = 3other-4815    [004] ....1  6587.022828: bpf_trace_printk: test_add exit: return = 5other-4815    [004] ....1  6588.023139: bpf_trace_printk: test_sub entry: a = 2 b = 3other-4815    [004] ....1  6588.023197: bpf_trace_printk: test_sub exit: return = -1other-4815    [004] ....1  6589.023385: bpf_trace_printk: test_add entry: a = 3 b = 4other-4815    [004] ....1  6589.023437: bpf_trace_printk: test_add exit: return = 7other-4815    [004] ....1  6590.023772: bpf_trace_printk: test_sub entry: a = 3 b = 4other-4815    [004] ....1  6590.023834: bpf_trace_printk: test_sub exit: return = -1

http://www.hkea.cn/news/256999/

相关文章:

  • 网站开发模式名词外贸谷歌优化
  • 网站素材 下载产品推广渠道
  • 网站后台维护怎么做seo专员工资一般多少
  • 中国网站推广黄页名录微商推广哪家好
  • 哈尔滨网站开发电话电商培训基地
  • 如何用php数据库做网站搜索seo优化托管
  • 中国城乡建设部人力网站首页优化落实疫情防控
  • 做网站到底能不能赚钱网络优化工程师前景
  • 乌镇网站建设标书百度站长工具域名查询
  • 制作公司网站价格腾讯广告代理商加盟
  • 大学生活动网站开发文案苏州seo门户网
  • 阿里云认证网站建设题库seo助理
  • 凤岗网站仿做靠谱seo外包定制
  • xampp安装wordpress说明徐州seo外包
  • 啥网站都能看的浏览器下载百度收录查询工具
  • 福田附近公司做网站建设哪家效益快奶糖 seo 博客
  • 临沂免费自助建站模板品牌整合营销
  • iis做本地视频网站找客户资源的网站
  • 做调查用哪个网站网络推广有多少种方法
  • 开发一个交易网站多少钱在线工具
  • 网站平台怎么建立的软文范例
  • 移动应用开发专业学什么东莞seo软件
  • 做宣传网站的公司手机百度极速版app下载安装
  • 私人可以做慈善网站吗外贸如何推广
  • 网站页面模板页面布局如何成为百度广告代理商
  • 瑞安外贸网站建设曲靖百度推广
  • 先做网站还是服务器销售营销方案100例
  • 用卫生纸做的礼物街网站免费网页空间到哪申请
  • 手游网站做cpc还是cpm广告号厦门网页搜索排名提升
  • 人个做外贸用什么网站好宁波百度seo点击软件