Skip to content

Commit

Permalink
Merge pull request linuxkerneltravel#669 from gaoyixiang1/develop
Browse files Browse the repository at this point in the history
Stack_Analyzre项目:add stack_count and improve doc
  • Loading branch information
chenamy2017 committed Feb 22, 2024
2 parents a1962f7 + 33188fd commit b9c2551
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 10 deletions.
2 changes: 1 addition & 1 deletion eBPF_Supermarket/Stack_Analyser/libbpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ INCLUDES := -I$(OUTPUT) -I./libbpf-bootstrap/libbpf/include/uapi -I$(dir $(VMLIN
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)

APPS = on_cpu_count off_cpu_count mem_count io_count pre_count
APPS = on_cpu_count off_cpu_count mem_count io_count pre_count stack_count
SYMBOL = elf symbol
TARGETS = stack_analyzer

Expand Down
72 changes: 72 additions & 0 deletions eBPF_Supermarket/Stack_Analyser/libbpf/bpf/stack_count.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>


#include "sa_ebpf.h"
#include "task.h"

DeclareCommonMaps(stack_tuple);
DeclareCommonVar();

//传进来的参数
int apid = 0;
// int acpu = 0;

const char LICENSE[] SEC("license") = "GPL";

static int handle(struct trace_event_raw_sys_enter *ctx)
{
struct task_struct* curr = (struct task_struct*)bpf_get_current_task(); //利用bpf_get_current_task()获得当前的进程tsk
ignoreKthread(curr);
// u32 cpu_id = bpf_get_smp_processor_id();
// if(cpu_id != acpu){
// return 0;
// }
stack_tuple key = {};
u32 pid = get_task_ns_pid(curr); //利用帮助函数获得当前进程的pid
if ((apid >= 0 && pid != apid) || !pid || pid == self_pid)
return 0;

u32 tgid = get_task_ns_tgid(curr); //利用帮助函数获取进程的tgid
bpf_map_update_elem(&pid_tgid, &pid, &tgid, BPF_ANY); //将pid_tgid表中的pid选项更新为tgid,若没有该表项,则创建
comm *p = bpf_map_lookup_elem(&pid_comm, &pid); //p指向pid_comm哈希表中的pid表项对应的value
if (!p) //如果p不为空,获取当前进程名保存至name中,如果pid_comm当中不存在pid name项,则更新
{
comm name;
bpf_get_current_comm(&name, COMM_LEN);
bpf_map_update_elem(&pid_comm, &pid, &name, BPF_NOEXIST);
p = &name;
}
key.name = *p;
u32 *t = bpf_map_lookup_elem(&pid_tgid, &pid);
if(!t){
key.tgid = 0xffffffff;
}else{
key.tgid = *t;
}

psid apsid = {
.pid = pid,
.usid = u ? USER_STACK : -1,
.ksid = k ? KERNEL_STACK : -1,
};
stack_tuple *d = bpf_map_lookup_elem(&psid_count, &apsid); //d指向psid_count表当中的apsid表项的值

if(!d) {
stack_tuple nd = {.count = 1, .name = key.name,.tgid = key.tgid};
bpf_map_update_elem(&psid_count, &apsid, &nd, BPF_NOEXIST);
} else {
d->count++;
}
return 0;

}

#define io_sec_tp(name) \
SEC("tp/syscalls/sys_enter_" #name) \
int prog_t_##name(struct trace_event_raw_sys_enter *ctx) { return handle(ctx); }

io_sec_tp(write);
io_sec_tp(read);
6 changes: 6 additions & 0 deletions eBPF_Supermarket/Stack_Analyser/libbpf/include/sa_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,10 @@ typedef struct {
__u64 size;
} io_tuple;

typedef struct {
__u32 tgid;
comm name;
__u64 count;
} stack_tuple;

#endif
9 changes: 8 additions & 1 deletion eBPF_Supermarket/Stack_Analyser/libbpf/include/sa_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef enum {
MOD_MEM, // 内存模式
MOD_IO, // io模式
MOD_RA, // 预读取分析模式
MOD_STACK, //调用栈次数统计模式
MOD_NUM // 该枚举类值的总数
} StackCollectMode;

Expand All @@ -49,7 +50,8 @@ char StackCollectModeName[MOD_NUM][16] = {
"off_cpu",
"memory",
"io",
"readahead"
"readahead",
"stackcount",
};

typedef enum {
Expand All @@ -63,6 +65,11 @@ typedef enum {
AVE
} io_mod;

typedef enum {
COUNTS,
CPU
} stack_mod;

/// @brief 获取epbf程序中指定表的文件描述符
/// @param name 表的名字
#define OPEN_MAP(name) bpf_map__fd(skel->maps.name)
Expand Down
48 changes: 44 additions & 4 deletions eBPF_Supermarket/Stack_Analyser/libbpf/stack_analyzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C"
#include "bpf/mem_count.skel.h"
#include "bpf/io_count.skel.h"
#include "bpf/pre_count.skel.h"
#include "bpf/stack_count.skel.h"
}

std::string demangleCppSym(std::string symbol)
Expand Down Expand Up @@ -96,6 +97,7 @@ class StackCollector
double val;
CountItem(int32_t p, int32_t k, int32_t u, double v)
{

pid = p;
ksid = k;
usid = u;
Expand Down Expand Up @@ -173,7 +175,7 @@ class StackCollector

public:
std::string name; // 标识类名

int pid = -1; // 用于设置ebpf程序跟踪的pid
int cpu = -1; // 用于设置ebpf程序跟踪的cpu
int err = 0; // 用于保存错误代码
Expand All @@ -184,7 +186,6 @@ class StackCollector
uint64_t max = __UINT64_MAX__; // 设置采集指标最大值,最小值

bool clear = false; // 清除已输出的指标积累量

int self_pid;

StackCollector()
Expand Down Expand Up @@ -384,6 +385,7 @@ class StackCollector
}
};


class OnCPUStackCollector : public StackCollector
{
private:
Expand Down Expand Up @@ -417,7 +419,7 @@ class OnCPUStackCollector : public StackCollector
fscanf(fp, "%p", &load_a);
pclose(fp);
StackProgLoadOpen(
skel->bss->load_a = load_a) return 0;
skel->bss->load_a = load_a ) return 0;
};

