From 067b71f991f70e6168cbe57fa7dbace9bc12589f Mon Sep 17 00:00:00 2001 From: albertxu216 <145351853+albertxu216@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:00:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?CPU=5FWatcher:=20=E6=9B=B4=E6=94=B9cpu=5Fwa?= =?UTF-8?q?tcher=E6=9E=B6=E6=9E=84=20&&=20=E6=9B=B4=E6=94=B9Makefile=20&&?= =?UTF-8?q?=20=E5=AE=8C=E5=96=84README=20=20(#776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 调整cpu_watcher架构 && 更改Makefile文件 * Update README.md 完善README --------- Co-authored-by: xhb --- .../CPU_Subsystem/cpu_watcher/Makefile | 12 +++++++--- .../CPU_Subsystem/cpu_watcher/README.md | 7 +++++- .../cpu_watcher/{ => bpf}/cs_delay.bpf.c | 16 +++++++++++++ .../cpu_watcher/{ => bpf}/mq_delay.bpf.c | 4 ++-- .../cpu_watcher/{ => bpf}/preempt.bpf.c | 19 ++++++++++++++- .../cpu_watcher/{ => bpf}/sar.bpf.c | 24 +++++++++++++++---- .../cpu_watcher/{ => bpf}/sc_delay.bpf.c | 16 +++++++++++++ .../{ => bpf}/schedule_delay.bpf.c | 16 +++++++++++++ .../CPU_Subsystem/cpu_watcher/cpu_watcher.c | 2 +- .../cpu_watcher/{ => include}/cpu_watcher.h | 5 ++-- 10 files changed, 106 insertions(+), 15 deletions(-) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => bpf}/cs_delay.bpf.c (58%) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => bpf}/mq_delay.bpf.c (98%) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => bpf}/preempt.bpf.c (68%) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => bpf}/sar.bpf.c (88%) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => bpf}/sc_delay.bpf.c (73%) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => bpf}/schedule_delay.bpf.c (88%) rename eBPF_Supermarket/CPU_Subsystem/cpu_watcher/{ => include}/cpu_watcher.h (98%) diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile index efe1a9de9..8b957563a 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile @@ -38,13 +38,15 @@ VMLINUX := ../vmlinux/$(ARCH)/vmlinux.h # Use our own libbpf API headers and Linux UAPI headers distributed with # libbpf to avoid dependency on system-wide headers, which could be missing or # outdated -INCLUDES := -I$(OUTPUT) -I../../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC) -I./ +INCLUDES := -I$(OUTPUT) -I../../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC) -I./include CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) APPS =cs_delay sar sc_delay preempt schedule_delay mq_delay TARGETS=cpu_watcher +SRC_DIR = ./include + # Get Clang's default includes on this system. We'll explicitly add these dirs # to the includes list when compiling with `-target bpf` because otherwise some @@ -112,7 +114,7 @@ $(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) $(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@ # Build BPF code -$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) +$(OUTPUT)/%.bpf.o: bpf/%.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) $(call msg,BPF,$@) $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ @@ -126,6 +128,10 @@ $(APPS): %: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) $(Q)$(BPFTOOL) gen skeleton $< > $(OUTPUT)/$@.skel.h # Build user-space code +$(OUTPUT)/%.o: $(SRC_DIR)/%.c | $(OUTPUT) + $(call msg,CC,$@) + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) $(call msg,CC,$@) $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ @@ -133,7 +139,7 @@ $(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) # Build application binary $(TARGETS): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT) $(call msg,BINARY,$@) - $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ + $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@ # delete failed targets .DELETE_ON_ERROR: diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md index f64e4a8a8..b981830cd 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md @@ -68,6 +68,9 @@ make clean 清除生成文件 - `sysc/ms`: CPU执行用户程序系统调用(`syscall`)所占用的时间,是所有CPU的叠加。 - ` utime/ms`:CPU执行普通用户进程时,花在用户态的时间,是所有CPU的叠加。 +原理介绍: + +[libbpf_sar工具原理分析](docs/libbpf_sar.md) ### **2.统计抢占调度时间:** ​ 统计系统中发生抢占调度的情况,包括抢占进程的`pid`与进程名,以及被强占进程的`pid`,和本次抢占时间,单位纳秒。 @@ -214,9 +217,11 @@ per_len = 1000 ​ 获取内核全局变量,直接从内核全局变量读取信息。如proc/s就是通过直接读取total_forks内核全局变量来计算每秒产生进程数的。 +## 五、cpu_watcher可视化 +[cpu_watcher可视化指南](docs/cpu_watcher_vis_guide.md) -## 五、未来展望 +## 六、未来展望 目前`cpu_watcher`工具的总体框架已经完成,工具所能满足的功能已覆盖CPU所涉及的大部分性能指标。下一阶段,本工具将从以下几个方向进行开发和优化: diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/cs_delay.bpf.c similarity index 58% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/cs_delay.bpf.c index c94c5d1bf..3434d6a8a 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/cs_delay.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/mq_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/mq_delay.bpf.c similarity index 98% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/mq_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/mq_delay.bpf.c index 92589afd6..becb4c27c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/mq_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/mq_delay.bpf.c @@ -1,4 +1,4 @@ -// Copyright 2024 The LMP Authors. +// Copyright 2023 The LMP Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: albert_xuu@163.com +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com #include "vmlinux.h" #include //包含了BPF 辅助函数 diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/preempt.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/preempt.bpf.c similarity index 68% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/preempt.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/preempt.bpf.c index 0abbbc781..57043e3bb 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/preempt.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/preempt.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include @@ -33,7 +49,8 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s return 0; } -SEC("kprobe/finish_task_switch") +// SEC("kprobe/finish_task_switch") +SEC("kprobe/finish_task_switch.isra.0") int BPF_KPROBE(finish_task_switch, struct task_struct *prev) { u64 end_time = bpf_ktime_get_ns(); pid_t pid = BPF_CORE_READ(prev, pid); diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sar.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sar.bpf.c similarity index 88% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sar.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sar.bpf.c index 4e48d49c7..2fe6b43f5 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sar.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sar.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include @@ -36,8 +52,8 @@ BPF_ARRAY(ut_LastTime,u32,u64,1); BPF_ARRAY(tick_user,u32,u64,1); BPF_ARRAY(symAddr,u32,u64,1); // 统计fork数 -//SEC("kprobe/finish_task_switch.isra.0") -SEC("kprobe/finish_task_switch") +SEC("kprobe/finish_task_switch.isra.0") +// SEC("kprobe/finish_task_switch") int kprobe__finish_task_switch(struct pt_regs *ctx) { u32 key = 0; @@ -75,8 +91,8 @@ int trace_sched_switch2(struct cswch_args *info) { return 0; } -SEC("kprobe/finish_task_switch") -//SEC("kprobe/finish_task_switch.isra.0") +// SEC("kprobe/finish_task_switch") +SEC("kprobe/finish_task_switch.isra.0") int BPF_KPROBE(finish_task_switch,struct task_struct *prev){ pid_t pid=BPF_CORE_READ(prev,pid); u64 *val, time = bpf_ktime_get_ns(); diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sc_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sc_delay.bpf.c similarity index 73% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sc_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sc_delay.bpf.c index ec642bf17..23eaf2200 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sc_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sc_delay.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include "vmlinux.h" #include //包含了BPF 辅助函数 #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/schedule_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/schedule_delay.bpf.c similarity index 88% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/schedule_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/schedule_delay.bpf.c index fda48bda6..036d1178c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/schedule_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/schedule_delay.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c index 709b29c74..8d768fc9c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: zhangziheng0525@163.com +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.h b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/include/cpu_watcher.h similarity index 98% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.h rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/include/cpu_watcher.h index 6812096ce..aaf5dfb1d 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.h +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/include/cpu_watcher.h @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: zhangziheng0525@163.com -// -// eBPF map for libbpf sar +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include From 3a602dc19d6c80eeaa7895ed95e8e581a7c8cd9d Mon Sep 17 00:00:00 2001 From: gaoyixiang1 <45355878+gaoyixiang1@users.noreply.github.com> Date: Sun, 28 Apr 2024 09:23:29 +0800 Subject: [PATCH 2/2] add flunclatency and user-defined probe (#769) --- .../Stack_Analyser/bpf/funclatency.bpf.c | 132 +++++++++++ .../include/bpf_wapper/funclatency.h | 59 +++++ .../src/bpf_wapper/funclatency.cpp | 220 ++++++++++++++++++ eBPF_Supermarket/Stack_Analyser/src/main.cpp | 12 +- 4 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c create mode 100644 eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h create mode 100644 eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c new file mode 100644 index 000000000..e69f199bc --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c @@ -0,0 +1,132 @@ +// Copyright 2024 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: luiyanbing@foxmail.com +// +// 内核态bpf程序的模板代码 + +#include "vmlinux.h" +#include +#include +#include +#include + +#include "sa_ebpf.h" +#include "bpf_wapper/funclatency.h" +#include "task.h" + +COMMON_MAPS(time_tuple); +COMMON_VALS; +BPF_HASH(starts,psid,u64); +const volatile int target_pid = 0; + +static int entry(void *ctx) +{ + CHECK_ACTIVE; + struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk + RET_IF_KERN(curr); + + u32 pid = get_task_ns_pid(curr); // 利用帮助函数获得当前进程的pid + if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + return 0; + + SAVE_TASK_INFO(pid, curr); + + psid a_psid =GET_COUNT_KEY(pid,ctx); + u64 nsec; + + nsec = bpf_ktime_get_ns(); + bpf_map_update_elem(&starts, &a_psid, &nsec, BPF_ANY); +} + + + +SEC("kprobe/dummy_kprobe") +int BPF_KPROBE(dummy_kprobe) +{ + entry(ctx); + return 0; +} +SEC("tp/sched/dummy_tp") +int tp_entry(void *ctx) +{ + entry(ctx); + return 0; +} +SEC("usdt") +int usdt_entry(void *ctx) +{ + entry(ctx); + return 0; +} +static int exit(void *ctx) +{ + u64 *start; + u64 nsec = bpf_ktime_get_ns(); + u64 delta; + + + + CHECK_ACTIVE; + struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk + RET_IF_KERN(curr); + + u32 pid = get_task_ns_pid(curr); // 利用帮助函数获得当前进程的pid + if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + return 0; + + SAVE_TASK_INFO(pid, curr); + + psid b_psid = GET_COUNT_KEY(pid, ctx); + + start = bpf_map_lookup_elem(&starts, &b_psid); + if (!start) + return 0; + + delta = nsec - *start; + + time_tuple *d = bpf_map_lookup_elem(&psid_count_map, &b_psid); + if (!d) + { + time_tuple tmp = {.lat = delta,.count=1}; + bpf_map_update_elem(&psid_count_map, &b_psid, &tmp, BPF_NOEXIST); + } + else + { + d->lat+=delta; + d->count++; + } +} + + + +SEC("kretprobe/dummy_kretprobe") +int BPF_KRETPROBE(dummy_kretprobe) +{ + exit(ctx); + return 0; +} +SEC("tp/sched/dummy_tp") +int tp_exit(void *ctx) +{ + exit(ctx); + return 0; +} +SEC("usdt") +int usdt_exit(void *ctx) +{ + exit(ctx); + return 0; +} +const char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h new file mode 100644 index 000000000..1f826942c --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h @@ -0,0 +1,59 @@ +// Copyright 2024 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: luiyanbing@foxmail.com +// +// ebpf程序的包装类的模板,声明接口和一些自定义方法,以及辅助结构 + +#ifndef _SA_FUNCLANTENCY_H__ +#define _SA_FUNCLANTENCY_H__ + +// ========== C code part ========== +#include +typedef struct +{ + __u64 lat; + __u64 count; +} time_tuple; +// ========== C code end ========== + +#ifdef __cplusplus +// ========== C++ code part ========== +#include "funclatency.skel.h" +#include "bpf_wapper/eBPFStackCollector.h" + +class FunclatencyStackCollector : public StackCollector +{ +private: + DECL_SKEL(funclatency); +public: + std::string probe; + +protected: + virtual uint64_t *count_values(void *); + +public: + void setScale(std::string probe); + FunclatencyStackCollector(); + virtual int load(void); + virtual int attach(void); + virtual void detach(void); + virtual void unload(void); + virtual void activate(bool tf); + virtual const char *getName(void); +}; +// ========== C++ code end ========== +#endif + +#endif \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp new file mode 100644 index 000000000..ffa9f8273 --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp @@ -0,0 +1,220 @@ +// Copyright 2024 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: luiyanbing@foxmail.com +// +// ebpf程序包装类的模板,实现接口和一些自定义方法 + +#include "bpf_wapper/funclatency.h" +#include "trace_helpers.h" +#include "uprobe_helpers.h" + +// ========== implement virtual func ========== + +uint64_t *FunclatencyStackCollector::count_values(void *data) +{ + time_tuple *p = (time_tuple *)data; + return new uint64_t[scale_num]{ + p->lat, + p->count}; +}; + +void FunclatencyStackCollector::setScale(std::string probe) +{ + this->probe = probe; + scales->Type = probe + "Delay"; +}; +int FunclatencyStackCollector::load(void) +{ + EBPF_LOAD_OPEN_INIT(skel->rodata->target_pid = pid;); + return 0; +}; +void splitStr(std::string symbol, const char split, std::vector &res) +{ + if (symbol == "") + return; + std::string strs = symbol + split; + size_t pos = strs.find(split); + while (pos != strs.npos) + { + std::string temp = strs.substr(0, pos); + res.push_back(temp); + strs = strs.substr(pos + 1, strs.size()); + pos = strs.find(split); + } +} + +static int get_binpath(char *path, int pid) +{ + char mode[16], line[128], buf[64]; + size_t seg_start, seg_end, seg_off; + FILE *f; + int i = 0; + + sprintf(buf, "/proc/%d/maps", pid); + f = fopen(buf, "r"); + if (!f) + return -1; + + while (fscanf(f, "%zx-%zx %s %zx %*s %*d%[^\n]\n", + &seg_start, &seg_end, mode, &seg_off, line) == 5) + { + i = 0; + while (isblank(line[i])) + i++; + if (strstr(line + i, "libc.so.6")) + { + break; + } + } + + strcpy(path, line + i); + fclose(f); + return 0; +} +static int attach_kprobes(struct funclatency_bpf *skel, std::string func) +{ + skel->links.dummy_kprobe = + bpf_program__attach_kprobe(skel->progs.dummy_kprobe, false, func.c_str()); + CHECK_ERR(!skel->links.dummy_kprobe, "Fail to attach kprobe"); + skel->links.dummy_kretprobe = + bpf_program__attach_kprobe(skel->progs.dummy_kretprobe, true, func.c_str()); + CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach ketprobe"); + return 0; +} +static int attach_uprobes(struct funclatency_bpf *skel, std::string probe, int pid) +{ + char *binary, *function; + char bin_path[128]; + std::string func = probe; + off_t func_off; + + binary = strdup(func.c_str()); + function = strchr(binary, ':'); // 查找:首次出现的位置 + *function = '\0'; + function++; + + if (resolve_binary_path(binary, pid, bin_path, sizeof(bin_path))) + free(binary); + + func_off = get_elf_func_offset(bin_path, function); + if (func_off < 0) + free(binary); + skel->links.dummy_kprobe = + bpf_program__attach_uprobe(skel->progs.dummy_kprobe, false, pid, + bin_path, func_off); + CHECK_ERR(!skel->links.dummy_kprobe, "Fail to attach uprobe"); + skel->links.dummy_kretprobe = + bpf_program__attach_uprobe(skel->progs.dummy_kretprobe, true, pid, + bin_path, func_off); + CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach uprobe"); + return 0; +} + +static int attach_tp(struct funclatency_bpf *skel, std::string tp_class, std::string func) +{ + + skel->links.tp_entry = + bpf_program__attach_tracepoint(skel->progs.tp_entry, tp_class.c_str(), func.c_str()); + CHECK_ERR(!skel->links.tp_entry, "Fail to attach tracepoint"); + skel->links.tp_exit = + bpf_program__attach_tracepoint(skel->progs.tp_exit, tp_class.c_str(), func.c_str()); + CHECK_ERR(!skel->links.tp_exit, "Fail to attach tracepoint"); + return 0; +} +static int attach_usdt(struct funclatency_bpf *skel, std::string func, int pid) +{ + char bin_path[128]; + int err = get_binpath(bin_path, pid); + CHECK_ERR(err, "Fail to get lib path"); + skel->links.usdt_entry = + bpf_program__attach_usdt(skel->progs.usdt_entry, pid, bin_path, "libc", func.c_str(), NULL); + CHECK_ERR(!skel->links.usdt_entry, "Fail to attach usdt"); + skel->links.usdt_exit = + bpf_program__attach_usdt(skel->progs.usdt_exit, pid, bin_path, "libc", func.c_str(), NULL); + CHECK_ERR(!skel->links.usdt_exit, "Fail to attach usdt"); +} +int FunclatencyStackCollector::attach(void) +{ + // dynamic mounting + std::vector strList; + splitStr(probe, ':', strList); + std::string func = probe; + int err; + + if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") + func = strList[2]; + if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")) + { + err = attach_kprobes(skel, func); + } + else if (strList.size() == 3 && strList[0] == "t") + { + err = attach_tp(skel, strList[1], strList[2]); + } + else if (strList.size() == 2 || (strList.size() == 3 && strList[0] == "p" && strList[1] != "")) + { + if (strList.size() == 3) + func = strList[1] + ":" + strList[2]; + err = attach_uprobes(skel, func, pid); + } + else if (strList.size() == 3 && strList[0] == "u") + { + char path[128]; + int err = get_binpath(path,pid); + CHECK_ERR(err, "Fail to get lib path"); + skel->links.usdt_entry = + bpf_program__attach_usdt(skel->progs.usdt_entry ,pid,path,"libc",strList[2].c_str(),NULL); + CHECK_ERR(!skel->links.usdt_entry , "Fail to attach usdt"); + } + else + { + printf("Type must be 'p', 't', or 'u' or too any args"); + } + + CHECK_ERR(err, "Fail to attach"); + + return 0; +}; + +void FunclatencyStackCollector::detach(void) +{ + DETACH_PROTO; +}; + +void FunclatencyStackCollector::unload(void) +{ + UNLOAD_PROTO; +}; + +void FunclatencyStackCollector::activate(bool tf) +{ + ACTIVE_SET(tf); +} + +const char *FunclatencyStackCollector::getName(void) +{ + return "FunclatencyStackCollector"; +} + +// ========== other implementations ========== + +FunclatencyStackCollector::FunclatencyStackCollector() +{ + scale_num = 2; + scales = new Scale[scale_num]{ + {"latencyTime", 1, "us"}, + {"latencyCount", 1, "counts"}, + }; +}; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index 842363627..6f3105212 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -23,6 +23,7 @@ #include #include "bpf_wapper/on_cpu.h" +#include "bpf_wapper/funclatency.h" #include "bpf_wapper/llc_stat.h" #include "bpf_wapper/off_cpu.h" #include "bpf_wapper/memleak.h" @@ -151,7 +152,15 @@ int main(int argc, char *argv[]) ->setScale(IntTmp); })) % "Set sampling period; default is 100", TraceOption); - + auto FunclatencyOption = clipp::option("funclatency").call([] + { StackCollectorList.push_back(new FunclatencyStackCollector()); }) % + COLLECTOR_INFO("funclatency") & + (clipp::value("probe", StrTmp) + .call([] + { static_cast(StackCollectorList.back()) + ->setScale(StrTmp); }) % + "set the probe string to time specfic func; default period is ns" & + TraceOption); auto MainOption = _GREEN "Some overall options" _RE % (( ((clipp::option("-p") & @@ -194,6 +203,7 @@ int main(int argc, char *argv[]) ReadaheadOption, ProbeOption, LlcStatOption, + FunclatencyOption, MainOption, Info); }