diff --git a/.github/workflows/eBPF_proc_image.yml b/.github/workflows/eBPF_proc_image.yml index 50c39ebb1..744a4be55 100644 --- a/.github/workflows/eBPF_proc_image.yml +++ b/.github/workflows/eBPF_proc_image.yml @@ -53,8 +53,9 @@ jobs: - name: Run proc_image run: | cd eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image - make proc_image - sudo ./proc_image -a -p 1 -t 1 + make + sudo ./proc_image -a & + sudo ./controller -f - name: Run test_proc run: | diff --git a/.gitignore b/.gitignore index 15b9578e1..681a24621 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,7 @@ eBPF_Supermarket/kvm_watcher/**/temp* eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/.output/* eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/test/test_proc +eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/controller # libbpf_bootstrap .output diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile index cbfc1e413..2c7d12a2a 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile @@ -42,7 +42,8 @@ CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) APPS = resource_image lock_image syscall_image keytime_image schedule_image -TARGETS = proc_image +WORKTOOL := proc_image +CONTROLLER := controller SRC_DIR = ./include COMMON_OBJ = \ @@ -83,12 +84,12 @@ $(call allow-override,CC,$(CROSS_COMPILE)cc) $(call allow-override,LD,$(CROSS_COMPILE)ld) .PHONY: all -all: $(TARGETS) +all: $(CONTROLLER) $(WORKTOOL) SUCCESS_MESSAGE .PHONY: clean clean: $(call msg,CLEAN) - $(Q)rm -rf $(OUTPUT) $(TARGETS) + $(Q)rm -rf $(OUTPUT) $(WORKTOOL) $(CONTROLLER) $(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): $(call msg,MKDIR,$@) @@ -126,17 +127,37 @@ $(OUTPUT)/%.o: $(SRC_DIR)/%.c | $(OUTPUT) $(call msg,CC,$@) $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ -$(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) +$(OUTPUT)/%.o: $(CONTROLLER).c | $(OUTPUT) + $(call msg,CC,$@) + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +$(OUTPUT)/$(WORKTOOL).o: $(WORKTOOL).c $(APPS) | $(OUTPUT) $(call msg,CC,$@) $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ # Build application binary and Create a file for storing data -$(TARGETS): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT) +$(CONTROLLER): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT) + $(call msg,BINARY,$@) + $(Q)$(CC) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@ + +$(WORKTOOL): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT) $(call msg,BINARY,$@) $(Q)$(CC) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@ @mkdir -p $(OUTPUT)/data @[ -f $(OUTPUT)/data/offcpu_stack.txt ] || touch $(OUTPUT)/data/offcpu_stack.txt +SUCCESS_MESSAGE: + @echo " ____ ____ ______ ____ ____ " + @echo " ___ / __ )/ __ \/ ____/ / __ \_________ _____ / _/___ ___ ____ _____ ____ " + @echo " / _ \/ __ / /_/ / /_ / /_/ / ___/ __ \/ ___/ / // __ \`__ \/ __ \`/ __ \`/ _ \\" + @echo "/ __/ /_/ / ____/ __/ / ____/ / / /_/ / /__ _/ // / / / / / /_/ / /_/ / __/" + @echo "\___/_____/_/ /_/ /_/ /_/ \____/\___/ /___/_/ /_/ /_/\__,_/\__, /\___/ " + @echo " /____/ " + @echo "Successful to compile eBPF_proc_image tools:" + @echo "proc_image ——— Pre-attach to eBPF program, data is collected and output after activation" + @echo "controller ——— Controller for proc_image tool" + @echo "Please start your use ~" + # delete failed targets .DELETE_ON_ERROR: diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/README.md b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/README.md index 65a9dd56b..4626ce028 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/README.md +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/README.md @@ -1,44 +1,62 @@ -# 基于eBPF的Linux系统性能监测工具-进程画像 +# 基于eBPF的进程生命周期画像 ## 一、介绍 -本项目是一个Linux进程生命周期画像工具,通过该工具可以清晰展示出一个进程从创建到终止的完整生命周期,并可以额外展示出进程/线程持有锁的区间画像、进程/线程上下文切换原因的标注、线程之间依赖关系(线程)、进程关联调用栈信息标注等。在这些功能的前提下,加入了更多的可视化元素和交互方式,使得整个画像更加直观、易于理解。 +本项目是一个Linux进程生命周期画像工具,可以清晰地展示出目标线程、目标线程组甚至系统中所有线程从创建到终止的完整生命周期,所展示出的进程生命周期信息包括关键时间点信息(execve、exit、fork、vfork、pthread_create、上下CPU等)、持有锁信息、资源使用信息、调度信息、系统调用序列信息等,并在特定的信息中加入了系统相关信息以作为参考和对比,考虑到对系统性能的影响和在高负载环境下的使用,该工具支持预先挂载使用激活的操作模式,同时在这些功能的前提下,基于Prometheus和Grafana构建了一个进程可视化平台,以实现进程画像的目的,并且通过清晰的进程画像即可察觉到进程的异常行为。 -运行环境:Ubuntu 22.04,内核版本 6.2 +eBPF_proc_image 工具的框架图: + +
-## 二、安装依赖 +## 二、安装工具 + +运行环境:Ubuntu 22.04,内核版本 6.2 ``` sudo apt update sudo apt install libbpf-dev clang llvm libelf-dev libpcap-dev gcc-multilib build-essential git submodule update --init --recursive +make ``` ## 三、proc_image 工具 -目前 proc_image 工具具备的功能: - -- 记录进程上下CPU的时间信息 -- 记录进程的关键时间点信息,即exec和exit -- 记录进程持有锁的区间信息,目前实现了用户态互斥锁、内核态互斥锁、用户态读写锁 -- 记录新创建进程或线程的时间信息 +proc_image 工具用于挂载 eBPF 的内核态程序,但不进行采集数据,并在用户态循环遍历 map,若有数据则输出 proc_image 工具的参数信息: | 参数 | 描述 | | -------------------- | ------------------------------------------------- | -| -p, --pid=PID | 指定跟踪进程的pid,默认为0号进程 | -| -t, --time=TIME-SEC | 设置程序的最大运行时间(0表示无限),默认一直运行 | -| -c, --cpuid=CPUID | 为每CPU进程设置,其他进程不需要设置该参数 | -| -r, --resource | 采集进程的资源使用情况,包括CPU利用率、内存利用率、每秒读写字节数(可持续开发) | -| -s, --syscall | 采集进程的系统调用序列信息 | -| -l, --lock | 采集进程持有的用户态锁信息,包括用户态互斥锁、用户态读写锁(可持续开发) | -| -q, --quote | 在参数周围添加引号(") | -| -k, --keytime | 采集进程关键时间点的相关信息,包括execve、exit、fork、vfork、pthread_create | -| -S, --schedule | 采集进程的调度信息 | -| -a, --all | 启动所有的采集进程数据的功能 | +| -a, --all | 挂载所有的 eBPF 内核态程序,但不进行采集数据 | +| -k, --keytime | 挂载进程关键时间点相关的 eBPF 内核态程序,但不进行采集数据 | +| -l, --lock | 挂载进程用户态持有锁相关的 eBPF 内核态程序,但不进行采集数据 | +| -r, --resource | 挂载进程资源使用情况相关的 eBPF 内核态程序,但不进行采集数据 | +| -s, --syscall | 挂载进程系统调用相关的 eBPF 内核态程序,但不进行采集数据 | +| -S, --schedule | 挂载进程调度相关的 eBPF 内核态程序,但不进行采集数据 | | -h, --help | 显示帮助信息 | +## 四、controller 工具 + +controller 工具用于控制eBPF程序的执行,可动态调整数据的采集策略 + +controller 工具的参数信息: + +| 参数 | 描述 | +| ---------------------- | ------------------------------------------------------------ | +| -a, --activate | 设置 proc_image 工具的启动策略 | +| -d, --deactivate | 初始化为原始的失活状态 | +| -f, --finish | 结束 proc_image 工具的运行 | +| -p, --pid=PID | 指定跟踪进程的pid | +| -P, --tgid=TGID | 指定跟踪进程的tgid | +| -c, --cpuid=CPUID | 为每CPU进程设置,其他进程不需要设置该参数 | +| -t, --time=TIME-SEC | 设置程序的最大运行时间(0表示无限),默认一直运行 | +| -r, --resource | 采集进程的资源使用情况,包括CPU利用率、内存利用率、每秒读写字节数(可持续开发) | +| -l, --lock | 采集进程持有用户态锁的时间信息,包括用户态互斥锁、用户态读写锁、用户态自旋锁(可持续开发) | +| -k, --keytime=KEYTIME | 采集进程关键时间点的相关信息,包括fork、vfork、pthread_create、execve、exit、onCPU、offCPU及offCPU的原因(可持续开发) | +| -s, --syscall=SYSCALLS | 采集进程以及系统的系统调用信息,进程的系统调用信息包括系统调用序列、前三个调用最频繁的系统调用、系统调用的平均延迟、最大延迟以及最小延迟,同时也采集了系统的这些延迟信息以作为参考和对比 | +| -S, --schedule | 采集进程及系统的调度信息,其中系统的调度信息具有参考和对比的作用,调度信息包括调度的平均延迟、最大延迟以及最小延迟 | +| -h, --help | 显示帮助信息 | + ## 四、tools tools文件夹中的eBPF程序是按照进程生命周期中数据的类型分别进行实现的: @@ -51,18 +69,10 @@ tools文件夹中的eBPF程序是按照进程生命周期中数据的类型分 | syscall_image | 对进程的系统调用序列进行画像 | | schedule_image | 对进程的调度信息进行画像 | -## 五、test_proc 测试程序 - -目前 [test_proc](./test/test_proc.c) 测试程序所具备逻辑: +## 五、基于 Prometheus 和 Grafana 的可视化平台 -- 逻辑1:加入sleep逻辑使进程睡眠3秒,即offCPU 3秒 -- 逻辑2:加入互斥锁逻辑,为了应对复杂场景,模拟进程异常地递归加锁解锁 -- 逻辑3:加入fork和vfork逻辑,创建子进程让子进程睡眠3秒,以表示它存在的时间 -- 逻辑4:加入pthread_create逻辑,创建线程让线程睡眠3秒,以表示它存在的时间 -- 逻辑5:加入读写锁逻辑,在读模式或写模式下上锁后睡眠3s,以表示持有锁时间 -- 逻辑6:加入execve逻辑,用于测试采集到数据的准确性 -- 逻辑7:加入exit逻辑,可以手动输入程序退出的error_code值 +基于 Prometheus 和 Grafana 的可视化平台框架图: -## 六、进程画像可视化 +
-可以参考:[进程画像可视化指南](docs/proc_image_vis_guide.md) \ No newline at end of file +eBPF_proc_image 工具的可视化操作可以参考:[进程画像可视化指南](docs/proc_image_vis_guide.md) \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/keytime_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/keytime_image.bpf.c index 65eb16892..d8c26f2e2 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/keytime_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/keytime_image.bpf.c @@ -27,10 +27,15 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; const volatile int max_args = DEFAULT_MAXARGS; -const volatile pid_t target_pid = -1; const volatile pid_t ignore_tgid = -1; -const volatile pid_t target_tgid = -1; -const volatile bool enable_cpu = false; +const int key = 0; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, int); + __type(value, struct kt_ctrl); +} kt_ctrl_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -61,11 +66,16 @@ struct { SEC("tracepoint/syscalls/sys_enter_execve") int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + int pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && ((target_tgid==-1 && target_pid==-1) || (target_tgid!=-1 && tgid==target_tgid) || - (target_pid!=-1 && pid==target_pid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && pid==kt_ctrl->target_pid))){ struct keytime_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); if(!event) @@ -78,6 +88,8 @@ int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx event->type = 1; event->pid = pid; + if(kt_ctrl->target_tgid != -1) event->tgid = tgid; + else event->tgid = -1; event->info_count = 0; event->info_size = 0; event->enable_char_info = true; @@ -137,11 +149,16 @@ int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx SEC("tracepoint/syscalls/sys_exit_execve") int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + int pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && ((target_tgid==-1 && target_pid==-1) || (target_tgid!=-1 && tgid==target_tgid) || - (target_pid!=-1 && pid==target_pid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && pid==kt_ctrl->target_pid))){ struct keytime_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); if(!event) @@ -149,6 +166,8 @@ int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) event->type = 2; event->pid = pid; + if(kt_ctrl->target_tgid != -1) event->tgid = tgid; + else event->tgid = -1; event->enable_char_info = false; event->info_count = 1; event->info[0] = ctx->ret; @@ -163,13 +182,19 @@ int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) SEC("uretprobe/fork") int BPF_KRETPROBE(fork_exit,int ret) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; // 判断是否为父进程触发 - if(tgid!=ignore_tgid && ret!=0 && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ret!=0 && ((kt_ctrl->target_pid ==-1 && kt_ctrl->target_tgid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && pid==kt_ctrl->target_pid))){ pid_t child_pid = ret; - child_create(4,child_pid,pid,&child,&keytime_rb); + child_create(4,child_pid,pid,&child,&keytime_rb,tgid,kt_ctrl->target_tgid); } return 0; @@ -179,15 +204,20 @@ int BPF_KRETPROBE(fork_exit,int ret) SEC("uretprobe/vfork") int BPF_KRETPROBE(vfork_exit,int ret) { - struct task_struct *current = (struct task_struct *)bpf_get_current_task(); + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + + struct task_struct *current = (struct task_struct *)bpf_get_current_task(); pid_t ppid = BPF_CORE_READ(current,real_parent,pid); int ptgid = BPF_CORE_READ(current,real_parent,tgid); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && ((target_pid==-1 && target_tgid==-1) || (target_pid!=-1 && ppid==target_pid)) || - (target_tgid!=-1 && ptgid==target_tgid)){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_pid==-1 && kt_ctrl->target_tgid==-1) || + (kt_ctrl->target_pid!=-1 && ppid==kt_ctrl->target_pid)) || (kt_ctrl->target_tgid!=-1 && ptgid==kt_ctrl->target_tgid)){ pid_t child_pid = BPF_CORE_READ(current,pid); - child_create(6,child_pid,ppid,&child,&keytime_rb); + child_create(6,child_pid,ppid,&child,&keytime_rb,ptgid,kt_ctrl->target_tgid); } return 0; @@ -196,10 +226,16 @@ int BPF_KRETPROBE(vfork_exit,int ret) SEC("uprobe/pthread_create") int BPF_KPROBE(pthread_create_enter) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + int current = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && current==kt_ctrl->target_pid))){ bool pthread_create_flag = true; bpf_map_update_elem(&pthread_create_enable, ¤t, &pthread_create_flag, BPF_ANY); } @@ -210,10 +246,16 @@ int BPF_KPROBE(pthread_create_enter) SEC("uretprobe/pthread_create") int BPF_KRETPROBE(pthread_create_exit,int ret) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + int current = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && current==kt_ctrl->target_pid))){ bpf_map_delete_elem(&pthread_create_enable, ¤t); } @@ -224,11 +266,16 @@ int BPF_KRETPROBE(pthread_create_exit,int ret) SEC("tracepoint/syscalls/sys_exit_clone3") int tracepoint__syscalls__sys_exit_clone3(struct trace_event_raw_sys_exit* ctx) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + pid_t current = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && ((target_tgid==-1 && target_pid==-1) || (target_tgid!=-1 && tgid==target_tgid) || - (target_pid!=-1 && current==target_pid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && current==kt_ctrl->target_pid))){ // 判断是否是pthread_create函数触发的clone3系统调用 bool *pthread_create_flag; pthread_create_flag = bpf_map_lookup_elem(&pthread_create_enable, ¤t); @@ -237,7 +284,7 @@ int tracepoint__syscalls__sys_exit_clone3(struct trace_event_raw_sys_exit* ctx) // 排除clone3错误返回的情况 if(new_thread <= 0) return 0; - child_create(8,new_thread,current,&child,&keytime_rb); + child_create(8,new_thread,current,&child,&keytime_rb,tgid,kt_ctrl->target_tgid); } } @@ -247,11 +294,16 @@ int tracepoint__syscalls__sys_exit_clone3(struct trace_event_raw_sys_exit* ctx) SEC("tracepoint/syscalls/sys_enter_exit_group") int tracepoint__syscalls__sys_enter_exit_group(struct trace_event_raw_sys_enter* ctx) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + int pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && ((target_tgid==-1 && target_pid==-1) || (target_tgid!=-1 && tgid==target_tgid) || - (target_pid!=-1 && pid==target_pid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && pid==kt_ctrl->target_pid))){ // 记录进程退出信息 struct keytime_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); @@ -260,27 +312,34 @@ int tracepoint__syscalls__sys_enter_exit_group(struct trace_event_raw_sys_enter* event->type = 3; event->pid = pid; + if(kt_ctrl->target_tgid != -1) event->tgid = tgid; + else event->tgid = -1; event->enable_char_info = false; event->info_count = 1; event->info[0] = ctx->args[0]; bpf_ringbuf_submit(event, 0); - - // 记录 fork 和 vfork 子进程的退出时间,并输出到 ringbuf 中 - child_exit(&child,&keytime_rb); } + // 记录 fork 和 vfork 子进程的退出时间,并输出到 ringbuf 中 + child_exit(&child,&keytime_rb); + return 0; } SEC("tracepoint/syscalls/sys_enter_exit") int tracepoint__syscalls__sys_enter_exit(struct trace_event_raw_sys_enter* ctx) { + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_func) + return 0; + int pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && ((target_tgid==-1 && target_pid==-1) || (target_tgid!=-1 && tgid==target_tgid) || - (target_pid!=-1 && pid==target_pid))){ + if((kt_ctrl->enable_myproc || tgid!=ignore_tgid) && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && pid==kt_ctrl->target_pid))){ // 记录进程退出信息 struct keytime_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); @@ -289,23 +348,28 @@ int tracepoint__syscalls__sys_enter_exit(struct trace_event_raw_sys_enter* ctx) event->type = 3; event->pid = pid; + if(kt_ctrl->target_tgid != -1) event->tgid = tgid; + else event->tgid = -1; event->enable_char_info = false; event->info_count = 1; event->info[0] = ctx->args[0]; bpf_ringbuf_submit(event, 0); - - // 记录 pthread_create 新线程的退出时间,并输出 - child_exit(&child,&keytime_rb); } + // 记录 pthread_create 新线程的退出时间,并输出 + child_exit(&child,&keytime_rb); + return 0; } SEC("tp_btf/sched_switch") int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_struct *next) { - if(!enable_cpu) return 0; + struct kt_ctrl *kt_ctrl; + kt_ctrl = bpf_map_lookup_elem(&kt_ctrl_map,&key); + if(!kt_ctrl || !kt_ctrl->kt_cpu_func) + return 0; pid_t next_pid = BPF_CORE_READ(next,pid); int next_tgid = BPF_CORE_READ(next,tgid); @@ -314,8 +378,8 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s int cpu_id = bpf_get_smp_processor_id(); // 记录 prev 进程的下CPU时的信息 - if(prev_tgid!=ignore_tgid && prev_pid!=0 && ((target_tgid==-1 && target_pid==-1) || - (target_tgid!=-1 && prev_tgid==target_tgid) || (target_pid!=-1 && prev_pid==target_pid))){ + if((kt_ctrl->enable_myproc || prev_tgid!=ignore_tgid) && prev_pid!=0 && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && prev_tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && prev_pid==kt_ctrl->target_pid))){ struct offcpu_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); @@ -324,6 +388,8 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s event->type = 11; event->pid = prev_pid; + if(kt_ctrl->target_tgid != -1) event->tgid = prev_tgid; + else event->tgid = -1; event->offcpu_time = bpf_ktime_get_ns(); event->kstack_sz = bpf_get_stack(ctx, event->kstack, sizeof(event->kstack), 0); @@ -331,8 +397,8 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s } // 记录 next 进程上CPU时的信息 - if(next_tgid!=ignore_tgid && next_pid!=0 && ((target_tgid==-1 && target_pid==-1) || - (target_tgid!=-1 && next_tgid==target_tgid) || (target_pid!=-1 && next_pid==target_pid))){ + if((kt_ctrl->enable_myproc || next_tgid!=ignore_tgid) && next_pid!=0 && ((kt_ctrl->target_tgid==-1 && kt_ctrl->target_pid==-1) || + (kt_ctrl->target_tgid!=-1 && next_tgid==kt_ctrl->target_tgid) || (kt_ctrl->target_pid!=-1 && next_pid==kt_ctrl->target_pid))){ struct keytime_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); @@ -341,6 +407,8 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s event->type = 10; event->pid = next_pid; + if(kt_ctrl->target_tgid != -1) event->tgid = next_tgid; + else event->tgid = -1; event->enable_char_info = false; event->info_count = 1; event->info[0] = bpf_ktime_get_ns(); diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/lock_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/lock_image.bpf.c index ad97ddc8f..05e7fddfd 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/lock_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/lock_image.bpf.c @@ -26,7 +26,13 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; const volatile pid_t ignore_tgid = -1; -const volatile int target_tgid = -1; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, int); + __type(value, struct lock_ctrl); +} lock_ctrl_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -58,7 +64,7 @@ struct { SEC("uprobe/pthread_mutex_lock") int BPF_KPROBE(pthread_mutex_lock_enter, void *__mutex) { - record_lock_enter(target_tgid,ignore_tgid,1,1,__mutex,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,1,1,__mutex,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -66,7 +72,7 @@ int BPF_KPROBE(pthread_mutex_lock_enter, void *__mutex) SEC("uretprobe/pthread_mutex_lock") int BPF_KRETPROBE(pthread_mutex_lock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,2,1,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,2,1,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -74,7 +80,7 @@ int BPF_KRETPROBE(pthread_mutex_lock_exit,int ret) SEC("uprobe/__pthread_mutex_trylock") int BPF_KPROBE(__pthread_mutex_trylock_enter, void *__mutex) { - record_lock_enter(target_tgid,ignore_tgid,1,1,__mutex,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,1,1,__mutex,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -82,7 +88,7 @@ int BPF_KPROBE(__pthread_mutex_trylock_enter, void *__mutex) SEC("uretprobe/__pthread_mutex_trylock") int BPF_KRETPROBE(__pthread_mutex_trylock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,2,1,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,2,1,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -90,7 +96,7 @@ int BPF_KRETPROBE(__pthread_mutex_trylock_exit,int ret) SEC("uprobe/pthread_mutex_unlock") int BPF_KPROBE(pthread_mutex_unlock_enter, void *__rwlock) { - record_unlock_enter(target_tgid,ignore_tgid,1,__rwlock,&proc_unlock); + record_unlock_enter(ignore_tgid,1,__rwlock,&proc_unlock,&lock_ctrl_map); return 0; } @@ -100,7 +106,7 @@ int BPF_KPROBE(pthread_mutex_unlock_enter, void *__rwlock) SEC("uretprobe/pthread_mutex_unlock") int BPF_KRETPROBE(pthread_mutex_unlock_exit) { - record_unlock_exit(target_tgid,ignore_tgid,3,1,&lock_rb,&proc_unlock,&locktype); + record_unlock_exit(ignore_tgid,3,1,&lock_rb,&proc_unlock,&locktype,&lock_ctrl_map); return 0; } @@ -109,7 +115,7 @@ int BPF_KRETPROBE(pthread_mutex_unlock_exit) SEC("uprobe/__pthread_rwlock_rdlock") int BPF_KPROBE(__pthread_rwlock_rdlock_enter, void *__rwlock) { - record_lock_enter(target_tgid,ignore_tgid,4,2,__rwlock,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,4,2,__rwlock,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -117,7 +123,7 @@ int BPF_KPROBE(__pthread_rwlock_rdlock_enter, void *__rwlock) SEC("uretprobe/__pthread_rwlock_rdlock") int BPF_KRETPROBE(__pthread_rwlock_rdlock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,5,2,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,5,2,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -125,7 +131,7 @@ int BPF_KRETPROBE(__pthread_rwlock_rdlock_exit,int ret) SEC("uprobe/__pthread_rwlock_tryrdlock") int BPF_KPROBE(__pthread_rwlock_tryrdlock_enter, void *__rwlock) { - record_lock_enter(target_tgid,ignore_tgid,4,2,__rwlock,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,4,2,__rwlock,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -133,7 +139,7 @@ int BPF_KPROBE(__pthread_rwlock_tryrdlock_enter, void *__rwlock) SEC("uretprobe/__pthread_rwlock_tryrdlock") int BPF_KRETPROBE(__pthread_rwlock_tryrdlock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,5,2,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,5,2,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -141,7 +147,7 @@ int BPF_KRETPROBE(__pthread_rwlock_tryrdlock_exit,int ret) SEC("uprobe/__pthread_rwlock_wrlock") int BPF_KPROBE(__pthread_rwlock_wrlock_enter, void *__rwlock) { - record_lock_enter(target_tgid,ignore_tgid,7,2,__rwlock,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,7,2,__rwlock,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -149,7 +155,7 @@ int BPF_KPROBE(__pthread_rwlock_wrlock_enter, void *__rwlock) SEC("uretprobe/__pthread_rwlock_wrlock") int BPF_KRETPROBE(__pthread_rwlock_wrlock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,8,2,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,8,2,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -157,7 +163,7 @@ int BPF_KRETPROBE(__pthread_rwlock_wrlock_exit,int ret) SEC("uprobe/__pthread_rwlock_trywrlock") int BPF_KPROBE(__pthread_rwlock_trywrlock_enter, void *__rwlock) { - record_lock_enter(target_tgid,ignore_tgid,7,2,__rwlock,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,7,2,__rwlock,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -165,7 +171,7 @@ int BPF_KPROBE(__pthread_rwlock_trywrlock_enter, void *__rwlock) SEC("uretprobe/__pthread_rwlock_trywrlock") int BPF_KRETPROBE(__pthread_rwlock_trywrlock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,8,2,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,8,2,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -173,7 +179,7 @@ int BPF_KRETPROBE(__pthread_rwlock_trywrlock_exit,int ret) SEC("uprobe/__pthread_rwlock_unlock") int BPF_KPROBE(__pthread_rwlock_unlock_enter, void *__rwlock) { - record_unlock_enter(target_tgid,ignore_tgid,2,__rwlock,&proc_unlock); + record_unlock_enter(ignore_tgid,2,__rwlock,&proc_unlock,&lock_ctrl_map); return 0; } @@ -181,7 +187,7 @@ int BPF_KPROBE(__pthread_rwlock_unlock_enter, void *__rwlock) SEC("uretprobe/__pthread_rwlock_unlock") int BPF_KRETPROBE(__pthread_rwlock_unlock_exit) { - record_unlock_exit(target_tgid,ignore_tgid,0,2,&lock_rb,&proc_unlock,&locktype); + record_unlock_exit(ignore_tgid,0,2,&lock_rb,&proc_unlock,&locktype,&lock_ctrl_map); return 0; } @@ -190,7 +196,7 @@ int BPF_KRETPROBE(__pthread_rwlock_unlock_exit) SEC("uprobe/pthread_spin_lock") int BPF_KPROBE(pthread_spin_lock_enter, void *__spinlock) { - record_lock_enter(target_tgid,ignore_tgid,10,3,__spinlock,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,10,3,__spinlock,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -198,7 +204,7 @@ int BPF_KPROBE(pthread_spin_lock_enter, void *__spinlock) SEC("uretprobe/pthread_spin_lock") int BPF_KRETPROBE(pthread_spin_lock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,11,3,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,11,3,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -206,7 +212,7 @@ int BPF_KRETPROBE(pthread_spin_lock_exit,int ret) SEC("uprobe/pthread_spin_trylock") int BPF_KPROBE(pthread_spin_trylock_enter, void *__spinlock) { - record_lock_enter(target_tgid,ignore_tgid,10,3,__spinlock,&lock_rb,&proc_lock); + record_lock_enter(ignore_tgid,10,3,__spinlock,&lock_rb,&proc_lock,&lock_ctrl_map); return 0; } @@ -214,7 +220,7 @@ int BPF_KPROBE(pthread_spin_trylock_enter, void *__spinlock) SEC("uretprobe/pthread_spin_trylock") int BPF_KRETPROBE(pthread_spin_trylock_exit,int ret) { - record_lock_exit(target_tgid,ignore_tgid,11,3,ret,&lock_rb,&proc_lock,&locktype); + record_lock_exit(ignore_tgid,11,3,ret,&lock_rb,&proc_lock,&locktype,&lock_ctrl_map); return 0; } @@ -222,7 +228,7 @@ int BPF_KRETPROBE(pthread_spin_trylock_exit,int ret) SEC("uprobe/pthread_spin_unlock") int BPF_KPROBE(pthread_spin_unlock_enter, void *__spinlock) { - record_unlock_enter(target_tgid,ignore_tgid,3,__spinlock,&proc_unlock); + record_unlock_enter(ignore_tgid,3,__spinlock,&proc_unlock,&lock_ctrl_map); return 0; } @@ -230,7 +236,7 @@ int BPF_KPROBE(pthread_spin_unlock_enter, void *__spinlock) SEC("uretprobe/pthread_spin_unlock") int BPF_KRETPROBE(pthread_spin_unlock_exit) { - record_unlock_exit(target_tgid,ignore_tgid,12,3,&lock_rb,&proc_unlock,&locktype); + record_unlock_exit(ignore_tgid,12,3,&lock_rb,&proc_unlock,&locktype,&lock_ctrl_map); return 0; } \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/resource_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/resource_image.bpf.c index ceeed1b87..3ae375525 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/resource_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/resource_image.bpf.c @@ -25,10 +25,14 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -const volatile pid_t target_pid = -1; -const volatile int target_cpu_id = -1; const volatile pid_t ignore_tgid = -1; -const volatile pid_t target_tgid = -1; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, int); + __type(value, struct rsc_ctrl); +} rsc_ctrl_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -47,6 +51,12 @@ struct { SEC("kprobe/finish_task_switch.isra.0") int kprobe__finish_task_switch(struct pt_regs *ctx) { + int key = 0; + struct rsc_ctrl *rsc_ctrl; + rsc_ctrl = bpf_map_lookup_elem(&rsc_ctrl_map,&key); + if(!rsc_ctrl || !rsc_ctrl->rsc_func) + return 0; + struct task_struct *prev = (struct task_struct *)PT_REGS_PARM1(ctx); pid_t prev_pid = BPF_CORE_READ(prev,pid); int prev_cpu = bpf_get_smp_processor_id(); @@ -56,8 +66,8 @@ int kprobe__finish_task_switch(struct pt_regs *ctx) int next_cpu = prev_cpu; int next_tgid = BPF_CORE_READ(next,tgid); - if(prev_tgid!=ignore_tgid && ((target_pid==-1 && target_tgid==-1) || (target_pid!=0 && prev_pid==target_pid) || - (target_pid==0 && prev_pid==target_pid && prev_cpu==target_cpu_id) || (prev_tgid==target_tgid))){ + if((rsc_ctrl->enable_myproc || prev_tgid!=ignore_tgid) && ((rsc_ctrl->target_pid==-1 && rsc_ctrl->target_tgid==-1) || (rsc_ctrl->target_pid!=0 && prev_pid==rsc_ctrl->target_pid) || + (rsc_ctrl->target_pid==0 && prev_pid==rsc_ctrl->target_pid && prev_cpu==rsc_ctrl->target_cpu_id) || (prev_tgid==rsc_ctrl->target_tgid))){ struct proc_id prev_pd = {}; prev_pd.pid = prev_pid; if(prev_pid == 0) prev_pd.cpu_id = prev_cpu; @@ -87,6 +97,8 @@ int kprobe__finish_task_switch(struct pt_regs *ctx) #endif */ prev_total.pid = prev_pd.pid; + if(rsc_ctrl->target_tgid != -1) prev_total.tgid = prev_tgid; + else prev_total.tgid = -1; prev_total.cpu_id = prev_cpu; prev_total.time = bpf_ktime_get_ns() - prev_start->time; prev_total.memused = memused; @@ -126,9 +138,9 @@ int kprobe__finish_task_switch(struct pt_regs *ctx) } } } - - if(next_tgid!=ignore_tgid && ((target_pid==-1 && target_tgid==-1) || (target_pid!=0 && next_pid==target_pid) || - (target_pid==0 && next_pid==target_pid && next_cpu==target_cpu_id) || (next_tgid==target_tgid))){ + + if((rsc_ctrl->enable_myproc || next_tgid!=ignore_tgid) && ((rsc_ctrl->target_pid==-1 && rsc_ctrl->target_tgid==-1) || (rsc_ctrl->target_pid!=0 && next_pid==rsc_ctrl->target_pid) || + (rsc_ctrl->target_pid==0 && next_pid==rsc_ctrl->target_pid && next_cpu==rsc_ctrl->target_cpu_id) || (next_tgid==rsc_ctrl->target_tgid))){ struct proc_id next_pd = {}; struct start_rsc next_start={}; diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/schedule_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/schedule_image.bpf.c index 58dab8e99..5cf7fb920 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/schedule_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/schedule_image.bpf.c @@ -24,9 +24,14 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -const volatile pid_t target_pid = -1; -const volatile int target_cpu_id = -1; -const volatile int target_tgid = -1; +const int key = 0; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, int); + __type(value, struct sched_ctrl); +} sched_ctrl_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -66,7 +71,13 @@ struct { SEC("tp_btf/sched_wakeup") int BPF_PROG(sched_wakeup, struct task_struct *p) { + struct sched_ctrl *sched_ctrl; + sched_ctrl = bpf_map_lookup_elem(&sched_ctrl_map,&key); + if(!sched_ctrl || !sched_ctrl->sched_func) + return 0; + pid_t pid = BPF_CORE_READ(p,pid); + int tgid = BPF_CORE_READ(p,tgid); int cpu = bpf_get_smp_processor_id(); struct schedule_event *schedule_event; struct proc_id pd = {}; @@ -80,6 +91,7 @@ int BPF_PROG(sched_wakeup, struct task_struct *p) bool e_add = false; schedule_event.pid = pid; + schedule_event.tgid = tgid; // 提前将 count 值赋值为 1,避免输出时进程还没有被调度,导致除数出现 0 的情况 schedule_event.count = 1; schedule_event.enter_time = current_time; @@ -96,7 +108,13 @@ int BPF_PROG(sched_wakeup, struct task_struct *p) SEC("tp_btf/sched_wakeup_new") int BPF_PROG(sched_wakeup_new, struct task_struct *p) { + struct sched_ctrl *sched_ctrl; + sched_ctrl = bpf_map_lookup_elem(&sched_ctrl_map,&key); + if(!sched_ctrl || !sched_ctrl->sched_func) + return 0; + pid_t pid = BPF_CORE_READ(p,pid); + int tgid = BPF_CORE_READ(p,tgid); int cpu = bpf_get_smp_processor_id(); struct schedule_event *schedule_event; struct proc_id pd = {}; @@ -110,6 +128,7 @@ int BPF_PROG(sched_wakeup_new, struct task_struct *p) bool e_add = false; schedule_event.pid = pid; + schedule_event.tgid = tgid; schedule_event.count = 1; schedule_event.enter_time = current_time; @@ -125,7 +144,13 @@ int BPF_PROG(sched_wakeup_new, struct task_struct *p) SEC("tp_btf/sched_switch") int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_struct *next) { + struct sched_ctrl *sched_ctrl; + sched_ctrl = bpf_map_lookup_elem(&sched_ctrl_map,&key); + if(!sched_ctrl || !sched_ctrl->sched_func) + return 0; + pid_t prev_pid = BPF_CORE_READ(prev,pid); + int prev_tgid = BPF_CORE_READ(prev,tgid); int prev_cpu = bpf_get_smp_processor_id(); unsigned int prev_state = BPF_CORE_READ(prev,__state); pid_t next_pid = BPF_CORE_READ(next,pid); @@ -152,6 +177,7 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s bool e_add = false; schedule_event.pid = prev_pid; + schedule_event.tgid = prev_tgid; schedule_event.count = 1; schedule_event.enter_time = current_time; @@ -184,13 +210,13 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s schedule_event->min_delay = this_delay; /* 若指定 target 进程,则单独记录 target 进程的调度信息 */ - if(target_pid!=-1 && ((target_pid!=0 && next_pid==target_pid) || - (target_pid==0 && next_pid==target_pid && next_cpu==target_cpu_id))){ + if(sched_ctrl->target_pid!=-1 && ((sched_ctrl->target_pid!=0 && next_pid==sched_ctrl->target_pid) || + (sched_ctrl->target_pid==0 && next_pid==sched_ctrl->target_pid && next_cpu==sched_ctrl->target_cpu_id))){ bpf_map_update_elem(&target_schedule,&key,schedule_event,BPF_ANY); } /* 记录指定的线程组调度信息 */ - if(next_tgid == target_tgid){ + if(next_tgid == sched_ctrl->target_tgid){ bpf_map_update_elem(&tg_schedule,&next_pid,schedule_event,BPF_ANY); } @@ -221,6 +247,11 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s SEC("tracepoint/sched/sched_process_exit") int sched_process_exit(void *ctx) { + struct sched_ctrl *sched_ctrl; + sched_ctrl = bpf_map_lookup_elem(&sched_ctrl_map,&key); + if(!sched_ctrl || !sched_ctrl->sched_func) + return 0; + struct task_struct *p = (struct task_struct *)bpf_get_current_task(); pid_t pid = BPF_CORE_READ(p,pid); int tgid = BPF_CORE_READ(p,tgid); @@ -244,8 +275,8 @@ int sched_process_exit(void *ctx) } // 若目标进程退出,删除 target_schedule map 中的数据 - if(target_pid!=-1 && ((target_pid!=0 && pid==target_pid) || - (target_pid==0 && pid==target_pid && cpu==target_cpu_id))){ + if(sched_ctrl->target_pid!=-1 && ((sched_ctrl->target_pid!=0 && pid==sched_ctrl->target_pid) || + (sched_ctrl->target_pid==0 && pid==sched_ctrl->target_pid && cpu==sched_ctrl->target_cpu_id))){ schedule_event = bpf_map_lookup_elem(&target_schedule,&key); if(schedule_event){ // 将 count 设置成 0 即可实现目标进程退出标志 @@ -254,7 +285,7 @@ int sched_process_exit(void *ctx) } // 若目标进程中的线程退出,删除 tg_schedule map 中的数据 - if(tgid == target_tgid){ + if(tgid == sched_ctrl->target_tgid){ bpf_map_delete_elem(&tg_schedule,&pid); } diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/syscall_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/syscall_image.bpf.c index 57f9851ff..68d8f29d5 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/syscall_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/syscall_image.bpf.c @@ -24,10 +24,15 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -const volatile pid_t target_pid = -1; -const volatile pid_t target_tgid = -1; -const volatile int syscalls = 0; const volatile pid_t ignore_tgid = -1; +const int key = 0; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, int); + __type(value, struct sc_ctrl); +} sc_ctrl_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -44,10 +49,15 @@ struct { SEC("tracepoint/raw_syscalls/sys_enter") int sys_enter(struct trace_event_raw_sys_enter *args) { + struct sc_ctrl *sc_ctrl; + sc_ctrl = bpf_map_lookup_elem(&sc_ctrl_map,&key); + if(!sc_ctrl || !sc_ctrl->sc_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid/* && (target_pid==-1 || pid==target_pid)*/){ + if(sc_ctrl->enable_myproc || tgid!=ignore_tgid){ u64 current_time = bpf_ktime_get_ns(); struct syscall_seq * syscall_seq; @@ -58,8 +68,8 @@ int sys_enter(struct trace_event_raw_sys_enter *args) syscall_seq.pid = pid; syscall_seq.enter_time = current_time; syscall_seq.count = 1; - if((target_tgid==-1 && (target_pid==-1 || pid==target_pid)) || - (target_tgid!=-1 && tgid == target_tgid)){ + if((sc_ctrl->target_tgid==-1 && (sc_ctrl->target_pid==-1 || pid==sc_ctrl->target_pid)) || + (sc_ctrl->target_tgid!=-1 && tgid == sc_ctrl->target_tgid)){ syscall_seq.record_syscall[0] = (int)args->id; } @@ -67,14 +77,14 @@ int sys_enter(struct trace_event_raw_sys_enter *args) }else{ syscall_seq->enter_time = current_time; if(syscall_seq->count == 0){ - if((target_tgid==-1 && (target_pid==-1 || pid==target_pid)) || (target_tgid!=-1 && tgid == target_tgid)){ + if((sc_ctrl->target_tgid==-1 && (sc_ctrl->target_pid==-1 || pid==sc_ctrl->target_pid)) || (sc_ctrl->target_tgid!=-1 && tgid == sc_ctrl->target_tgid)){ syscall_seq->record_syscall[syscall_seq->count] = (int)args->id; } syscall_seq->count ++; }else if (syscall_seq->count <= MAX_SYSCALL_COUNT-1 && syscall_seq->count > 0 && syscall_seq->record_syscall+syscall_seq->count <= syscall_seq->record_syscall+(MAX_SYSCALL_COUNT-1)){ - if((target_tgid==-1 && (target_pid==-1 || pid==target_pid)) || - (target_tgid!=-1 && tgid == target_tgid)){ + if((sc_ctrl->target_tgid==-1 && (sc_ctrl->target_pid==-1 || pid==sc_ctrl->target_pid)) || + (sc_ctrl->target_tgid!=-1 && tgid == sc_ctrl->target_tgid)){ syscall_seq->record_syscall[syscall_seq->count] = (int)args->id; } syscall_seq->count ++; @@ -88,10 +98,15 @@ int sys_enter(struct trace_event_raw_sys_enter *args) SEC("tracepoint/raw_syscalls/sys_exit") int sys_exit(struct trace_event_raw_sys_exit *args) { + struct sc_ctrl *sc_ctrl; + sc_ctrl = bpf_map_lookup_elem(&sc_ctrl_map,&key); + if(!sc_ctrl || !sc_ctrl->sc_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid/* && (target_pid==-1 || pid==target_pid)*/){ + if(sc_ctrl->enable_myproc || tgid!=ignore_tgid){ u64 current_time = bpf_ktime_get_ns(); long long unsigned int this_delay; struct syscall_seq * syscall_seq; @@ -103,7 +118,7 @@ int sys_exit(struct trace_event_raw_sys_exit *args) this_delay = current_time-syscall_seq->enter_time; - if(syscall_seq->count < syscalls){ + if(syscall_seq->count < sc_ctrl->syscalls){ syscall_seq->sum_delay += this_delay; if(this_delay > syscall_seq->max_delay) syscall_seq->max_delay = this_delay; @@ -117,8 +132,8 @@ int sys_exit(struct trace_event_raw_sys_exit *args) syscall_seq->max_delay = this_delay; if(syscall_seq->min_delay==0 || this_delaymin_delay) syscall_seq->min_delay = this_delay; - if((target_tgid==-1 && (target_pid==-1 || pid==target_pid)) || - (target_tgid!=-1 && tgid == target_tgid)){ + if((sc_ctrl->target_tgid==-1 && (sc_ctrl->target_pid==-1 || pid==sc_ctrl->target_pid)) || + (sc_ctrl->target_tgid!=-1 && tgid == sc_ctrl->target_tgid)){ syscall_seq->proc_count += syscall_seq->count; syscall_seq->proc_sd += syscall_seq->sum_delay; } @@ -136,8 +151,8 @@ int sys_exit(struct trace_event_raw_sys_exit *args) e->count = syscall_seq->count; for(int i=0; i<=syscall_seq->count-1 && i<=MAX_SYSCALL_COUNT-1; i++) e->record_syscall[i] = syscall_seq->record_syscall[i]; - if((target_tgid==-1 && (target_pid==-1 || pid==target_pid)) || - (target_tgid!=-1 && tgid == target_tgid)){ + if((sc_ctrl->target_tgid==-1 && (sc_ctrl->target_pid==-1 || pid==sc_ctrl->target_pid)) || + (sc_ctrl->target_tgid!=-1 && tgid == sc_ctrl->target_tgid)){ e->proc_count = syscall_seq->proc_count; e->proc_sd = syscall_seq->proc_sd; } @@ -156,6 +171,11 @@ int sys_exit(struct trace_event_raw_sys_exit *args) SEC("tracepoint/sched/sched_process_exit") int sched_process_exit(void *ctx) { + struct sc_ctrl *sc_ctrl; + sc_ctrl = bpf_map_lookup_elem(&sc_ctrl_map,&key); + if(!sc_ctrl || !sc_ctrl->sc_func) + return 0; + struct task_struct *p = (struct task_struct *)bpf_get_current_task(); pid_t pid = BPF_CORE_READ(p,pid); diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/controller.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/controller.c new file mode 100644 index 000000000..121a8fdb1 --- /dev/null +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/controller.c @@ -0,0 +1,291 @@ +// 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: zhangziheng0525@163.com +// +// used to control the execution of proc_image tool +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc_image.h" +#include "hashmap.h" +#include "helpers.h" + +static struct env { + // 1代表activate;2代表deactivate;3代表finish + int usemode; + int pid; + int tgid; + int cpu_id; + int time; + int syscalls; + bool enable_myproc; + bool output_resourse; + bool output_schedule; + bool create_thread; + bool exit_thread; + bool enable_resource; + bool first_rsc; + bool enable_cpu; + bool enable_keytime; + bool enable_lock; + bool enable_syscall; + bool enable_schedule; +} env = { + .usemode = 0, + .pid = -1, + .tgid = -1, + .cpu_id = -1, + .time = 0, + .syscalls = 0, + .enable_myproc = false, + .output_resourse = false, + .output_schedule = false, + .create_thread = false, + .exit_thread = false, + .enable_resource = false, + .first_rsc = true, + .enable_cpu = false, + .enable_keytime = false, + .enable_lock = false, + .enable_syscall = false, + .enable_schedule = false, +}; + +const char argp_program_doc[] ="Trace process to get process image.\n"; + +static const struct argp_option opts[] = { + { "activate", 'a', NULL, 0, "Set startup policy of proc_image tool" }, + { "deactivate", 'd', NULL, 0, "Initialize to the original deactivated state" }, + { "finish", 'f', NULL, 0, "Finish to run eBPF tool" }, + { "pid", 'p', "PID", 0, "Process ID to trace" }, + { "tgid", 'P', "TGID", 0, "Thread group to trace" }, + { "cpuid", 'c', "CPUID", 0, "Set For Tracing per-CPU Process(other processes don't need to set this parameter)" }, + { "time", 't', "TIME-SEC", 0, "Max Running Time(0 for infinite)" }, + { "myproc", 'm', NULL, 0, "Trace the process of the tool itself (not tracked by default)" }, + { "resource", 'r', NULL, 0, "Collects resource usage information about processes" }, + { "keytime", 'k', "KEYTIME", 0, "Collects keytime information about processes(0:except CPU kt_info,1:all kt_info,any 0 or 1 when deactivated)" }, + { "lock", 'l', NULL, 0, "Collects lock information about processes" }, + { "syscall", 's', "SYSCALLS", 0, "Collects syscall sequence (1~50) information about processes(any 1~50 when deactivated)" }, + { "schedule", 'S', NULL, 0, "Collects schedule information about processes (trace tool process)" }, + { NULL, 'h', NULL, OPTION_HIDDEN, "show the full help" }, + {}, +}; + +static error_t parse_arg(int key, char *arg, struct argp_state *state) +{ + long pid; + long tgid; + long cpu_id; + long syscalls; + long enable_cpu; + switch (key) { + case 'a': + env.usemode = 1; + break; + case 'd': + env.usemode = 2; + break; + case 'f': + env.usemode = 3; + break; + case 'p': + errno = 0; + pid = strtol(arg, NULL, 10); + if (errno || pid < 0) { + warn("Invalid PID: %s\n", arg); + // 调用argp_usage函数,用于打印用法信息并退出程序 + argp_usage(state); + } + env.pid = pid; + break; + case 'P': + errno = 0; + tgid = strtol(arg, NULL, 10); + if (errno || tgid < 0) { + warn("Invalid TGID: %s\n", arg); + // 调用argp_usage函数,用于打印用法信息并退出程序 + argp_usage(state); + } + env.tgid = tgid; + break; + case 'c': + errno = 0; + cpu_id = strtol(arg, NULL, 10); + if(cpu_id < 0){ + warn("Invalid CPUID: %s\n", arg); + argp_usage(state); + } + env.cpu_id = cpu_id; + break; + case 't': + env.time = strtol(arg, NULL, 10); + if(env.time) alarm(env.time); + break; + case 'm': + env.enable_myproc = true; + break; + case 'r': + env.enable_resource = true; + break; + case 'k': + enable_cpu = strtol(arg, NULL, 10); + if(enable_cpu<0 || enable_cpu>1){ + warn("Invalid KEYTIME: %s\n", arg); + argp_usage(state); + } + env.enable_cpu = enable_cpu; + env.enable_keytime = true; + break; + case 'l': + env.enable_lock = true; + break; + case 's': + syscalls = strtol(arg, NULL, 10); + if(syscalls<=0 || syscalls>50){ + warn("Invalid SYSCALLS: %s\n", arg); + argp_usage(state); + } + env.syscalls = syscalls; + env.enable_syscall = true; + case 'S': + env.enable_schedule = true; + break; + case 'h': + argp_state_help(state, stderr, ARGP_HELP_STD_HELP); + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +int deactivate_mode(){ + int err; + + if(env.enable_resource){ + struct rsc_ctrl rsc_ctrl = {false,-1,-1,false,-1}; + err = update_rsc_ctrl_map(rsc_ctrl); + if(err < 0) return err; + } + + if(env.enable_keytime){ + struct kt_ctrl kt_ctrl = {false,false,false,-1,-1}; + err = update_kt_ctrl_map(kt_ctrl); + if(err < 0) return err; + } + + if(env.enable_lock){ + struct lock_ctrl lock_ctrl = {false,false,-1,-1}; + err = update_lock_ctrl_map(lock_ctrl); + if(err < 0) return err; + } + + if(env.enable_syscall){ + struct sc_ctrl sc_ctrl = {false,false,-1,-1,0}; + err = update_sc_ctrl_map(sc_ctrl); + if(err < 0) return err; + } + + if(env.enable_schedule){ + struct sched_ctrl sched_ctrl = {false,-1,-1,-1}; + err = update_sched_ctrl_map(sched_ctrl); + if(err < 0) return err; + } + + return 0; +} + +static void sig_handler(int signo) +{ + deactivate_mode(); +} + +int main(int argc, char **argv) +{ + int err; + static const struct argp argp = { + .options = opts, + .parser = parse_arg, + .doc = argp_program_doc, + }; + + err = argp_parse(&argp, argc, argv, 0, NULL, NULL); + if (err) + return err; + + signal(SIGALRM,sig_handler); + signal(SIGINT,sig_handler); + signal(SIGTERM,sig_handler); + + if(env.usemode == 1){ // activate mode + if(env.enable_resource){ + struct rsc_ctrl rsc_ctrl = {true, env.pid, env.cpu_id, env.enable_myproc, env.tgid}; + err = update_rsc_ctrl_map(rsc_ctrl); + if(err < 0) return err; + } + + if(env.enable_keytime){ + struct kt_ctrl kt_ctrl = {true,env.enable_cpu,env.enable_myproc,env.pid,env.tgid}; + err = update_kt_ctrl_map(kt_ctrl); + if(err < 0) return err; + } + + if(env.enable_lock){ + struct lock_ctrl lock_ctrl = {true,env.enable_myproc,env.pid,env.tgid}; + err = update_lock_ctrl_map(lock_ctrl); + if(err < 0) return err; + } + + if(env.enable_syscall){ + struct sc_ctrl sc_ctrl = {true,env.enable_myproc,env.pid,env.tgid,env.syscalls}; + err = update_sc_ctrl_map(sc_ctrl); + if(err < 0) return err; + } + + if(env.enable_schedule){ + struct sched_ctrl sched_ctrl = {true,env.pid,env.cpu_id,env.tgid}; + err = update_sched_ctrl_map(sched_ctrl); + if(err < 0) return err; + } + + if(env.time!=0) pause(); + }else if(env.usemode == 2){ // deactivate mode + err = deactivate_mode(); + if(err<0){ + fprintf(stderr, "Failed to deactivate\n"); + return err; + } + }else if(env.usemode == 3){ // finish mode + const char *command = "pkill proc_image"; + int status = system(command); + if (status == -1) { + perror("system"); + } + }else{ + // 输出help信息 + printf("Please enter the usage mode(activate/deactivate/finish) before selecting the function\n"); + argp_help(&argp, stderr, ARGP_HELP_LONG, argv[0]); + } + + return 0; +} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/images/eBPF_proc_image.png b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/images/eBPF_proc_image.png new file mode 100644 index 000000000..df78641c4 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/images/eBPF_proc_image.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/images/visualization_platform.png b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/images/visualization_platform.png new file mode 100644 index 000000000..039052268 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/images/visualization_platform.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/helpers.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/helpers.h index 7ebfbaf47..617b314cb 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/helpers.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/helpers.h @@ -24,7 +24,7 @@ .func_name = #sym_name); \ skel->links.prog_name = bpf_program__attach_uprobe_opts( \ skel->progs.prog_name, \ - env.pid, \ + -1, \ object, \ 0, \ &uprobe_opts); \ @@ -73,6 +73,12 @@ typedef unsigned int u32; #define KEYTIME_IMAGE 4 #define SCHEDULE_IMAGE 5 +const char *rsc_ctrl_path = "/sys/fs/bpf/proc_image_map/rsc_ctrl_map"; +const char *kt_ctrl_path = "/sys/fs/bpf/proc_image_map/kt_ctrl_map"; +const char *lock_ctrl_path = "/sys/fs/bpf/proc_image_map/lock_ctrl_map"; +const char *sched_ctrl_path = "/sys/fs/bpf/proc_image_map/sched_ctrl_map"; +const char *sc_ctrl_path = "/sys/fs/bpf/proc_image_map/sc_ctrl_map"; + struct proc_syscall_info { int first_syscall; int second_syscall; @@ -138,5 +144,114 @@ void update_syscalls(u32 *syscalls, const struct syscall_seq *e, int *first_sysc *third_syscall = e->record_syscall[i]; } } +} + +int common_pin_map(struct bpf_map **bpf_map, const struct bpf_object *obj, const char *map_name, const char *ctrl_path) +{ + int ret; + + *bpf_map = bpf_object__find_map_by_name(obj, map_name); + if (!*bpf_map) { + fprintf(stderr, "Failed to find BPF map\n"); + return -1; + } + // 用于防止上次没有成功 unpin 掉这个 map + bpf_map__unpin(*bpf_map, ctrl_path); + ret = bpf_map__pin(*bpf_map, ctrl_path); + if (ret){ + fprintf(stderr, "Failed to pin BPF map\n"); + return -1; + } + + return 0; +} + +int update_rsc_ctrl_map(struct rsc_ctrl rsc_ctrl){ + int err,key = 0; + int srcmap_fd; + + srcmap_fd = bpf_obj_get(rsc_ctrl_path); + if (srcmap_fd < 0) { + fprintf(stderr,"Failed to open rsc_ctrl_map file\n"); + return srcmap_fd; + } + err = bpf_map_update_elem(srcmap_fd,&key,&rsc_ctrl, 0); + if(err < 0){ + fprintf(stderr, "Failed to update rsc_ctrl_map elem\n"); + return err; + } + + return 0; +} + +int update_kt_ctrl_map(struct kt_ctrl kt_ctrl){ + int err,key = 0; + int ktmap_fd; + + ktmap_fd = bpf_obj_get(kt_ctrl_path); + if (ktmap_fd < 0) { + fprintf(stderr,"Failed to open kt_ctrl_map file\n"); + return ktmap_fd; + } + err = bpf_map_update_elem(ktmap_fd,&key,&kt_ctrl, 0); + if(err < 0){ + fprintf(stderr, "Failed to update kt_ctrl_map elem\n"); + return err; + } + + return 0; +} + +int update_lock_ctrl_map(struct lock_ctrl lock_ctrl){ + int err,key = 0; + int lockmap_fd; + + lockmap_fd = bpf_obj_get(lock_ctrl_path); + if (lockmap_fd < 0) { + fprintf(stderr,"Failed to open lock_ctrl_map file\n"); + return lockmap_fd; + } + err = bpf_map_update_elem(lockmap_fd,&key,&lock_ctrl, 0); + if(err < 0){ + fprintf(stderr, "Failed to update lock_ctrl_map elem\n"); + return err; + } + + return 0; +} + +int update_sc_ctrl_map(struct sc_ctrl sc_ctrl){ + int err,key = 0; + int scmap_fd; + + scmap_fd = bpf_obj_get(sc_ctrl_path); + if (scmap_fd < 0) { + fprintf(stderr,"Failed to open sc_ctrl_map file\n"); + return scmap_fd; + } + err = bpf_map_update_elem(scmap_fd,&key,&sc_ctrl, 0); + if(err < 0){ + fprintf(stderr, "Failed to update sc_ctrl_map elem\n"); + return err; + } + + return 0; +} + +int update_sched_ctrl_map(struct sched_ctrl sched_ctrl){ + int err,key = 0; + int schedmap_fd; + + schedmap_fd = bpf_obj_get(sched_ctrl_path); + if (schedmap_fd < 0) { + fprintf(stderr,"Failed to open sched_ctrl_map file\n"); + return schedmap_fd; + } + err = bpf_map_update_elem(schedmap_fd,&key,&sched_ctrl, 0); + if(err < 0){ + fprintf(stderr, "Failed to update sched_ctrl_map elem\n"); + return err; + } + return 0; } \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/keytime_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/keytime_image.h index 45c8aa041..c1ee7e6f1 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/keytime_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/keytime_image.h @@ -17,11 +17,13 @@ // Variable definitions and help functions for keytime in the process // 记录开始时间,并输出 -static int child_create(int type, pid_t child_pid, pid_t pid, void *child, void *keytime_rb) +static int child_create(int type, pid_t child_pid, pid_t pid, void *child, void *keytime_rb, int tgid, int target_tgid) { struct child_info child_info = {}; child_info.type = type; child_info.ppid = pid; + if(target_tgid != -1) child_info.ptgid = tgid; + else child_info.ptgid = -1; if(bpf_map_update_elem(child, &child_pid, &child_info, BPF_ANY)) return 0; @@ -32,6 +34,8 @@ static int child_create(int type, pid_t child_pid, pid_t pid, void *child, void e->type = type; e->pid = pid; + if(target_tgid != -1) e->tgid = tgid; + else e->tgid = -1; e->enable_char_info = false; e->info_count = 1; e->info[0] = child_pid; @@ -54,6 +58,7 @@ static int child_exit(void *child, void *keytime_rb) e->type = child_info->type + 1; e->pid = child_info->ppid; + e->tgid = child_info->ptgid; e->enable_char_info = false; e->info_count = 1; e->info[0] = child_pid; diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lock_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lock_image.h index 036286c15..693e804e3 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lock_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lock_image.h @@ -16,12 +16,19 @@ // // Variable definitions and help functions for lock in the process -static int record_lock_enter(int target_tgid,pid_t ignore_tgid,int lock_status,int flag,void *__lock,void *lock_rb,void *proc_lock) +static int record_lock_enter(pid_t ignore_tgid,int lock_status,int flag,void *__lock,void *lock_rb,void *proc_lock,void *lock_ctrl_map) { + int key = 0; + struct lock_ctrl *lock_ctrl; + lock_ctrl = bpf_map_lookup_elem(lock_ctrl_map,&key); + if(!lock_ctrl || !lock_ctrl->lock_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((lock_ctrl->enable_myproc || tgid!=ignore_tgid) && ((lock_ctrl->target_pid==-1 && lock_ctrl->target_tgid==-1) || + (lock_ctrl->target_pid!=0 && pid==lock_ctrl->target_pid) || (lock_ctrl->target_tgid!=0 && tgid==lock_ctrl->target_tgid))){ u64 lock_ptr = (u64)__lock; struct proc_flag proc_flag = {}; @@ -37,6 +44,8 @@ static int record_lock_enter(int target_tgid,pid_t ignore_tgid,int lock_status,i e->lock_status = lock_status; e->pid = pid; + if(lock_ctrl->target_tgid != -1) e->tgid = tgid; + else e->tgid = -1; e->lock_ptr = lock_ptr; e->time = bpf_ktime_get_ns(); @@ -46,12 +55,19 @@ static int record_lock_enter(int target_tgid,pid_t ignore_tgid,int lock_status,i return 0; } -static int record_lock_exit(int target_tgid,pid_t ignore_tgid,int lock_status,int flag,int ret,void *lock_rb,void *proc_lock,void *locktype) +static int record_lock_exit(pid_t ignore_tgid,int lock_status,int flag,int ret,void *lock_rb,void *proc_lock,void *locktype,void *lock_ctrl_map) { + int key = 0; + struct lock_ctrl *lock_ctrl; + lock_ctrl = bpf_map_lookup_elem(lock_ctrl_map,&key); + if(!lock_ctrl || !lock_ctrl->lock_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((lock_ctrl->enable_myproc || tgid!=ignore_tgid) && ((lock_ctrl->target_pid==-1 && lock_ctrl->target_tgid==-1) || + (lock_ctrl->target_pid!=0 && pid==lock_ctrl->target_pid) || (lock_ctrl->target_tgid!=0 && tgid==lock_ctrl->target_tgid))){ u64 *lock_ptr; u64 temp_lock_ptr; struct proc_flag proc_flag = {}; @@ -82,6 +98,8 @@ static int record_lock_exit(int target_tgid,pid_t ignore_tgid,int lock_status,in e->lock_status = lock_status; e->pid = pid; + if(lock_ctrl->target_tgid != -1) e->tgid = tgid; + else e->tgid = -1; e->ret = ret; e->lock_ptr = temp_lock_ptr; e->time = bpf_ktime_get_ns(); @@ -92,12 +110,19 @@ static int record_lock_exit(int target_tgid,pid_t ignore_tgid,int lock_status,in return 0; } -static int record_unlock_enter(int target_tgid,pid_t ignore_tgid,int flag,void *__lock,void *proc_unlock) +static int record_unlock_enter(pid_t ignore_tgid,int flag,void *__lock,void *proc_unlock,void *lock_ctrl_map) { + int key = 0; + struct lock_ctrl *lock_ctrl; + lock_ctrl = bpf_map_lookup_elem(lock_ctrl_map,&key); + if(!lock_ctrl || !lock_ctrl->lock_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((lock_ctrl->enable_myproc || tgid!=ignore_tgid) && ((lock_ctrl->target_pid==-1 && lock_ctrl->target_tgid==-1) || + (lock_ctrl->target_pid!=0 && pid==lock_ctrl->target_pid) || (lock_ctrl->target_tgid!=0 && tgid==lock_ctrl->target_tgid))){ u64 lock_ptr = (u64)__lock; struct proc_flag proc_flag = {}; @@ -110,12 +135,19 @@ static int record_unlock_enter(int target_tgid,pid_t ignore_tgid,int flag,void * return 0; } -static int record_unlock_exit(int target_tgid,pid_t ignore_tgid,int lock_status,int flag,void *lock_rb,void *proc_unlock,void *locktype) +static int record_unlock_exit(pid_t ignore_tgid,int lock_status,int flag,void *lock_rb,void *proc_unlock,void *locktype,void *lock_ctrl_map) { + int key = 0; + struct lock_ctrl *lock_ctrl; + lock_ctrl = bpf_map_lookup_elem(lock_ctrl_map,&key); + if(!lock_ctrl || !lock_ctrl->lock_func) + return 0; + pid_t pid = bpf_get_current_pid_tgid(); int tgid = bpf_get_current_pid_tgid() >> 32; - if(tgid!=ignore_tgid && (target_tgid==-1 || (target_tgid!=-1 && tgid==target_tgid))){ + if((lock_ctrl->enable_myproc || tgid!=ignore_tgid) && ((lock_ctrl->target_pid==-1 && lock_ctrl->target_tgid==-1) || + (lock_ctrl->target_pid!=0 && pid==lock_ctrl->target_pid) || (lock_ctrl->target_tgid!=0 && tgid==lock_ctrl->target_tgid))){ u64 *lock_ptr; u64 temp_lock_ptr; struct proc_flag proc_flag = {}; @@ -148,6 +180,8 @@ static int record_unlock_exit(int target_tgid,pid_t ignore_tgid,int lock_status, e->lock_status = lock_status; e->pid = pid; + if(lock_ctrl->target_tgid != -1) e->tgid = tgid; + else e->tgid = -1; e->lock_ptr = temp_lock_ptr; e->time = bpf_ktime_get_ns(); diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h index 53575e1b3..ecfc1905f 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/proc_image.h @@ -32,6 +32,14 @@ typedef __u64 stack_trace_t[MAX_STACK_DEPTH]; // resource_image +struct rsc_ctrl{ + bool rsc_func; + pid_t target_pid; + int target_cpu_id; + bool enable_myproc; + pid_t target_tgid; +}; + struct proc_id{ int pid; int cpu_id; @@ -45,6 +53,7 @@ struct start_rsc{ struct total_rsc{ int pid; + int tgid; int cpu_id; long long unsigned int time; long unsigned int memused; @@ -53,6 +62,14 @@ struct total_rsc{ }; //syscall_image +struct sc_ctrl { + bool sc_func; + bool enable_myproc; + pid_t target_pid; + pid_t target_tgid; + int syscalls; +}; + struct syscall_seq{ int pid; int tgid; @@ -67,6 +84,13 @@ struct syscall_seq{ }; // lock_image +struct lock_ctrl{ + bool lock_func; + bool enable_myproc; + pid_t target_pid; + pid_t target_tgid; +}; + struct proc_flag{ int pid; // 1代表用户态互斥锁 @@ -84,15 +108,25 @@ struct lock_event{ */ int lock_status; int pid; + int tgid; int ret; long long unsigned int lock_ptr; long long unsigned int time; }; // keytime_image +struct kt_ctrl{ + bool kt_func; + bool kt_cpu_func; + bool enable_myproc; + pid_t target_pid; + pid_t target_tgid; +}; + struct child_info{ int type; int ppid; + int ptgid; }; struct keytime_event{ @@ -106,6 +140,7 @@ struct keytime_event{ */ int type; int pid; + int tgid; bool enable_char_info; int info_count; long long unsigned int info[6]; @@ -118,14 +153,23 @@ struct offcpu_event{ // 为固定值 11,为了标识 offCPU事件 int type; int pid; + int tgid; long long unsigned int offcpu_time; __s32 kstack_sz; stack_trace_t kstack; }; // schedule_image +struct sched_ctrl { + bool sched_func; + pid_t target_pid; + int target_cpu_id; + int target_tgid; +}; + struct schedule_event{ int pid; + int tgid; int prio; int count; long long unsigned int enter_time; diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c index 27adbea40..b52a77712 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c @@ -42,22 +42,13 @@ static int prev_image = 0; static volatile bool exiting = false; static const char object[] = "/usr/lib/x86_64-linux-gnu/libc.so.6"; static struct env { - int pid; - int tgid; int ignore_tgid; - int cpu_id; - int time; - bool enable_myproc; bool output_resourse; bool output_schedule; bool create_thread; bool exit_thread; bool enable_resource; bool first_rsc; - int syscalls; -/* int first_syscall; - int second_syscall; - int third_syscall; */ u64 sum_delay; u64 sum_count; u64 max_delay; @@ -65,28 +56,22 @@ static struct env { bool enable_hashmap; bool enable_syscall; bool enable_lock; - bool quote; int max_args; bool enable_keytime; - bool enable_cpu; int stack_count; bool enable_schedule; + int rsc_prev_tgid; + int kt_prev_tgid; + int lock_prev_tgid; + int sched_prev_tgid; + int sc_prev_tgid; } env = { - .pid = -1, - .tgid = -1, - .cpu_id = -1, - .time = 0, - .enable_myproc = false, .output_resourse = false, .output_schedule = false, .create_thread = false, .exit_thread = false, .enable_resource = false, .first_rsc = true, - .syscalls = 0, -/* .first_syscall = 0, - .second_syscall = 0, - .third_syscall = 0, */ .sum_delay = 0, .sum_count = 0, .max_delay = 0, @@ -94,16 +79,25 @@ static struct env { .enable_hashmap = false, .enable_syscall = false, .enable_lock = false, - .quote = false, .max_args = DEFAULT_MAXARGS, .enable_keytime = false, - .enable_cpu = false, .stack_count = 0, .enable_schedule = false, + .rsc_prev_tgid = 0, + .kt_prev_tgid = 0, + .lock_prev_tgid = 0, + .sched_prev_tgid = 0, + .sc_prev_tgid = 0, }; struct hashmap *map = NULL; +static int scmap_fd; +static int rscmap_fd; +static int lockmap_fd; +static int ktmap_fd; +static int schedmap_fd; + static struct timespec prevtime; static struct timespec currentime; @@ -131,100 +125,36 @@ char *task_state[] = {"TASK_RUNNING", "TASK_INTERRUPTIBLE", "TASK_UNINTERRUPTIBL const char argp_program_doc[] ="Trace process to get process image.\n"; static const struct argp_option opts[] = { - { "pid", 'p', "PID", 0, "Process ID to trace" }, - { "tgid", 'P', "TGID", 0, "Thread group to trace" }, - { "cpuid", 'c', "CPUID", 0, "Set For Tracing per-CPU Process(other processes don't need to set this parameter)" }, - { "time", 't', "TIME-SEC", 0, "Max Running Time(0 for infinite)" }, - { "myproc", 'm', NULL, 0, "Trace the process of the tool itself (not tracked by default)" }, - { "all", 'a', NULL, 0, "Start all functions(but not track tool progress)" }, - { "resource", 'r', NULL, 0, "Collects resource usage information about processes" }, - { "syscall", 's', "SYSCALLS", 0, "Collects syscall sequence (1~50) information about processes" }, - { "lock", 'l', NULL, 0, "Collects lock information about processes" }, - { "quote", 'q', NULL, 0, "Add quotemarks (\") around arguments" }, - { "keytime", 'k', "ENABLE_CPU", 0, "Collects keytime information about processes(0:except CPU kt_info,1:all kt_info)" }, - { "schedule", 'S', NULL, 0, "Collects schedule information about processes (trace tool process)" }, + { "all", 'a', NULL, 0, "Attach all eBPF functions(but do not start)" }, + { "resource", 'r', NULL, 0, "Attach eBPF functions about resource usage(but do not start)" }, + { "syscall", 's', NULL, 0, "Attach eBPF functions about syscall sequence(but do not start)" }, + { "lock", 'l', NULL, 0, "Attach eBPF functions about lock(but do not start)" }, + { "keytime", 'k', NULL, 0, "Attach eBPF functions about keytime(but do not start)" }, + { "schedule", 'S', NULL, 0, "Attach eBPF functions about schedule (but do not start)" }, { NULL, 'h', NULL, OPTION_HIDDEN, "show the full help" }, {}, }; static error_t parse_arg(int key, char *arg, struct argp_state *state) { - long pid; - long tgid; - long cpu_id; - long syscalls; - long enable_cpu; switch (key) { - case 'p': - errno = 0; - pid = strtol(arg, NULL, 10); - if (errno || pid < 0) { - warn("Invalid PID: %s\n", arg); - // 调用argp_usage函数,用于打印用法信息并退出程序 - argp_usage(state); - } - env.pid = pid; - break; - case 'P': - errno = 0; - tgid = strtol(arg, NULL, 10); - if (errno || tgid < 0) { - warn("Invalid TGID: %s\n", arg); - // 调用argp_usage函数,用于打印用法信息并退出程序 - argp_usage(state); - } - env.tgid = tgid; - break; - case 'c': - cpu_id = strtol(arg, NULL, 10); - if(cpu_id < 0){ - warn("Invalid CPUID: %s\n", arg); - argp_usage(state); - } - env.cpu_id = cpu_id; - break; - case 't': - env.time = strtol(arg, NULL, 10); - if(env.time) alarm(env.time); - break; - case 'm': - env.enable_myproc = true; - break; case 'a': env.enable_resource = true; - env.syscalls = 10; env.enable_syscall = true; env.enable_lock = true; env.enable_keytime = true; - env.enable_cpu = true; env.enable_schedule = true; break; case 'r': env.enable_resource = true; break; case 's': - syscalls = strtol(arg, NULL, 10); - if(syscalls<=0 && syscalls>50){ - warn("Invalid SYSCALLS: %s\n", arg); - argp_usage(state); - } - env.syscalls = syscalls; env.enable_syscall = true; break; case 'l': env.enable_lock = true; break; - case 'q': - env.quote = true; - break; case 'k': - errno = 0; - enable_cpu = strtol(arg, NULL, 10); - if(errno || (enable_cpu<0 && enable_cpu>1)){ - warn("Invalid KEYTIME: %s\n", arg); - argp_usage(state); - } - env.enable_cpu = enable_cpu; env.enable_keytime = true; break; case 'S': @@ -240,16 +170,25 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) return 0; } -static int print_resource(struct bpf_map *map) +static int print_resource(struct bpf_map *map,int rscmap_fd) { - struct proc_id lookup_key = {-1}, next_key; - int err, fd = bpf_map__fd(map); + int err,key = 0; + struct rsc_ctrl rsc_ctrl ={}; + err = bpf_map_lookup_elem(rscmap_fd,&key,&rsc_ctrl); + if (err < 0) { + fprintf(stderr, "failed to lookup infos: %d\n", err); + return -1; + } + if(!rsc_ctrl.rsc_func) + return 0; if(env.first_rsc){ env.first_rsc = false; goto delete_elem; } - + + struct proc_id lookup_key = {-1,-1}, next_key; + int fd = bpf_map__fd(map); struct total_rsc event; float pcpu,pmem; double read_rate,write_rate; @@ -260,16 +199,25 @@ static int print_resource(struct bpf_map *map) int min = localTime->tm_min; int sec = localTime->tm_sec; long long unsigned int interval; + int rsc_cur_tgid = 0; + + if(rsc_ctrl.target_tgid != -1) rsc_cur_tgid = 2; + else rsc_cur_tgid = 1; while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { - if(prev_image != RESOURCE_IMAGE){ + if(prev_image != RESOURCE_IMAGE || env.rsc_prev_tgid != rsc_cur_tgid){ printf("RESOURCE ------------------------------------------------------------------------------------------------\n"); printf("%-8s ","TIME"); - if(env.tgid != -1) printf("%-6s ","TGID"); + if(rsc_ctrl.target_tgid != -1){ + printf("%-6s ","TGID"); + env.rsc_prev_tgid = 2; + }else{ + env.rsc_prev_tgid = 1; + } printf("%-6s %-6s %-6s %-6s %-12s %-12s\n","PID","CPU-ID","CPU(%)","MEM(%)","READ(kb/s)","WRITE(kb/s)"); prev_image = RESOURCE_IMAGE; } - + err = bpf_map_lookup_elem(fd, &next_key, &event); if (err < 0) { fprintf(stderr, "failed to lookup infos: %d\n", err); @@ -290,7 +238,7 @@ static int print_resource(struct bpf_map *map) if(pcpu<=100 && pmem<=100){ printf("%02d:%02d:%02d ",hour,min,sec); - if(env.tgid != -1) printf("%-6d ",env.tgid); + if(rsc_ctrl.target_tgid != -1) printf("%-6d ",event.tgid); printf("%-6d %-6d %-6.3f %-6.3f %-12.2lf %-12.2lf\n", event.pid,event.cpu_id,pcpu,pmem,read_rate,write_rate); } @@ -318,11 +266,20 @@ static int print_resource(struct bpf_map *map) return 0; } -static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,struct bpf_map *tg_map,struct bpf_map *sys_map) +static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,struct bpf_map *tg_map,struct bpf_map *sys_map,int schedmap_fd) { + int err,key = 0; + struct sched_ctrl sched_ctrl ={}; + + err = bpf_map_lookup_elem(schedmap_fd,&key,&sched_ctrl); + if (err < 0) { + fprintf(stderr, "failed to lookup infos: %d\n", err); + return -1; + } + if(!sched_ctrl.sched_func) return 0; + struct proc_id lookup_key = {-1}, next_key; int l_key = -1, n_key; - int err; int proc_fd = bpf_map__fd(proc_map); int target_fd = bpf_map__fd(target_map); int tg_fd = bpf_map__fd(tg_map); @@ -337,17 +294,25 @@ static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,st u64 proc_avg_delay; u64 target_avg_delay; u64 sys_avg_delay; - int key = 0; + int sched_cur_tgid = 0; - if(prev_image != SCHEDULE_IMAGE){ + if(sched_ctrl.target_tgid != -1) sched_cur_tgid = 2; + else sched_cur_tgid = 1; + + if(prev_image != SCHEDULE_IMAGE || env.sched_prev_tgid != sched_cur_tgid){ printf("SCHEDULE ----------------------------------------------------------------------------------------------------------------------\n"); printf("%-8s ","TIME"); - if(env.tgid != -1) printf("%-6s ","TGID"); + if(sched_ctrl.target_tgid != -1){ + printf("%-6s ","TGID"); + env.sched_prev_tgid = 2; + }else{ + env.sched_prev_tgid = 1; + } printf("%-6s %-4s %s\n","PID","PRIO","| P_AVG_DELAY(ms) S_AVG_DELAY(ms) | P_MAX_DELAY(ms) S_MAX_DELAY(ms) | P_MIN_DELAY(ms) S_MIN_DELAY(ms) |"); prev_image = SCHEDULE_IMAGE; } - if(env.pid==-1 && env.tgid==-1){ + if(sched_ctrl.target_pid==-1 && sched_ctrl.target_tgid==-1){ while (!bpf_map_get_next_key(proc_fd, &lookup_key, &next_key)) { err = bpf_map_lookup_elem(proc_fd, &next_key, &proc_event); if (err < 0) { @@ -369,7 +334,7 @@ static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,st lookup_key = next_key; } - }else if(env.pid!=-1 && env.tgid==-1){ + }else if(sched_ctrl.target_pid!=-1 && sched_ctrl.target_tgid==-1){ err = bpf_map_lookup_elem(target_fd, &key, &proc_event); if (err < 0) { fprintf(stderr, "failed to lookup infos: %d\n", err); @@ -390,7 +355,7 @@ static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,st hour,min,sec,proc_event.pid,proc_event.prio,target_avg_delay/1000000.0,sys_avg_delay/1000000.0, proc_event.max_delay/1000000.0,sys_event.max_delay/1000000.0,proc_event.min_delay/1000000.0,sys_event.min_delay/1000000.0); } - }else if(env.pid==-1 && env.tgid!=-1){ + }else if(sched_ctrl.target_pid==-1 && sched_ctrl.target_tgid!=-1){ while (!bpf_map_get_next_key(tg_fd, &l_key, &n_key)) { err = bpf_map_lookup_elem(tg_fd, &n_key, &proc_event); if (err < 0) { @@ -407,7 +372,7 @@ static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,st sys_avg_delay = sys_event.sum_delay/sys_event.sum_count; printf("%02d:%02d:%02d %-6d %-6d %-4d | %-15lf %-15lf | %-15lf %-15lf | %-15lf %-15lf |\n", - hour,min,sec,env.tgid,proc_event.pid,proc_event.prio,proc_avg_delay/1000000.0,sys_avg_delay/1000000.0, + hour,min,sec,proc_event.tgid,proc_event.pid,proc_event.prio,proc_avg_delay/1000000.0,sys_avg_delay/1000000.0, proc_event.max_delay/1000000.0,sys_event.max_delay/1000000.0,proc_event.min_delay/1000000.0,sys_event.min_delay/1000000.0); l_key = n_key; @@ -421,6 +386,16 @@ static int print_schedule(struct bpf_map *proc_map,struct bpf_map *target_map,st static int print_syscall(void *ctx, void *data,unsigned long data_sz) { + int err,key = 0; + struct sc_ctrl sc_ctrl ={}; + + err = bpf_map_lookup_elem(scmap_fd,&key,&sc_ctrl); + if (err < 0) { + fprintf(stderr, "failed to lookup infos: %d\n", err); + return -1; + } + if(!sc_ctrl.sc_func) return 0; + const struct syscall_seq *e = data; u64 avg_delay; time_t now = time(NULL); @@ -428,11 +403,20 @@ static int print_syscall(void *ctx, void *data,unsigned long data_sz) int hour = localTime->tm_hour; int min = localTime->tm_min; int sec = localTime->tm_sec; + int sc_cur_tgid = 0; - if(prev_image != SYSCALL_IMAGE){ + if(sc_ctrl.target_tgid != -1) sc_cur_tgid = 2; + else sc_cur_tgid = 1; + + if(prev_image != SYSCALL_IMAGE || env.sc_prev_tgid != sc_cur_tgid){ printf("SYSCALL ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"); printf("%-8s ","TIME"); - if(env.tgid != -1) printf("%-6s ","TGID"); + if(sc_ctrl.target_tgid != -1){ + printf("%-6s ","TGID"); + env.sc_prev_tgid = 2; + }else{ + env.sc_prev_tgid = 1; + } printf("%-6s %-14s %-14s %-14s %-103s %-8s\n", "PID","1st/num","2nd/num","3nd/num","| P_AVG_DELAY(ns) S_AVG_DELAY(ns) | P_MAX_DELAY(ns) S_MAX_DELAY(ns) | P_MIN_DELAY(ns) S_MIN_DELAY(ns) |","SYSCALLS"); @@ -455,9 +439,9 @@ static int print_syscall(void *ctx, void *data,unsigned long data_sz) env.enable_hashmap = true; } - if((env.pid==-1 && env.tgid==-1) || e->pid==env.pid || e->tgid==env.tgid){ + if((sc_ctrl.target_pid==-1 && sc_ctrl.target_tgid==-1) || e->pid==sc_ctrl.target_pid || e->tgid==sc_ctrl.target_tgid){ printf("%02d:%02d:%02d ",hour,min,sec); - if(env.tgid != -1) printf("%-6d ",env.tgid); + if(sc_ctrl.target_tgid != -1) printf("%-6d ",e->tgid); printf("%-6d ",e->pid); struct syscall_hash *syscall_hash = (struct syscall_hash *)hashmap_get(map,&(struct syscall_hash){.key=e->pid}); @@ -495,17 +479,26 @@ static int print_syscall(void *ctx, void *data,unsigned long data_sz) static int print_lock(void *ctx, void *data,unsigned long data_sz) { const struct lock_event *e = data; + int lock_cur_tgid = 0; + + if(e->tgid != -1) lock_cur_tgid = 2; + else lock_cur_tgid = 1; - if(prev_image != LOCK_IMAGE){ + if(prev_image != LOCK_IMAGE || env.lock_prev_tgid != lock_cur_tgid){ printf("USERLOCK ------------------------------------------------------------------------------------------------\n"); printf("%-15s ","TIME"); - if(env.tgid != -1) printf("%-6s ","TGID"); + if(e->tgid != -1){ + printf("%-6s ","TGID"); + env.lock_prev_tgid = 2; + } else { + env.lock_prev_tgid = 1; + } printf("%-6s %-15s %s\n","PID","LockAddr","LockStatus"); prev_image = LOCK_IMAGE; } printf("%-15lld ",e->time); - if(env.tgid != -1) printf("%-6d ",env.tgid); + if(e->tgid != -1) printf("%-6d ",e->tgid); printf("%-6d %-15lld ",e->pid,e->lock_ptr); if(e->lock_status==2 || e->lock_status==5 || e->lock_status==8 || e->lock_status==11){ printf("%s-%d\n",lock_status[e->lock_status],e->ret); @@ -540,30 +533,13 @@ static void print_info1(const struct keytime_event *e) { int i, args_counter = 0; - if (env.quote) - putchar('"'); - for (i = 0; i < e->info_size && args_counter < e->info_count; i++) { char c = e->char_info[i]; - - if (env.quote) { - if (c == '\0') { - args_counter++; - putchar('"'); - putchar(' '); - if (args_counter < e->info_count) { - putchar('"'); - } - } else { - quoted_symbol(c); - } + if (c == '\0') { + args_counter++; + putchar(' '); } else { - if (c == '\0') { - args_counter++; - putchar(' '); - } else { - putchar(c); - } + putchar(c); } } if (e->info_count == env.max_args + 1) { @@ -576,11 +552,7 @@ static void print_info2(const struct keytime_event *e) int i=0; for(int tmp=e->info_count; tmp>0 ; tmp--){ - if(env.quote){ - printf("\"%llu\" ",e->info[i++]); - }else{ - printf("%llu ",e->info[i++]); - } + printf("%llu ",e->info[i++]); } } @@ -605,22 +577,31 @@ static int print_keytime(void *ctx, void *data,unsigned long data_sz) int hour = localTime->tm_hour; int min = localTime->tm_min; int sec = localTime->tm_sec; + int kt_cur_tgid = 0; + + if(e->tgid != -1) kt_cur_tgid = 2; + else kt_cur_tgid = 1; if(e->type == 11){ is_offcpu = true; } - if(prev_image != KEYTIME_IMAGE){ + if(prev_image != KEYTIME_IMAGE || env.kt_prev_tgid != kt_cur_tgid){ printf("KEYTIME -------------------------------------------------------------------------------------------------\n"); printf("%-8s ","TIME"); - if(env.tgid != -1) printf("%-6s ","TGID"); + if(e->tgid != -1){ + printf("%-6s ","TGID"); + env.kt_prev_tgid = 2; + } else { + env.kt_prev_tgid = 1; + } printf("%-6s %-15s %s\n","PID","EVENT","ARGS/RET/OTHERS"); prev_image = KEYTIME_IMAGE; } printf("%02d:%02d:%02d ",hour,min,sec); - if(env.tgid != -1) printf("%-6d ",env.tgid); + if(e->tgid != -1) printf("%-6d ",e->tgid); if(!is_offcpu){ printf("%-6d %-15s ",e->pid,keytime_type[e->type]); if(e->type==4 || e->type==5 || e->type==6 || e->type==7 || e->type==8 || e->type==9){ @@ -642,7 +623,7 @@ static int print_keytime(void *ctx, void *data,unsigned long data_sz) if(env.stack_count < 100){ FILE *file = fopen("./.output/data/offcpu_stack.txt", "a"); fprintf(file, "TIME:%02d:%02d:%02d ", hour,min,sec); - if(env.tgid != -1) fprintf(file, "TGID:%-6d ",env.tgid); + if(offcpu_event->tgid != -1) fprintf(file, "TGID:%-6d ",offcpu_event->tgid); fprintf(file, "PID:%-6d OFFCPU_TIME:%llu\n",offcpu_event->pid,offcpu_event->offcpu_time); for(int i=0 ; ikstack[i],file); @@ -653,7 +634,7 @@ static int print_keytime(void *ctx, void *data,unsigned long data_sz) }else{ FILE *file = fopen("./.output/data/offcpu_stack.txt", "w"); fprintf(file, "TIME:%02d:%02d:%02d ", hour,min,sec); - if(env.tgid != -1) fprintf(file, "TGID:%-6d ",env.tgid); + if(offcpu_event->tgid != -1) fprintf(file, "TGID:%-6d ",offcpu_event->tgid); fprintf(file, "PID:%-6d OFFCPU_TIME:%llu\n",offcpu_event->pid,offcpu_event->offcpu_time); for(int i=0 ; ikstack[i],file); @@ -745,14 +726,20 @@ static void sig_handler(int signo) int main(int argc, char **argv) { struct resource_image_bpf *resource_skel = NULL; + struct bpf_map *rsc_ctrl_map = NULL; struct syscall_image_bpf *syscall_skel = NULL; struct ring_buffer *syscall_rb = NULL; + struct bpf_map *sc_ctrl_map = NULL; struct lock_image_bpf *lock_skel = NULL; struct ring_buffer *lock_rb = NULL; + struct bpf_map *lock_ctrl_map = NULL; struct keytime_image_bpf *keytime_skel = NULL; struct ring_buffer *keytime_rb = NULL; + struct bpf_map *kt_ctrl_map = NULL; struct schedule_image_bpf *schedule_skel = NULL; + struct bpf_map *sched_ctrl_map = NULL; pthread_t thread_enable; + int key = 0; int err; static const struct argp argp = { .options = opts, @@ -770,7 +757,8 @@ int main(int argc, char **argv) /* 设置libbpf错误和调试信息回调 */ libbpf_set_print(libbpf_print_fn); - signal(SIGALRM,sig_handler); + signal(SIGINT, sig_handler); + //signal(SIGTERM, sig_handler); if(env.enable_resource){ resource_skel = resource_image_bpf__open(); @@ -779,10 +767,7 @@ int main(int argc, char **argv) return 1; } - resource_skel->rodata->target_pid = env.pid; - resource_skel->rodata->target_cpu_id = env.cpu_id; - if(!env.enable_myproc) resource_skel->rodata->ignore_tgid = env.ignore_tgid; - resource_skel->rodata->target_tgid = env.tgid; + resource_skel->rodata->ignore_tgid = env.ignore_tgid; err = resource_image_bpf__load(resource_skel); if (err) { @@ -790,6 +775,18 @@ int main(int argc, char **argv) goto cleanup; } + err = common_pin_map(&rsc_ctrl_map,resource_skel->obj,"rsc_ctrl_map",rsc_ctrl_path); + if(err < 0){ + goto cleanup; + } + rscmap_fd = bpf_map__fd(rsc_ctrl_map); + struct rsc_ctrl init_value= {false,-1,-1,false,-1}; + err = bpf_map_update_elem(rscmap_fd, &key, &init_value, 0); + if(err < 0){ + fprintf(stderr, "Failed to update elem\n"); + goto cleanup; + } + err = resource_image_bpf__attach(resource_skel); if (err) { fprintf(stderr, "Failed to attach BPF resource skeleton\n"); @@ -804,10 +801,7 @@ int main(int argc, char **argv) return 1; } - syscall_skel->rodata->target_pid = env.pid; - syscall_skel->rodata->target_tgid = env.tgid; - syscall_skel->rodata->syscalls = env.syscalls; - if(!env.enable_myproc) syscall_skel->rodata->ignore_tgid = env.ignore_tgid; + syscall_skel->rodata->ignore_tgid = env.ignore_tgid; err = syscall_image_bpf__load(syscall_skel); if (err) { @@ -815,6 +809,18 @@ int main(int argc, char **argv) goto cleanup; } + err = common_pin_map(&sc_ctrl_map,syscall_skel->obj,"sc_ctrl_map",sc_ctrl_path); + if(err < 0){ + goto cleanup; + } + scmap_fd = bpf_map__fd(sc_ctrl_map); + struct sc_ctrl init_value= {false,false,-1,-1,0}; + err = bpf_map_update_elem(scmap_fd, &key, &init_value, 0); + if(err < 0){ + fprintf(stderr, "Failed to update elem\n"); + goto cleanup; + } + err = syscall_image_bpf__attach(syscall_skel); if (err) { fprintf(stderr, "Failed to attach BPF syscall skeleton\n"); @@ -838,8 +844,7 @@ int main(int argc, char **argv) return 1; } - if(!env.enable_myproc) lock_skel->rodata->ignore_tgid = env.ignore_tgid; - lock_skel->rodata->target_tgid = env.tgid; + lock_skel->rodata->ignore_tgid = env.ignore_tgid; err = lock_image_bpf__load(lock_skel); if (err) { @@ -847,6 +852,18 @@ int main(int argc, char **argv) goto cleanup; } + err = common_pin_map(&lock_ctrl_map,lock_skel->obj,"lock_ctrl_map",lock_ctrl_path); + if(err < 0){ + goto cleanup; + } + lockmap_fd = bpf_map__fd(lock_ctrl_map); + struct lock_ctrl init_value = {false,false,-1,-1}; + err = bpf_map_update_elem(lockmap_fd, &key, &init_value, 0); + if(err < 0){ + fprintf(stderr, "Failed to update elem\n"); + goto cleanup; + } + /* 附加跟踪点处理程序 */ err = lock_attach(lock_skel); if (err) { @@ -871,10 +888,7 @@ int main(int argc, char **argv) return 1; } - keytime_skel->rodata->target_pid = env.pid; - if(!env.enable_myproc) keytime_skel->rodata->ignore_tgid = env.ignore_tgid; - keytime_skel->rodata->target_tgid = env.tgid; - keytime_skel->rodata->enable_cpu = env.enable_cpu; + keytime_skel->rodata->ignore_tgid = env.ignore_tgid; err = keytime_image_bpf__load(keytime_skel); if (err) { @@ -887,6 +901,18 @@ int main(int argc, char **argv) fprintf(stderr, "failed to load kallsyms\n"); goto cleanup; } + + err = common_pin_map(&kt_ctrl_map,keytime_skel->obj,"kt_ctrl_map",kt_ctrl_path); + if(err < 0){ + goto cleanup; + } + ktmap_fd = bpf_map__fd(kt_ctrl_map); + struct kt_ctrl init_value = {false,false,false,-1,-1}; + err = bpf_map_update_elem(ktmap_fd, &key, &init_value, 0); + if(err < 0){ + fprintf(stderr, "Failed to update elem\n"); + goto cleanup; + } /* 附加跟踪点处理程序 */ err = keytime_attach(keytime_skel); @@ -912,16 +938,24 @@ int main(int argc, char **argv) return 1; } - schedule_skel->rodata->target_pid = env.pid; - schedule_skel->rodata->target_tgid = env.tgid; - schedule_skel->rodata->target_cpu_id = env.cpu_id; - err = schedule_image_bpf__load(schedule_skel); if (err) { fprintf(stderr, "Failed to load and verify BPF schedule skeleton\n"); goto cleanup; } + err = common_pin_map(&sched_ctrl_map,schedule_skel->obj,"sched_ctrl_map",sched_ctrl_path); + if(err < 0){ + goto cleanup; + } + schedmap_fd = bpf_map__fd(sched_ctrl_map); + struct sched_ctrl init_value= {false,-1,-1,-1}; + err = bpf_map_update_elem(schedmap_fd, &key, &init_value, 0); + if(err < 0){ + fprintf(stderr, "Failed to update elem\n"); + goto cleanup; + } + err = schedule_image_bpf__attach(schedule_skel); if (err) { fprintf(stderr, "Failed to attach BPF schedule skeleton\n"); @@ -951,7 +985,7 @@ int main(int argc, char **argv) } if(env.enable_resource && env.output_resourse){ - err = print_resource(resource_skel->maps.total); + err = print_resource(resource_skel->maps.total,rscmap_fd); /* Ctrl-C will cause -EINTR */ if (err == -EINTR) { err = 0; @@ -1003,7 +1037,7 @@ int main(int argc, char **argv) if(env.enable_schedule && env.output_schedule){ err = print_schedule(schedule_skel->maps.proc_schedule,schedule_skel->maps.target_schedule, - schedule_skel->maps.tg_schedule,schedule_skel->maps.sys_schedule); + schedule_skel->maps.tg_schedule,schedule_skel->maps.sys_schedule,schedmap_fd); /* Ctrl-C will cause -EINTR */ if (err == -EINTR) { err = 0; @@ -1017,16 +1051,31 @@ int main(int argc, char **argv) /* 卸载BPF程序 */ cleanup: - resource_image_bpf__destroy(resource_skel); - ring_buffer__free(syscall_rb); - syscall_image_bpf__destroy(syscall_skel); - ring_buffer__free(lock_rb); - lock_image_bpf__destroy(lock_skel); - ring_buffer__free(keytime_rb); - keytime_image_bpf__destroy(keytime_skel); - schedule_image_bpf__destroy(schedule_skel); - hashmap_free(map); - ksyms__free(ksyms); + if(env.enable_resource){ + bpf_map__unpin(rsc_ctrl_map, rsc_ctrl_path); + resource_image_bpf__destroy(resource_skel); + } + if(env.enable_syscall){ + bpf_map__unpin(sc_ctrl_map, sc_ctrl_path); + ring_buffer__free(syscall_rb); + hashmap_free(map); + syscall_image_bpf__destroy(syscall_skel); + } + if(env.enable_lock){ + bpf_map__unpin(lock_ctrl_map, lock_ctrl_path); + ring_buffer__free(lock_rb); + lock_image_bpf__destroy(lock_skel); + } + if(env.enable_keytime){ + bpf_map__unpin(kt_ctrl_map, kt_ctrl_path); + ksyms__free(ksyms); + ring_buffer__free(keytime_rb); + keytime_image_bpf__destroy(keytime_skel); + } + if(env.enable_schedule){ + bpf_map__unpin(sched_ctrl_map, sched_ctrl_path); + schedule_image_bpf__destroy(schedule_skel); + } return err < 0 ? -err : 0; } \ No newline at end of file diff --git a/eBPF_Visualization/eBPF_prometheus/Makefile b/eBPF_Visualization/eBPF_prometheus/Makefile index 763e16961..a0f985b7a 100644 --- a/eBPF_Visualization/eBPF_prometheus/Makefile +++ b/eBPF_Visualization/eBPF_prometheus/Makefile @@ -2,9 +2,11 @@ Prometheus_image = prom/prometheus all: go mod tidy go build -o data-visual ./main.go + @mkdir -p ./.output/data + @touch ./.output/data/offcpu_stack.txt start_service: ./runimages.sh clean_data: - rm ./dao/data.db + rm -rf ./dao/data.db ./.output/data