int attach(void) override
Expand Down Expand Up @@ -638,6 +640,40 @@ class ReadaheadStackCollector : public StackCollector
};
};

class StackCountStackCollector : public StackCollector
{
private:
declareEBPF(stack_count_bpf);


protected:
std::string data_str(void) override
{
return "Calling Counts";
};
double data_value(void *data) override
{
stack_tuple *p = (stack_tuple *)data;
return p->count;
};

public:
stack_mod DataType = stack_mod::COUNTS;

StackCountStackCollector()
{
count_size = sizeof(stack_tuple);
name = "stackcount";
};

defaultLoad;
defaultAttach;
defaultDetach;
defaultUnload;

};


namespace MainConfig
{
int run_time = __INT_MAX__; // 运行时间
Expand Down Expand Up @@ -726,6 +762,9 @@ int main(int argc, char *argv[])
{ StackCollectorList.push_back(new ReadaheadStackCollector()); }) %
"sample the readahead hit rate of call stacks" &
SubOption;
auto StackCountOption = clipp::option("stackcount").call([]
{ StackCollectorList.push_back(new StackCountStackCollector()); }) %
"sample the counts of calling stacks" & SubOption;

auto cli = (MainOption,
clipp::option("-v", "--version").call([]
Expand All @@ -735,7 +774,8 @@ int main(int argc, char *argv[])
OffCpuOption,
MemoryOption,
IOOption,
ReadaheadOption) %
ReadaheadOption,
StackCountOption) %
"statistic call trace relate with some metrics";

if (!clipp::parse(argc, argv, cli))
Expand Down
6 changes: 2 additions & 4 deletions eBPF_Supermarket/Stack_Analyser/libbpf/框架使用方法.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# 用户侧

1.`include/stack_analyzer.h` 中的 `MOD` 枚举类型定义中新增一个功能模块的标识
1.`include/stack_analyzer.h` 中的 `MOD` 枚举类型定义中新增一个功能模块的标识,将该名称添加到`MOD_NUM`前面即可

2.`stack_analyzer.cc` 中创建一个 `bpf_loader` 的子类,在其中重写以下函数:

Expand All @@ -24,9 +24,7 @@

6. 自定义eBPF程序清除函数 `void remove(void)`,将eBPF程序清除

3. 在 main 函数中添加新增子命令和对应参数解析语句,将子命令解析为新增子功能对应的标识符并设置给 `env::mod`

4.`bpf_loader arr[]` 中添加 包装子类构造函数的匿名函数,添加顺序需和其在 MOD 枚举类型中对应的 标识 的顺序一致
3. 在 main 函数中添加新增子命令和对应参数解析语句

# 编译侧

Expand Down

0 comments on commit b9c2551

Please sign in to comment.