From 5ca8724c0754e08d8c3f7cc45895072074396328 Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Sun, 10 Dec 2023 16:38:00 +0800 Subject: [PATCH 1/7] md syscall --- .../eBPF_proc_image/developing/Makefile | 2 +- .../developing/bpf/syscall_image.bpf.c | 30 +++++--- .../developing/include/proc_image.h | 4 +- .../eBPF_proc_image/developing/proc_image.c | 68 ++++++++----------- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile index 9045bae0b..7ec9847d9 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile @@ -41,7 +41,7 @@ INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(LIBBLAZESYM_INC) -I./inc CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) -APPS = resource_image lock_image #syscall_image +APPS = resource_image lock_image syscall_image TARGETS = proc_image # Get Clang's default includes on this system. We'll explicitly add these dirs diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/syscall_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/syscall_image.bpf.c index fc21c8edb..f157b1afc 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/syscall_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/syscall_image.bpf.c @@ -34,10 +34,9 @@ struct { } proc_syscall SEC(".maps"); struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u32)); -} syscalls SEC(".maps"); + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries,256 * 10240); +} syscall_rb SEC(".maps"); // 记录进程的系统调用序列 SEC("tracepoint/raw_syscalls/sys_enter") @@ -53,11 +52,10 @@ int sys_enter(struct trace_event_raw_sys_enter *args) return 0; } - if(syscall_seq->count < MAX_SYSCALL_COUNT-1 && syscall_seq->count >= 0){ - if((syscall_seq->record_syscall+syscall_seq->count) <= (syscall_seq->record_syscall+MAX_SYSCALL_COUNT)){ - syscall_seq->record_syscall[syscall_seq->count] = args->id; + 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){ + syscall_seq->record_syscall[syscall_seq->count] = (int)args->id; syscall_seq->count ++; - } }else if(syscall_seq->count == MAX_SYSCALL_COUNT-1){ syscall_seq->record_syscall[syscall_seq->count] = -1; syscall_seq->count = MAX_SYSCALL_COUNT; @@ -82,9 +80,19 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s prev_syscall_seq = bpf_map_lookup_elem(&proc_syscall, &prev_pid); if(prev_syscall_seq){ - prev_syscall_seq->offcpu_time = current_time; - - bpf_perf_event_output(ctx, &syscalls, BPF_F_CURRENT_CPU, prev_syscall_seq, sizeof(*prev_syscall_seq)); + struct syscall_seq* e; + e = bpf_ringbuf_reserve(&syscall_rb, sizeof(*e), 0); + if(!e) + return 0; + + e->pid = prev_syscall_seq->pid; + e->oncpu_time = prev_syscall_seq->oncpu_time; + e->offcpu_time = current_time; + e->count = prev_syscall_seq->count; + for(int i=0; i<=prev_syscall_seq->count && i<=MAX_SYSCALL_COUNT-1; i++) + e->record_syscall[i] = prev_syscall_seq->record_syscall[i]; + + bpf_ringbuf_submit(e, 0); bpf_map_delete_elem(&proc_syscall, &prev_pid); } } diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h index dc7e60ffa..8e3eb6359 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h @@ -19,7 +19,7 @@ #ifndef __PROC_IMAGE_H #define __PROC_IMAGE_H -#define MAX_SYSCALL_COUNT 58 +#define MAX_SYSCALL_COUNT 116 // resource_image struct proc_id{ @@ -48,7 +48,7 @@ struct syscall_seq{ long long unsigned int oncpu_time; long long unsigned int offcpu_time; int count; // 若count值超过MAX_SYSCALL_COUNT,则record_syscall数组最后一个元素的值用-1表示以作说明 - long int record_syscall[MAX_SYSCALL_COUNT]; + int record_syscall[MAX_SYSCALL_COUNT]; }; // lock_image diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c index dc6280d6d..155781730 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c @@ -30,9 +30,7 @@ #include #include "proc_image.h" #include "resource_image.skel.h" -/* #include "syscall_image.skel.h" -*/ #include "lock_image.skel.h" #define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ @@ -100,7 +98,7 @@ static struct env { bool exit_thread; bool enable_resource; bool first_rsc; -// bool enable_syscall; + bool enable_syscall; bool enable_lock; } env = { .pid = -1, @@ -111,7 +109,7 @@ static struct env { .exit_thread = false, .enable_resource = false, .first_rsc = true, -// .enable_syscall = false, + .enable_syscall = false, .enable_lock = false, }; @@ -165,15 +163,15 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) break; case 'a': env.enable_resource = true; -// env.enable_syscall = true; + env.enable_syscall = true; env.enable_lock = true; break; case 'r': env.enable_resource = true; break; -/* case 's': + case 's': env.enable_syscall = true; - break;*/ + break; case 'l': env.enable_lock = true; break; @@ -261,13 +259,12 @@ static int print_resource(struct bpf_map *map) return 0; } -/* -static void print_syscall(void *ctx, int cpu, void *data, __u32 data_sz) +static int print_syscall(void *ctx, void *data,unsigned long data_sz) { const struct syscall_seq *e = data; int count = e->count; - if(count == 0) return; + if(count == 0) return 0; if(prev_image != SYSCALL_IMAGE){ printf("SYSCALL------------------------------------------------------------\n"); @@ -278,18 +275,14 @@ static void print_syscall(void *ctx, int cpu, void *data, __u32 data_sz) printf("%-14lld-%14lld %-6d ",e->oncpu_time,e->offcpu_time,e->pid); for(int i=0; irecord_syscall[i]); - else printf("%ld,",e->record_syscall[i]); + if(i == count-1) printf("%d",e->record_syscall[i]); + else printf("%d,",e->record_syscall[i]); } putchar('\n'); -} -static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt) -{ - fprintf(stderr, "Lost %llu events on CPU #%d!\n", lost_cnt, cpu); + return 0; } -*/ static int print_lock(void *ctx, void *data,unsigned long data_sz) { @@ -365,12 +358,10 @@ static void sig_handler(int signo) int main(int argc, char **argv) { struct resource_image_bpf *resource_skel; -/* struct syscall_image_bpf *syscall_skel; - struct perf_buffer *syscall_pb = NULL; -*/ - struct ring_buffer *lock_rb = NULL; + struct ring_buffer *syscall_rb = NULL; struct lock_image_bpf *lock_skel; + struct ring_buffer *lock_rb = NULL; pthread_t thread_enable; int err; static const struct argp argp = { @@ -413,7 +404,7 @@ int main(int argc, char **argv) } -/* + if(env.enable_syscall){ syscall_skel = syscall_image_bpf__open(); if(!syscall_skel) { @@ -435,15 +426,15 @@ int main(int argc, char **argv) goto cleanup; } - syscall_pb = perf_buffer__new(bpf_map__fd(syscall_skel->maps.syscalls), PERF_BUFFER_PAGES, - print_syscall, handle_lost_events, NULL, NULL); - if (!syscall_pb) { - err = -errno; - fprintf(stderr, "failed to open syscall perf buffer: %d\n", err); + /* 设置环形缓冲区轮询 */ + //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 + syscall_rb = ring_buffer__new(bpf_map__fd(syscall_skel->maps.syscall_rb), print_syscall, NULL, NULL); + if (!syscall_rb) { + err = -1; + fprintf(stderr, "Failed to create syscall ring buffer\n"); goto cleanup; } } -*/ if(env.enable_lock){ lock_skel = lock_image_bpf__open(); @@ -506,16 +497,19 @@ int main(int argc, char **argv) } } -/* if(env.enable_syscall){ - err = perf_buffer__poll(syscall_pb, 0); - if (err < 0 && err != -EINTR) { - fprintf(stderr, "error polling syscall perf buffer: %s\n", strerror(-err)); - goto cleanup; + err = ring_buffer__poll(syscall_rb, 0); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + printf("Error polling syscall ring buffer: %d\n", err); + break; } - err = 0; } -*/ + if(env.enable_lock){ err = ring_buffer__poll(lock_rb, 0); /* Ctrl-C will cause -EINTR */ @@ -533,10 +527,8 @@ int main(int argc, char **argv) /* 卸载BPF程序 */ cleanup: resource_image_bpf__destroy(resource_skel); -/* - perf_buffer__free(syscall_pb); + ring_buffer__free(syscall_rb); syscall_image_bpf__destroy(syscall_skel); -*/ ring_buffer__free(lock_rb); lock_image_bpf__destroy(lock_skel); From fd143e02f25ff71e681fad208cbb4a711d6eabe0 Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Mon, 11 Dec 2023 20:04:30 +0800 Subject: [PATCH 2/7] add exec --- .../eBPF_proc_image/developing/Makefile | 2 +- .../developing/bpf/keytime_image.bpf.c | 115 ++++++++++++ .../developing/include/keytime_image.h | 17 ++ .../developing/include/proc_image.h | 26 +++ .../eBPF_proc_image/developing/proc_image.c | 167 ++++++++++++++++++ 5 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c create mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile index 7ec9847d9..49f760d80 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile @@ -41,7 +41,7 @@ INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(LIBBLAZESYM_INC) -I./inc CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) -APPS = resource_image lock_image syscall_image +APPS = resource_image lock_image syscall_image keytime_image TARGETS = proc_image # Get Clang's default includes on this system. We'll explicitly add these dirs diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c new file mode 100644 index 000000000..80d3420ed --- /dev/null +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c @@ -0,0 +1,115 @@ +// 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 +// +// eBPF kernel-mode code that collects process key time information + +#include +#include +#include +#include +#include "proc_image.h" + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +const volatile int max_args = DEFAULT_MAXARGS; + +const volatile pid_t target_pid = -1; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10240); + __type(key, pid_t); + __type(value, struct keytime_event); +} keytime SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries,256 * 10240); +} keytime_rb SEC(".maps"); + +SEC("tracepoint/syscalls/sys_enter_execve") +int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx) +{ + struct task_struct *task = (struct task_struct *)bpf_get_current_task(); + int pid = BPF_CORE_READ(task,pid); + if(target_pid==-1 || pid==target_pid){ + struct keytime_event* event; + event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); + if(!event) + return 0; + + int ret; + int i; + const char **args = (const char **)(ctx->args[1]); + const char *argp; + + event->type = 1; + event->pid = pid; + event->count = 0; + event->args_size = 0; + event->enable_char_args = true; + + ret = bpf_probe_read_user_str(event->args, ARGSIZE, (const char*)ctx->args[0]); + if (ret < 0) { + bpf_ringbuf_submit(event, 0); + return 0; + } + if (ret <= ARGSIZE) { + event->args_size += ret; + } else { + /* 写一个空字符串 */ + event->args[0] = '\0'; + event->args_size++; + } + + event->count++; + #pragma unroll + for (i = 1; i < TOTAL_MAX_ARGS && i < max_args; i++) { + ret = bpf_probe_read_user(&argp, sizeof(argp), &args[i]); + if (ret < 0){ + bpf_ringbuf_submit(event, 0); + return 0; + } + + if (event->args_size > LAST_ARG){ + bpf_ringbuf_submit(event, 0); + return 0; + } + + ret = bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp); + if (ret < 0){ + bpf_ringbuf_submit(event, 0); + return 0; + } + + event->count++; + event->args_size += ret; + } + /* 试着再读一个参数来检查是否有 */ + ret = bpf_probe_read_user(&argp, sizeof(argp), &args[max_args]); + if (ret < 0){ + bpf_ringbuf_submit(event, 0); + return 0; + } + + /* 指向max_args+1的指针不为空,假设我们有更多的参数 */ + event->count++; + + bpf_ringbuf_submit(event, 0); + } + + return 0; +} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h new file mode 100644 index 000000000..5c9d5aafd --- /dev/null +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h @@ -0,0 +1,17 @@ +// 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 +// +// Variable definitions and help functions for keytime in the process \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h index 8e3eb6359..b80474a6d 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h @@ -20,6 +20,11 @@ #define __PROC_IMAGE_H #define MAX_SYSCALL_COUNT 116 +#define ARGSIZE 128 +#define TOTAL_MAX_ARGS 60 +#define DEFAULT_MAXARGS 20 +#define FULL_MAX_ARGS_ARR 440 +#define LAST_ARG (FULL_MAX_ARGS_ARR - ARGSIZE) // resource_image struct proc_id{ @@ -72,4 +77,25 @@ struct lock_event{ long long unsigned int time; }; +// keytime_image +struct keytime_event{ + /* type: + 1代表exec_enter;2代表exec_exit + 3代表exit_enter + 4代表fork_enter;5代表fork_exit + 6代表vfork_enter;7代表vfork_exit + 8代表pthread_enter;9代表pthread_exit + */ + int type; + int pid; + int retval; + bool enable_char_args; + int count; + long long unsigned int info[6]; + unsigned int args_size; + char args[FULL_MAX_ARGS_ARR]; +}; + + + #endif /* __PROCESS_H */ \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c index 155781730..ad0ebb80f 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c @@ -32,6 +32,7 @@ #include "resource_image.skel.h" #include "syscall_image.skel.h" #include "lock_image.skel.h" +#include "keytime_image.skel.h" #define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ do \ @@ -85,6 +86,7 @@ #define RESOURCE_IMAGE 1 #define SYSCALL_IMAGE 2 #define LOCK_IMAGE 3 +#define KEYTIME_IMAGE 4 static int prev_image = 0; static volatile bool exiting = false; @@ -100,6 +102,9 @@ static struct env { bool first_rsc; bool enable_syscall; bool enable_lock; + bool quote; + int max_args; + bool enable_keytime; } env = { .pid = -1, .cpu_id = -1, @@ -111,6 +116,9 @@ static struct env { .first_rsc = true, .enable_syscall = false, .enable_lock = false, + .quote = false, + .max_args = DEFAULT_MAXARGS, + .enable_keytime = false, }; static struct timespec prevtime; @@ -120,6 +128,12 @@ char *lock_status[] = {"", "mutex_req", "mutex_lock", "mutex_unlock", "rdlock_req", "rdlock_lock", "rdlock_unlock", "wrlock_req", "wrlock_lock", "wrlock_unlock"}; +char *keytime_type[] = {"", "exec_enter", "exec_exit", + "exit_enter", + "fork_enter", "fork_exit", + "vfork_enter", "vfork_exit", + "pthread_enter", "pthread_exit",}; + const char argp_program_doc[] ="Trace process to get process image.\n"; static const struct argp_option opts[] = { @@ -130,6 +144,8 @@ static const struct argp_option opts[] = { { "resource", 'r', NULL, 0, "Collects resource usage information about processes" }, { "syscall", 's', NULL, 0, "Collects syscall sequence information about processes" }, { "lock", 'l', NULL, 0, "Collects lock information about processes" }, + { "quote", 'q', NULL, 0, "Add quotemarks (\") around arguments" }, + { "keytime", 'k', NULL, 0, "Collects keytime information about processes" }, { NULL, 'h', NULL, OPTION_HIDDEN, "show the full help" }, {}, }; @@ -165,6 +181,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) env.enable_resource = true; env.enable_syscall = true; env.enable_lock = true; + env.enable_keytime = true; break; case 'r': env.enable_resource = true; @@ -175,6 +192,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'l': env.enable_lock = true; break; + case 'q': + env.quote = true; + break; + case 'k': + env.enable_keytime = true; + break; case 'h': argp_state_help(state, stderr, ARGP_HELP_STD_HELP); break; @@ -305,6 +328,101 @@ static int print_lock(void *ctx, void *data,unsigned long data_sz) return 0; } +static void inline quoted_symbol(char c) { + switch(c) { + case '"': + putchar('\\'); + putchar('"'); + break; + case '\t': + putchar('\\'); + putchar('t'); + break; + case '\n': + putchar('\\'); + putchar('n'); + break; + default: + putchar(c); + break; + } +} + +static void print_args1(const struct keytime_event *e) +{ + int i, args_counter = 0; + + if (env.quote) + putchar('"'); + + for (i = 0; i < e->args_size && args_counter < e->count; i++) { + char c = e->args[i]; + + if (env.quote) { + if (c == '\0') { + args_counter++; + putchar('"'); + putchar(' '); + if (args_counter < e->count) { + putchar('"'); + } + } else { + quoted_symbol(c); + } + } else { + if (c == '\0') { + args_counter++; + putchar(' '); + } else { + putchar(c); + } + } + } + if (e->count == env.max_args + 1) { + fputs(" ...", stdout); + } +} + +static void print_args2(const struct keytime_event *e) +{ + int i=0; + for(int tmp=e->count; tmp>0 ; tmp--){ + if(env.quote){ + printf("\"%llu\" ",e->info[i++]); + }else{ + printf("%llu ",e->info[i++]); + } + } +} + +static int print_keytime(void *ctx, void *data,unsigned long data_sz) +{ + const struct keytime_event *e = data; + time_t now = time(NULL); + struct tm *localTime = localtime(&now); + int hour = localTime->tm_hour; + int min = localTime->tm_min; + int sec = localTime->tm_sec; + + if(prev_image != KEYTIME_IMAGE){ + printf("KEYTIME_IMAGE------------------------------------------------------------\n"); + printf("%-8s %-6s %-15s %s\n","TIME","PID","EVENT","ARGS/RET/OTHERS"); + + prev_image = KEYTIME_IMAGE; + } + + printf("%02d:%02d:%02d %-6d %-15s",hour,min,sec,e->pid,keytime_type[e->type]); + if(e->enable_char_args){ + print_args1(e); + }else{ + print_args2(e); + } + + putchar('\n'); + + return 0; +} + static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { return vfprintf(stderr, format, args); @@ -362,6 +480,8 @@ int main(int argc, char **argv) struct ring_buffer *syscall_rb = NULL; struct lock_image_bpf *lock_skel; struct ring_buffer *lock_rb = NULL; + struct keytime_image_bpf *keytime_skel; + struct ring_buffer *keytime_rb = NULL; pthread_t thread_enable; int err; static const struct argp argp = { @@ -466,6 +586,38 @@ int main(int argc, char **argv) } } + if(env.enable_keytime){ + keytime_skel = keytime_image_bpf__open(); + if (!keytime_skel) { + fprintf(stderr, "Failed to open BPF keytime skeleton\n"); + return 1; + } + + keytime_skel->rodata->target_pid = env.pid; + + err = keytime_image_bpf__load(keytime_skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF keytime skeleton\n"); + goto cleanup; + } + + /* 附加跟踪点处理程序 */ + err = keytime_image_bpf__attach(keytime_skel); + if (err) { + fprintf(stderr, "Failed to attach BPF keytime skeleton\n"); + goto cleanup; + } + + /* 设置环形缓冲区轮询 */ + //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 + keytime_rb = ring_buffer__new(bpf_map__fd(keytime_skel->maps.keytime_rb), print_keytime, NULL, NULL); + if (!keytime_rb) { + err = -1; + fprintf(stderr, "Failed to create keytime ring buffer\n"); + goto cleanup; + } + } + /* 处理事件 */ while (!exiting) { // 等待新线程结束,回收资源 @@ -522,6 +674,19 @@ int main(int argc, char **argv) break; } } + + if(env.enable_keytime){ + err = ring_buffer__poll(keytime_rb, 0); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + printf("Error polling keytime ring buffer: %d\n", err); + break; + } + } } /* 卸载BPF程序 */ @@ -531,6 +696,8 @@ int main(int argc, char **argv) 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); return err < 0 ? -err : 0; } \ No newline at end of file From f538bc718f814d510b83f97043378c40de2b3d41 Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Tue, 12 Dec 2023 18:09:50 +0800 Subject: [PATCH 3/7] add exit --- .../developing/bpf/keytime_image.bpf.c | 99 +++++++++++++++---- .../developing/include/proc_image.h | 17 ++-- .../eBPF_proc_image/developing/proc_image.c | 33 ++++--- 3 files changed, 108 insertions(+), 41 deletions(-) diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c index 80d3420ed..18f72be69 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c @@ -27,14 +27,14 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; const volatile int max_args = DEFAULT_MAXARGS; const volatile pid_t target_pid = -1; - +/* struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 10240); __type(key, pid_t); __type(value, struct keytime_event); } keytime SEC(".maps"); - +*/ struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries,256 * 10240); @@ -43,8 +43,7 @@ struct { SEC("tracepoint/syscalls/sys_enter_execve") int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx) { - struct task_struct *task = (struct task_struct *)bpf_get_current_task(); - int pid = BPF_CORE_READ(task,pid); + int pid = bpf_get_current_pid_tgid(); if(target_pid==-1 || pid==target_pid){ struct keytime_event* event; event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); @@ -58,24 +57,24 @@ int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx event->type = 1; event->pid = pid; - event->count = 0; - event->args_size = 0; - event->enable_char_args = true; + event->info_count = 0; + event->info_size = 0; + event->enable_char_info = true; - ret = bpf_probe_read_user_str(event->args, ARGSIZE, (const char*)ctx->args[0]); + ret = bpf_probe_read_user_str(event->char_info, ARGSIZE, (const char*)ctx->args[0]); if (ret < 0) { bpf_ringbuf_submit(event, 0); return 0; } if (ret <= ARGSIZE) { - event->args_size += ret; + event->info_size += ret; } else { /* 写一个空字符串 */ - event->args[0] = '\0'; - event->args_size++; + event->char_info[0] = '\0'; + event->info_size++; } - event->count++; + event->info_count++; #pragma unroll for (i = 1; i < TOTAL_MAX_ARGS && i < max_args; i++) { ret = bpf_probe_read_user(&argp, sizeof(argp), &args[i]); @@ -84,19 +83,19 @@ int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx return 0; } - if (event->args_size > LAST_ARG){ + if (event->info_size > LAST_ARG){ bpf_ringbuf_submit(event, 0); return 0; } - ret = bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp); + ret = bpf_probe_read_user_str(&event->char_info[event->info_size], ARGSIZE, argp); if (ret < 0){ bpf_ringbuf_submit(event, 0); return 0; } - event->count++; - event->args_size += ret; + event->info_count++; + event->info_size += ret; } /* 试着再读一个参数来检查是否有 */ ret = bpf_probe_read_user(&argp, sizeof(argp), &args[max_args]); @@ -106,7 +105,73 @@ int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx } /* 指向max_args+1的指针不为空,假设我们有更多的参数 */ - event->count++; + event->info_count++; + + bpf_ringbuf_submit(event, 0); + } + + return 0; +} + +SEC("tracepoint/syscalls/sys_exit_execve") +int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) +{ + int pid = bpf_get_current_pid_tgid(); + if(target_pid==-1 || pid==target_pid){ + struct keytime_event* event; + event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); + if(!event) + return 0; + + event->type = 2; + event->pid = pid; + event->enable_char_info = false; + event->info_count = 1; + event->info[0] = ctx->ret; + + bpf_ringbuf_submit(event, 0); + } + + return 0; +} + +SEC("tracepoint/syscalls/sys_enter_exit_group") +int tracepoint__syscalls__sys_enter_exit_group(struct trace_event_raw_sys_enter* ctx) +{ + int pid = bpf_get_current_pid_tgid(); + if(target_pid==-1 || pid==target_pid){ + struct keytime_event* event; + event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); + if(!event) + return 0; + + event->type = 3; + event->pid = pid; + event->enable_char_info = false; + event->info_count = 1; + event->info[0] = ctx->args[0]; + + bpf_ringbuf_submit(event, 0); + } + + return 0; +} + +SEC("tracepoint/syscalls/sys_enter_exit") +int tracepoint__syscalls__sys_enter_exit(struct trace_event_raw_sys_enter* ctx) +{ + int pid = bpf_get_current_pid_tgid(); + if(target_pid==-1 || pid==target_pid){ + struct keytime_event* event; + event = bpf_ringbuf_reserve(&keytime_rb, sizeof(*event), 0); + if(!event) + return 0; + + event->type = 3; + event->pid = pid; + event->enable_char_info = false; + event->info_count = 1; + event->info[0] = ctx->args[0]; bpf_ringbuf_submit(event, 0); } diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h index b80474a6d..865ae9b20 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h @@ -81,19 +81,18 @@ struct lock_event{ struct keytime_event{ /* type: 1代表exec_enter;2代表exec_exit - 3代表exit_enter - 4代表fork_enter;5代表fork_exit - 6代表vfork_enter;7代表vfork_exit - 8代表pthread_enter;9代表pthread_exit + 3代表exit + 4代表forkP_enter;5代表forkP_exit + 6代表vforkP_enter;7代表vforkP_exit + 8代表createT_enter;9代表createT_exit */ int type; int pid; - int retval; - bool enable_char_args; - int count; + bool enable_char_info; + int info_count; long long unsigned int info[6]; - unsigned int args_size; - char args[FULL_MAX_ARGS_ARR]; + unsigned int info_size; + char char_info[FULL_MAX_ARGS_ARR]; }; diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c index ad0ebb80f..5829b08e9 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c @@ -129,10 +129,10 @@ char *lock_status[] = {"", "mutex_req", "mutex_lock", "mutex_unlock", "wrlock_req", "wrlock_lock", "wrlock_unlock"}; char *keytime_type[] = {"", "exec_enter", "exec_exit", - "exit_enter", - "fork_enter", "fork_exit", - "vfork_enter", "vfork_exit", - "pthread_enter", "pthread_exit",}; + "exit", + "forkP_enter", "forkP_exit", + "vforkP_enter", "vforkP_exit", + "createT_enter", "createT_exit"}; const char argp_program_doc[] ="Trace process to get process image.\n"; @@ -348,22 +348,22 @@ static void inline quoted_symbol(char c) { } } -static void print_args1(const struct keytime_event *e) +static void print_info1(const struct keytime_event *e) { int i, args_counter = 0; if (env.quote) putchar('"'); - for (i = 0; i < e->args_size && args_counter < e->count; i++) { - char c = e->args[i]; + 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->count) { + if (args_counter < e->info_count) { putchar('"'); } } else { @@ -378,15 +378,15 @@ static void print_args1(const struct keytime_event *e) } } } - if (e->count == env.max_args + 1) { + if (e->info_count == env.max_args + 1) { fputs(" ...", stdout); } } -static void print_args2(const struct keytime_event *e) +static void print_info2(const struct keytime_event *e) { int i=0; - for(int tmp=e->count; tmp>0 ; tmp--){ + for(int tmp=e->info_count; tmp>0 ; tmp--){ if(env.quote){ printf("\"%llu\" ",e->info[i++]); }else{ @@ -411,11 +411,14 @@ static int print_keytime(void *ctx, void *data,unsigned long data_sz) prev_image = KEYTIME_IMAGE; } - printf("%02d:%02d:%02d %-6d %-15s",hour,min,sec,e->pid,keytime_type[e->type]); - if(e->enable_char_args){ - print_args1(e); + printf("%02d:%02d:%02d %-6d %-15s ",hour,min,sec,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){ + printf("child_pid:"); + } + if(e->enable_char_info){ + print_info1(e); }else{ - print_args2(e); + print_info2(e); } putchar('\n'); From 72a9e8e1cbdb32cf670788adebb096d645c20963 Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Thu, 14 Dec 2023 18:21:16 +0800 Subject: [PATCH 4/7] add fork & vfork & pthread_create --- .../developing/bpf/keytime_image.bpf.c | 95 ++++++++++++++++++- .../developing/include/keytime_image.h | 51 +++++++++- .../developing/include/proc_image.h | 7 +- .../eBPF_proc_image/developing/proc_image.c | 28 ++++-- 4 files changed, 166 insertions(+), 15 deletions(-) diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c index 18f72be69..aa54dda07 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c @@ -21,20 +21,28 @@ #include #include #include "proc_image.h" +#include "keytime_image.h" char LICENSE[] SEC("license") = "Dual BSD/GPL"; const volatile int max_args = DEFAULT_MAXARGS; const volatile pid_t target_pid = -1; -/* + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10240); + __type(key, pid_t); + __type(value, struct child_info); +} child SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 10240); __type(key, pid_t); - __type(value, struct keytime_event); -} keytime SEC(".maps"); -*/ + __type(value, bool); +} pthread_create_enable SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries,256 * 10240); @@ -135,6 +143,79 @@ int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) return 0; } +// 记录 fork 子进程的开始时间,并输出 +SEC("uretprobe/fork") +int BPF_KRETPROBE(fork_exit,int ret) +{ + pid_t pid = bpf_get_current_pid_tgid(); + + // 判断是否为父进程触发 + if(ret!=0 && (pid==target_pid || target_pid==-1)){ + pid_t child_pid = ret; + child_create(4,child_pid,pid,&child,&keytime_rb); + } + + return 0; +} + +// 记录 vfork 子进程的开始时间,并输出 +SEC("uretprobe/vfork") +int BPF_KRETPROBE(vfork_exit,int ret) +{ + struct task_struct *current = (struct task_struct *)bpf_get_current_task(); + pid_t ppid = BPF_CORE_READ(current,real_parent,pid); + + if(ppid==target_pid || target_pid==-1){ + pid_t child_pid = BPF_CORE_READ(current,pid); + child_create(6,child_pid,ppid,&child,&keytime_rb); + } + + return 0; +} + +SEC("uprobe/pthread_create") +int BPF_KPROBE(pthread_create_enter) +{ + int current = bpf_get_current_pid_tgid(); + bool pthread_create_flag = true; + + bpf_map_update_elem(&pthread_create_enable, ¤t, &pthread_create_flag, BPF_ANY); + + return 0; +} + +SEC("uretprobe/pthread_create") +int BPF_KRETPROBE(pthread_create_exit,int ret) +{ + int current = bpf_get_current_pid_tgid(); + bpf_map_delete_elem(&pthread_create_enable, ¤t); + + return 0; +} + +// 记录 pthread_create 新线程的开始时间,并输出 +SEC("tracepoint/syscalls/sys_exit_clone3") +int tracepoint__syscalls__sys_exit_clone3(struct trace_event_raw_sys_exit* ctx) +{ + pid_t current = bpf_get_current_pid_tgid(); + + if(current==target_pid || current==-1) + { + // 判断是否是pthread_create函数触发的clone3系统调用 + bool *pthread_create_flag; + pthread_create_flag = bpf_map_lookup_elem(&pthread_create_enable, ¤t); + if(pthread_create_flag && *pthread_create_flag){ + pid_t new_thread = ctx->ret; + // 排除clone3错误返回的情况 + if(new_thread <= 0) return 0; + + child_create(8,new_thread,current,&child,&keytime_rb); + } + } + + return 0; +} + SEC("tracepoint/syscalls/sys_enter_exit_group") int tracepoint__syscalls__sys_enter_exit_group(struct trace_event_raw_sys_enter* ctx) { @@ -154,6 +235,9 @@ int tracepoint__syscalls__sys_enter_exit_group(struct trace_event_raw_sys_enter* bpf_ringbuf_submit(event, 0); } + // 记录 fork 和 vfork 子进程的退出时间,并输出到 ringbuf 中 + child_exit(&child,&keytime_rb); + return 0; } @@ -176,5 +260,8 @@ int tracepoint__syscalls__sys_enter_exit(struct trace_event_raw_sys_enter* ctx) bpf_ringbuf_submit(event, 0); } + // 记录 pthread_create 新线程的退出时间,并输出 + child_exit(&child,&keytime_rb); + return 0; } \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h index 5c9d5aafd..45c8aa041 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h @@ -14,4 +14,53 @@ // // author: zhangziheng0525@163.com // -// Variable definitions and help functions for keytime in the process \ No newline at end of file +// 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) +{ + struct child_info child_info = {}; + child_info.type = type; + child_info.ppid = pid; + if(bpf_map_update_elem(child, &child_pid, &child_info, BPF_ANY)) + return 0; + + struct keytime_event* e; + e = bpf_ringbuf_reserve(keytime_rb, sizeof(*e), 0); + if(!e) + return 0; + + e->type = type; + e->pid = pid; + e->enable_char_info = false; + e->info_count = 1; + e->info[0] = child_pid; + + bpf_ringbuf_submit(e, 0); + + return 0; +} + +// 记录退出时间,并输出 +static int child_exit(void *child, void *keytime_rb) +{ + pid_t child_pid = bpf_get_current_pid_tgid(); + struct child_info *child_info = bpf_map_lookup_elem(child, &child_pid); + if(child_info){ + struct keytime_event* e; + e = bpf_ringbuf_reserve(keytime_rb, sizeof(*e), 0); + if(!e) + return 0; + + e->type = child_info->type + 1; + e->pid = child_info->ppid; + e->enable_char_info = false; + e->info_count = 1; + e->info[0] = child_pid; + + bpf_ringbuf_submit(e, 0); + bpf_map_delete_elem(child,&child_pid); + } + + return 0; +} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h index 865ae9b20..1d383cb11 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h @@ -78,6 +78,11 @@ struct lock_event{ }; // keytime_image +struct child_info{ + int type; + int ppid; +}; + struct keytime_event{ /* type: 1代表exec_enter;2代表exec_exit @@ -95,6 +100,4 @@ struct keytime_event{ char char_info[FULL_MAX_ARGS_ARR]; }; - - #endif /* __PROCESS_H */ \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c index 5829b08e9..e68720dee 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c @@ -80,9 +80,6 @@ #define warn(...) fprintf(stderr, __VA_ARGS__) -#define PERF_BUFFER_PAGES 64 -#define PERF_POLL_TIMEOUT_MS 100 - #define RESOURCE_IMAGE 1 #define SYSCALL_IMAGE 2 #define LOCK_IMAGE 3 @@ -290,7 +287,7 @@ static int print_syscall(void *ctx, void *data,unsigned long data_sz) if(count == 0) return 0; if(prev_image != SYSCALL_IMAGE){ - printf("SYSCALL------------------------------------------------------------\n"); + printf("SYSCALL-------------------------------------------------------------\n"); printf("%-29s %-6s %-8s\n","TIME(oncpu-offcpu)","PID","SYSCALLS"); prev_image = SYSCALL_IMAGE; @@ -405,7 +402,7 @@ static int print_keytime(void *ctx, void *data,unsigned long data_sz) int sec = localTime->tm_sec; if(prev_image != KEYTIME_IMAGE){ - printf("KEYTIME_IMAGE------------------------------------------------------------\n"); + printf("KEYTIME_IMAGE-------------------------------------------------------\n"); printf("%-8s %-6s %-15s %s\n","TIME","PID","EVENT","ARGS/RET/OTHERS"); prev_image = KEYTIME_IMAGE; @@ -431,7 +428,7 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va return vfprintf(stderr, format, args); } -static int attach(struct lock_image_bpf *skel) +static int lock_attach(struct lock_image_bpf *skel) { int err; @@ -461,6 +458,21 @@ static int attach(struct lock_image_bpf *skel) return 0; } +static int keytime_attach(struct keytime_image_bpf *skel) +{ + int err; + + ATTACH_URETPROBE_CHECKED(skel,fork,fork_exit); + ATTACH_URETPROBE_CHECKED(skel,vfork,vfork_exit); + ATTACH_UPROBE_CHECKED(skel,pthread_create,pthread_create_enter); + ATTACH_URETPROBE_CHECKED(skel,pthread_create,pthread_create_exit); + + err = keytime_image_bpf__attach(skel); + CHECK_ERR(err, "Failed to attach BPF keytime skeleton"); + + return 0; +} + void *enable_function(void *arg) { env.create_thread = true; sleep(1); @@ -573,7 +585,7 @@ int main(int argc, char **argv) } /* 附加跟踪点处理程序 */ - err = attach(lock_skel); + err = lock_attach(lock_skel); if (err) { fprintf(stderr, "Failed to attach BPF lock skeleton\n"); goto cleanup; @@ -605,7 +617,7 @@ int main(int argc, char **argv) } /* 附加跟踪点处理程序 */ - err = keytime_image_bpf__attach(keytime_skel); + err = keytime_attach(keytime_skel); if (err) { fprintf(stderr, "Failed to attach BPF keytime skeleton\n"); goto cleanup; From 3697addd8f892ab1670295062c55ca6af3c2df5d Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Thu, 14 Dec 2023 21:59:31 +0800 Subject: [PATCH 5/7] add helpers.h --- .../developing/include/helpers.h | 68 +++++++++++++++++++ .../eBPF_proc_image/developing/proc_image.c | 52 +------------- 2 files changed, 69 insertions(+), 51 deletions(-) create mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/helpers.h diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/helpers.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/helpers.h new file mode 100644 index 000000000..2fbd87bbe --- /dev/null +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/helpers.h @@ -0,0 +1,68 @@ +// 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 +// +// user-mode helper functions for the process image + +#define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ + do \ + { \ + LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, \ + .retprobe = is_retprobe, \ + .func_name = #sym_name); \ + skel->links.prog_name = bpf_program__attach_uprobe_opts( \ + skel->progs.prog_name, \ + env.pid, \ + object, \ + 0, \ + &uprobe_opts); \ + } while (false) + +#define __CHECK_PROGRAM(skel, prog_name) \ + do \ + { \ + if (!skel->links.prog_name) \ + { \ + fprintf(stderr, "[%s] no program attached for" #prog_name "\n", strerror(errno)); \ + return -errno; \ + } \ + } while (false) + +#define __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, is_retprobe) \ + do \ + { \ + __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe); \ + __CHECK_PROGRAM(skel, prog_name); \ + } while (false) + +#define ATTACH_UPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, false) +#define ATTACH_URETPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, true) + +#define ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, false) +#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, true) + +#define CHECK_ERR(cond, info) \ + if (cond) \ + { \ + fprintf(stderr, "[%s]" info "\n", strerror(errno)); \ + return -1; \ + } + +#define warn(...) fprintf(stderr, __VA_ARGS__) + +#define RESOURCE_IMAGE 1 +#define SYSCALL_IMAGE 2 +#define LOCK_IMAGE 3 +#define KEYTIME_IMAGE 4 \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c index e68720dee..cd9bc28c4 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c @@ -33,57 +33,7 @@ #include "syscall_image.skel.h" #include "lock_image.skel.h" #include "keytime_image.skel.h" - -#define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ - do \ - { \ - LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, \ - .retprobe = is_retprobe, \ - .func_name = #sym_name); \ - skel->links.prog_name = bpf_program__attach_uprobe_opts( \ - skel->progs.prog_name, \ - env.pid, \ - object, \ - 0, \ - &uprobe_opts); \ - } while (false) - -#define __CHECK_PROGRAM(skel, prog_name) \ - do \ - { \ - if (!skel->links.prog_name) \ - { \ - fprintf(stderr, "[%s] no program attached for" #prog_name "\n", strerror(errno)); \ - return -errno; \ - } \ - } while (false) - -#define __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, is_retprobe) \ - do \ - { \ - __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe); \ - __CHECK_PROGRAM(skel, prog_name); \ - } while (false) - -#define ATTACH_UPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, false) -#define ATTACH_URETPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, true) - -#define ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, false) -#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, true) - -#define CHECK_ERR(cond, info) \ - if (cond) \ - { \ - fprintf(stderr, "[%s]" info "\n", strerror(errno)); \ - return -1; \ - } - -#define warn(...) fprintf(stderr, __VA_ARGS__) - -#define RESOURCE_IMAGE 1 -#define SYSCALL_IMAGE 2 -#define LOCK_IMAGE 3 -#define KEYTIME_IMAGE 4 +#include "helpers.h" static int prev_image = 0; static volatile bool exiting = false; From b628ffbf4dedeb44b5cdfaff08b741604e122eb8 Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Fri, 22 Dec 2023 16:07:59 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=96=B0=E6=A1=86=E6=9E=B6=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E5=B7=A5=E5=85=B7=E6=9B=BF=E6=8D=A2=E6=97=A7?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=B7=A5=E5=85=B7=20&=20=E4=BF=AE=E6=94=B9re?= =?UTF-8?q?adme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/eBPF_proc_image.yml | 8 +- .../CPU_Subsystem/eBPF_proc_image/Makefile | 47 +- .../CPU_Subsystem/eBPF_proc_image/README.md | 21 +- .../{developing => }/bpf/keytime_image.bpf.c | 0 .../{developing => }/bpf/lock_image.bpf.c | 0 .../{developing => }/bpf/resource_image.bpf.c | 0 .../{developing => }/bpf/syscall_image.bpf.c | 0 .../eBPF_proc_image/developing/Makefile | 132 --- .../developing/include/keytime_image.h | 66 -- .../developing/include/lock_image.h | 142 ---- .../developing/include/proc_image.h | 103 --- .../eBPF_proc_image/developing/proc_image.c | 668 --------------- .../{developing => }/include/helpers.h | 0 .../eBPF_proc_image/include/keytime_image.h | 192 +---- .../eBPF_proc_image/include/lifecycle_image.h | 175 ---- .../eBPF_proc_image/include/lock_image.h | 246 +++--- .../eBPF_proc_image/include/newlife_image.h | 86 -- .../eBPF_proc_image/include/proc_image.h | 101 ++- .../{developing => }/include/vmlinux.h | 0 .../eBPF_proc_image/proc_image.bpf.c | 396 --------- .../eBPF_proc_image/proc_image.c | 799 ++++++++++-------- 21 files changed, 670 insertions(+), 2512 deletions(-) rename eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/{developing => }/bpf/keytime_image.bpf.c (100%) rename eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/{developing => }/bpf/lock_image.bpf.c (100%) rename eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/{developing => }/bpf/resource_image.bpf.c (100%) rename eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/{developing => }/bpf/syscall_image.bpf.c (100%) delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/lock_image.h delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c rename eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/{developing => }/include/helpers.h (100%) delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lifecycle_image.h delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/newlife_image.h rename eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/{developing => }/include/vmlinux.h (100%) delete mode 100644 eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.bpf.c diff --git a/.github/workflows/eBPF_proc_image.yml b/.github/workflows/eBPF_proc_image.yml index e9bf578a0..a7af90521 100644 --- a/.github/workflows/eBPF_proc_image.yml +++ b/.github/workflows/eBPF_proc_image.yml @@ -49,17 +49,11 @@ jobs: cd eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/tools make keytime_image sudo ./keytime_image -t 1 - + - name: Run proc_image run: | cd eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image make proc_image - sudo ./proc_image -t 1 - - - name: Run new_proc_image - run: | - cd eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing - make proc_image sudo ./proc_image -a -p 1 -t 1 - name: Run mutex_test diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile index 477afb1de..a80365a6c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/Makefile @@ -34,25 +34,15 @@ ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ | sed 's/mips.*/mips/' \ | sed 's/riscv64/riscv/' \ | sed 's/loongarch64/loongarch/') -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) +INCLUDES := -I$(OUTPUT) -I../libbpf/include/uapi -I$(LIBBLAZESYM_INC) -I./include CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) -APPS = proc_image - -CARGO ?= $(shell which cargo) -ifeq ($(strip $(CARGO)),) -BZS_APPS := -else -BZS_APPS := profile -APPS += $(BZS_APPS) -# Required by libblazesym -ALL_LDFLAGS += -lrt -ldl -lpthread -lm -endif +APPS = resource_image lock_image syscall_image keytime_image +TARGETS = proc_image # 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 @@ -87,12 +77,12 @@ $(call allow-override,CC,$(CROSS_COMPILE)cc) $(call allow-override,LD,$(CROSS_COMPILE)ld) .PHONY: all -all: $(APPS) +all: $(TARGETS) .PHONY: clean clean: $(call msg,CLEAN) - $(Q)rm -rf $(OUTPUT) $(APPS) + $(Q)rm -rf $(OUTPUT) $(TARGETS) $(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): $(call msg,MKDIR,$@) @@ -111,16 +101,8 @@ $(BPFTOOL): | $(BPFTOOL_OUTPUT) $(call msg,BPFTOOL,$@) $(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap - -$(LIBBLAZESYM_SRC)/target/release/libblazesym.a:: - $(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --release - -$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) - $(call msg,LIB, $@) - $(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) \ @@ -128,25 +110,20 @@ $(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) # Generate BPF skeletons -$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) +.PHONY: $(APPS) +$(APPS): %: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) $(call msg,GEN-SKEL,$@) - $(Q)$(BPFTOOL) gen skeleton $< > $@ + $(Q)$(BPFTOOL) gen skeleton $< > $(OUTPUT)/$@.skel.h # Build user-space code -$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h - -$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) +$(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) $(call msg,CC,$@) $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ -$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_OBJ) - -$(BZS_APPS): $(LIBBLAZESYM_OBJ) - # Build application binary -$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) +$(TARGETS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) $(call msg,BINARY,$@) - $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ + $(Q)$(CC) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@ # 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 912403c46..95990ccc9 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/README.md +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/README.md @@ -29,22 +29,13 @@ proc_image 工具的参数信息: | -------------------- | ------------------------------------------------- | | -p, --pid=PID | 指定跟踪进程的pid,默认为0号进程 | | -t, --time=TIME-SEC | 设置程序的最大运行时间(0表示无限),默认一直运行 | -| -C, --cpuid=CPUID | 为每CPU进程设置,其他进程不需要设置该参数 | -| -c, --cputime | 统计进程上下CPU时间信息 | -| -e, --execve | 对进程execve关键时间点进行画像 | -| -E, --exit | 对进程exit关键时间点进行画像 | +| -c, --cpuid=CPUID | 为每CPU进程设置,其他进程不需要设置该参数 | +| -r, --resource | 采集进程的资源使用情况,包括CPU利用率、内存利用率、每秒读写字节数(可持续开发) | +| -s, --syscall | 采集进程在on_CPU时间段内的系统调用序列 | +| -l, --lock | 采集进程持有的用户态锁信息,包括用户态互斥锁、用户态读写锁(可持续开发) | | -q, --quote | 在参数周围添加引号(") | -| -K, --keytime | 对进程的关键时间点进行画像,即execve和exit | -| -m, --user-mutex | 对进程的用户态互斥锁进行画像 | -| -M, --kernel-mutex | 对进程的内核态互斥锁进行画像 | -| -r, --user-rwlock-rd | 对进程用户态读模式下的读写锁进行画像 | -| -w, --user-rwlock-wr | 对进程用户态写模式下的读写锁进行画像 | -| -L, --lock | 对进程的各种锁进行画像 | -| -f, --fork | 对fork出来的子进程进行画像 | -| -F, --vfork | 对vfork出来的子进程进行画像 | -| -T, --newthread | 对pthread_create出来的新线程进行画像 | -| -S, --child | 对新创建进程和线程进行画像 | -| -A, --all | 开启所有的功能 | +| -k, --keytime | 采集进程关键时间点的相关信息,包括execve、exit、fork、vfork、pthread_create | +| -a, --all | 启动所有的采集进程数据的功能 | | -h, --help | 显示帮助信息 | ## 四、tools diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/keytime_image.bpf.c similarity index 100% rename from eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/keytime_image.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/keytime_image.bpf.c diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/lock_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/lock_image.bpf.c similarity index 100% rename from eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/lock_image.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/lock_image.bpf.c diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/resource_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/resource_image.bpf.c similarity index 100% rename from eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/resource_image.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/resource_image.bpf.c diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/syscall_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/syscall_image.bpf.c similarity index 100% rename from eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/bpf/syscall_image.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/bpf/syscall_image.bpf.c diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile deleted file mode 100644 index 49f760d80..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/Makefile +++ /dev/null @@ -1,132 +0,0 @@ -# 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 -# -# compile the current folder code - -# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -OUTPUT := .output -CLANG ?= clang -LIBBPF_SRC := $(abspath ../../libbpf/src) -BPFTOOL_SRC := $(abspath ../../bpftool/src) -LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) -BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) -BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool -LIBBLAZESYM_SRC := $(abspath ../../blazesym/) -LIBBLAZESYM_INC := $(abspath $(LIBBLAZESYM_SRC)/include) -LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a) -ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ - | sed 's/arm.*/arm/' \ - | sed 's/aarch64/arm64/' \ - | sed 's/ppc64le/powerpc/' \ - | sed 's/mips.*/mips/' \ - | sed 's/riscv64/riscv/' \ - | sed 's/loongarch64/loongarch/') -# 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$(LIBBLAZESYM_INC) -I./include -CFLAGS := -g -Wall -ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) - -APPS = resource_image lock_image syscall_image keytime_image -TARGETS = proc_image - -# 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 -# architecture-specific dirs will be "missing" on some architectures/distros - -# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, -# sys/cdefs.h etc. might be missing. -# -# Use '-idirafter': Don't interfere with include mechanics except where the -# build would have failed anyways. -CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - &1 \ - | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') - -ifeq ($(V),1) - Q = - msg = -else - Q = @ - msg = @printf ' %-8s %s%s\n' \ - "$(1)" \ - "$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ - "$(if $(3), $(3))"; - MAKEFLAGS += --no-print-directory -endif - -define allow-override - $(if $(or $(findstring environment,$(origin $(1))),\ - $(findstring command line,$(origin $(1)))),,\ - $(eval $(1) = $(2))) -endef - -$(call allow-override,CC,$(CROSS_COMPILE)cc) -$(call allow-override,LD,$(CROSS_COMPILE)ld) - -.PHONY: all -all: $(TARGETS) - -.PHONY: clean -clean: - $(call msg,CLEAN) - $(Q)rm -rf $(OUTPUT) $(TARGETS) - -$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): - $(call msg,MKDIR,$@) - $(Q)mkdir -p $@ - -# Build libbpf -$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf - $(call msg,LIB,$@) - $(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \ - OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ - INCLUDEDIR= LIBDIR= UAPIDIR= \ - install - -# Build bpftool -$(BPFTOOL): | $(BPFTOOL_OUTPUT) - $(call msg,BPFTOOL,$@) - $(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap - -# Build BPF code -$(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) \ - -c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) - $(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) - -# Generate BPF skeletons -.PHONY: $(APPS) -$(APPS): %: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) - $(call msg,GEN-SKEL,$@) - $(Q)$(BPFTOOL) gen skeleton $< > $(OUTPUT)/$@.skel.h - -# Build user-space code -$(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) - $(call msg,CC,$@) - $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ - -# Build application binary -$(TARGETS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) - $(call msg,BINARY,$@) - $(Q)$(CC) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@ - -# delete failed targets -.DELETE_ON_ERROR: - -# keep intermediate (.skel.h, .bpf.o, etc) targets -.SECONDARY: \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h deleted file mode 100644 index 45c8aa041..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/keytime_image.h +++ /dev/null @@ -1,66 +0,0 @@ -// 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 -// -// 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) -{ - struct child_info child_info = {}; - child_info.type = type; - child_info.ppid = pid; - if(bpf_map_update_elem(child, &child_pid, &child_info, BPF_ANY)) - return 0; - - struct keytime_event* e; - e = bpf_ringbuf_reserve(keytime_rb, sizeof(*e), 0); - if(!e) - return 0; - - e->type = type; - e->pid = pid; - e->enable_char_info = false; - e->info_count = 1; - e->info[0] = child_pid; - - bpf_ringbuf_submit(e, 0); - - return 0; -} - -// 记录退出时间,并输出 -static int child_exit(void *child, void *keytime_rb) -{ - pid_t child_pid = bpf_get_current_pid_tgid(); - struct child_info *child_info = bpf_map_lookup_elem(child, &child_pid); - if(child_info){ - struct keytime_event* e; - e = bpf_ringbuf_reserve(keytime_rb, sizeof(*e), 0); - if(!e) - return 0; - - e->type = child_info->type + 1; - e->pid = child_info->ppid; - e->enable_char_info = false; - e->info_count = 1; - e->info[0] = child_pid; - - bpf_ringbuf_submit(e, 0); - bpf_map_delete_elem(child,&child_pid); - } - - return 0; -} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/lock_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/lock_image.h deleted file mode 100644 index de9c6c73d..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/lock_image.h +++ /dev/null @@ -1,142 +0,0 @@ -// 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 -// -// Variable definitions and help functions for lock in the process - -static int record_lock_enter(int lock_status,int flag,void *__lock,void *lock_rb,void *proc_lock) -{ - pid_t pid = bpf_get_current_pid_tgid(); - u64 lock_ptr = (u64)__lock; - struct proc_flag proc_flag = {}; - - proc_flag.pid = pid; - proc_flag.flag = flag; - if(bpf_map_update_elem(proc_lock, &proc_flag, &lock_ptr, BPF_ANY)) - return 0; - - struct lock_event* e; - e = bpf_ringbuf_reserve(lock_rb, sizeof(*e), 0); - if(!e) - return 0; - - e->lock_status = lock_status; - e->pid = pid; - e->lock_ptr = lock_ptr; - e->time = bpf_ktime_get_ns(); - - bpf_ringbuf_submit(e, 0); - - return 0; -} - -static int record_lock_exit(int lock_status,int flag,int ret,void *lock_rb,void *proc_lock,void *locktype) -{ - pid_t pid = bpf_get_current_pid_tgid(); - u64 *lock_ptr; - u64 temp_lock_ptr; - struct proc_flag proc_flag = {}; - - proc_flag.pid = pid; - proc_flag.flag = flag; - - lock_ptr = bpf_map_lookup_elem(proc_lock, &proc_flag); - if(!lock_ptr) - return 0; - temp_lock_ptr = *lock_ptr; - bpf_map_delete_elem(proc_lock, &proc_flag); - - if((lock_status==5 || lock_status==8) && ret==0){ - int type; - - if(lock_status == 5) type= 1; - else type= 2; - - if(bpf_map_update_elem(locktype, &temp_lock_ptr, &type, BPF_ANY)) - return 0; - } - - struct lock_event* e; - e = bpf_ringbuf_reserve(lock_rb, sizeof(*e), 0); - if(!e) - return 0; - - e->lock_status = lock_status; - e->pid = pid; - e->ret = ret; - e->lock_ptr = temp_lock_ptr; - e->time = bpf_ktime_get_ns(); - - bpf_ringbuf_submit(e, 0); - - return 0; -} - -static int record_unlock_enter(int flag,void *__lock,void *proc_unlock) -{ - pid_t pid = bpf_get_current_pid_tgid(); - u64 lock_ptr = (u64)__lock; - struct proc_flag proc_flag = {}; - - proc_flag.pid = pid; - proc_flag.flag = flag; - - bpf_map_update_elem(proc_unlock, &proc_flag, &lock_ptr, BPF_ANY); - - return 0; -} - -static int record_unlock_exit(int lock_status,int flag,void *lock_rb,void *proc_unlock,void *locktype) -{ - pid_t pid = bpf_get_current_pid_tgid(); - u64 *lock_ptr; - u64 temp_lock_ptr; - struct proc_flag proc_flag = {}; - - proc_flag.pid = pid; - proc_flag.flag = flag; - - lock_ptr = bpf_map_lookup_elem(proc_unlock, &proc_flag); - if(!lock_ptr) - return 0; - temp_lock_ptr = *lock_ptr; - bpf_map_delete_elem(proc_unlock, &proc_flag); - - if(lock_status ==0){ - int *type; - - type = bpf_map_lookup_elem(locktype, &temp_lock_ptr); - if(!type) - return 0; - - if(*type == 1) lock_status = 6; - else if(*type == 2) lock_status = 9; - bpf_map_delete_elem(locktype, &temp_lock_ptr); - } - - struct lock_event* e; - e = bpf_ringbuf_reserve(lock_rb, sizeof(*e), 0); - if(!e) - return 0; - - e->lock_status = lock_status; - e->pid = pid; - e->lock_ptr = temp_lock_ptr; - e->time = bpf_ktime_get_ns(); - - bpf_ringbuf_submit(e, 0); - - return 0; -} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h deleted file mode 100644 index 1d383cb11..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/proc_image.h +++ /dev/null @@ -1,103 +0,0 @@ -// 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 -// -// eBPF map for the process image - -#ifndef __PROC_IMAGE_H -#define __PROC_IMAGE_H - -#define MAX_SYSCALL_COUNT 116 -#define ARGSIZE 128 -#define TOTAL_MAX_ARGS 60 -#define DEFAULT_MAXARGS 20 -#define FULL_MAX_ARGS_ARR 440 -#define LAST_ARG (FULL_MAX_ARGS_ARR - ARGSIZE) - -// resource_image -struct proc_id{ - int pid; - int cpu_id; -}; - -struct start_rsc{ - long long unsigned int time; - long long unsigned int readchar; - long long unsigned int writechar; -}; - -struct total_rsc{ - int pid; - int cpu_id; - long long unsigned int time; - long unsigned int memused; - long long unsigned int readchar; - long long unsigned int writechar; -}; - -//syscall_image -struct syscall_seq{ - int pid; - long long unsigned int oncpu_time; - long long unsigned int offcpu_time; - int count; // 若count值超过MAX_SYSCALL_COUNT,则record_syscall数组最后一个元素的值用-1表示以作说明 - int record_syscall[MAX_SYSCALL_COUNT]; -}; - -// lock_image -struct proc_flag{ - int pid; - // 1代表用户态互斥锁 - // 2代表用户态读写锁 - int flag; -}; - -struct lock_event{ - /* lock_status: - 1代表mutex_req;2代表mutex_lock;3代表mutex_unlock - 4代表rdlock_req;5代表rdlock_lock;6代表rdlock_unlock - 7代表wrlock_req;8代表wrlock_lock;9代表wrlock_unlock - */ - int lock_status; - int pid; - int ret; - long long unsigned int lock_ptr; - long long unsigned int time; -}; - -// keytime_image -struct child_info{ - int type; - int ppid; -}; - -struct keytime_event{ - /* type: - 1代表exec_enter;2代表exec_exit - 3代表exit - 4代表forkP_enter;5代表forkP_exit - 6代表vforkP_enter;7代表vforkP_exit - 8代表createT_enter;9代表createT_exit - */ - int type; - int pid; - bool enable_char_info; - int info_count; - long long unsigned int info[6]; - unsigned int info_size; - char char_info[FULL_MAX_ARGS_ARR]; -}; - -#endif /* __PROCESS_H */ \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c deleted file mode 100644 index cd9bc28c4..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/proc_image.c +++ /dev/null @@ -1,668 +0,0 @@ -// 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 -// -// user-mode code for the process image - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "proc_image.h" -#include "resource_image.skel.h" -#include "syscall_image.skel.h" -#include "lock_image.skel.h" -#include "keytime_image.skel.h" -#include "helpers.h" - -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 cpu_id; - int time; - bool enable_output; - bool create_thread; - bool exit_thread; - bool enable_resource; - bool first_rsc; - bool enable_syscall; - bool enable_lock; - bool quote; - int max_args; - bool enable_keytime; -} env = { - .pid = -1, - .cpu_id = -1, - .time = 0, - .enable_output = false, - .create_thread = false, - .exit_thread = false, - .enable_resource = false, - .first_rsc = true, - .enable_syscall = false, - .enable_lock = false, - .quote = false, - .max_args = DEFAULT_MAXARGS, - .enable_keytime = false, -}; - -static struct timespec prevtime; -static struct timespec currentime; - -char *lock_status[] = {"", "mutex_req", "mutex_lock", "mutex_unlock", - "rdlock_req", "rdlock_lock", "rdlock_unlock", - "wrlock_req", "wrlock_lock", "wrlock_unlock"}; - -char *keytime_type[] = {"", "exec_enter", "exec_exit", - "exit", - "forkP_enter", "forkP_exit", - "vforkP_enter", "vforkP_exit", - "createT_enter", "createT_exit"}; - -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" }, - { "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)" }, - { "all", 'a', NULL, 0, "Start all functions" }, - { "resource", 'r', NULL, 0, "Collects resource usage information about processes" }, - { "syscall", 's', NULL, 0, "Collects syscall sequence information about processes" }, - { "lock", 'l', NULL, 0, "Collects lock information about processes" }, - { "quote", 'q', NULL, 0, "Add quotemarks (\") around arguments" }, - { "keytime", 'k', NULL, 0, "Collects keytime information about processes" }, - { 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 cpu_id; - 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 '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 'a': - env.enable_resource = true; - env.enable_syscall = true; - env.enable_lock = true; - env.enable_keytime = true; - break; - case 'r': - env.enable_resource = true; - break; - case 's': - env.enable_syscall = true; - break; - case 'l': - env.enable_lock = true; - break; - case 'q': - env.quote = true; - break; - case 'k': - env.enable_keytime = true; - break; - case 'h': - argp_state_help(state, stderr, ARGP_HELP_STD_HELP); - break; - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -static int print_resource(struct bpf_map *map) -{ - struct proc_id lookup_key = {-1}, next_key; - int err, fd = bpf_map__fd(map); - - if(env.first_rsc){ - env.first_rsc = false; - goto delete_elem; - } - - struct total_rsc event; - float pcpu,pmem; - double read_rate,write_rate; - unsigned long memtotal = sysconf(_SC_PHYS_PAGES); - time_t now = time(NULL); - struct tm *localTime = localtime(&now); - int hour = localTime->tm_hour; - int min = localTime->tm_min; - int sec = localTime->tm_sec; - long long unsigned int interval; - - while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { - if(prev_image != RESOURCE_IMAGE){ - printf("RESOURCE------------------------------------------------------------\n"); - printf("%-8s %-6s %-6s %-6s %-6s %-12s %-12s\n","TIME","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); - return -1; - } - - clock_gettime(CLOCK_REALTIME, ¤time); - interval = currentime.tv_nsec-prevtime.tv_nsec+(currentime.tv_sec-prevtime.tv_sec)*1000000000; - - if(interval>0 && memtotal>0 && event.time>0){ - pcpu = (100.0*event.time)/interval; - pmem = (100.0*event.memused)/memtotal; - read_rate = (1.0*event.readchar)/1024/((1.0*event.time)/1000000000); // kb/s - write_rate = (1.0*event.writechar)/1024/((1.0*event.time)/1000000000); // kb/s - }else{ - goto next_elem; - } - - if(pcpu<=100 && pmem<=100){ - printf("%02d:%02d:%02d %-6d %-6d %-6.3f %-6.3f %-12.2lf %-12.2lf\n", - hour,min,sec,event.pid,event.cpu_id,pcpu,pmem,read_rate,write_rate); - } - -next_elem: - lookup_key = next_key; - } - -delete_elem: - lookup_key.pid = -1; - lookup_key.cpu_id = -1; - while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { - err = bpf_map_delete_elem(fd, &next_key); - if (err < 0) { - fprintf(stderr, "failed to cleanup infos: %d\n", err); - return -1; - } - lookup_key = next_key; - } - - // 获取当前高精度时间 - clock_gettime(CLOCK_REALTIME, &prevtime); - env.enable_output = false; - - return 0; -} - -static int print_syscall(void *ctx, void *data,unsigned long data_sz) -{ - const struct syscall_seq *e = data; - int count = e->count; - - if(count == 0) return 0; - - if(prev_image != SYSCALL_IMAGE){ - printf("SYSCALL-------------------------------------------------------------\n"); - printf("%-29s %-6s %-8s\n","TIME(oncpu-offcpu)","PID","SYSCALLS"); - - prev_image = SYSCALL_IMAGE; - } - - printf("%-14lld-%14lld %-6d ",e->oncpu_time,e->offcpu_time,e->pid); - for(int i=0; irecord_syscall[i]); - else printf("%d,",e->record_syscall[i]); - } - - putchar('\n'); - - return 0; -} - -static int print_lock(void *ctx, void *data,unsigned long data_sz) -{ - const struct lock_event *e = data; - - if(prev_image != LOCK_IMAGE){ - printf("USERLOCK------------------------------------------------------------\n"); - printf("%-14s %-6s %-15s %s\n","TIME","PID","LockAddr","LockStatus"); - - prev_image = LOCK_IMAGE; - } - - printf("%-14lld %-6d %-15lld ",e->time,e->pid,e->lock_ptr); - if(e->lock_status==2 || e->lock_status==5 || e->lock_status==8){ - printf("%s-%d\n",lock_status[e->lock_status],e->ret); - }else{ - printf("%s\n",lock_status[e->lock_status]); - } - - return 0; -} - -static void inline quoted_symbol(char c) { - switch(c) { - case '"': - putchar('\\'); - putchar('"'); - break; - case '\t': - putchar('\\'); - putchar('t'); - break; - case '\n': - putchar('\\'); - putchar('n'); - break; - default: - putchar(c); - break; - } -} - -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); - } - } else { - if (c == '\0') { - args_counter++; - putchar(' '); - } else { - putchar(c); - } - } - } - if (e->info_count == env.max_args + 1) { - fputs(" ...", stdout); - } -} - -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++]); - } - } -} - -static int print_keytime(void *ctx, void *data,unsigned long data_sz) -{ - const struct keytime_event *e = data; - time_t now = time(NULL); - struct tm *localTime = localtime(&now); - int hour = localTime->tm_hour; - int min = localTime->tm_min; - int sec = localTime->tm_sec; - - if(prev_image != KEYTIME_IMAGE){ - printf("KEYTIME_IMAGE-------------------------------------------------------\n"); - printf("%-8s %-6s %-15s %s\n","TIME","PID","EVENT","ARGS/RET/OTHERS"); - - prev_image = KEYTIME_IMAGE; - } - - printf("%02d:%02d:%02d %-6d %-15s ",hour,min,sec,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){ - printf("child_pid:"); - } - if(e->enable_char_info){ - print_info1(e); - }else{ - print_info2(e); - } - - putchar('\n'); - - return 0; -} - -static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) -{ - return vfprintf(stderr, format, args); -} - -static int lock_attach(struct lock_image_bpf *skel) -{ - int err; - - ATTACH_UPROBE_CHECKED(skel,pthread_mutex_lock,pthread_mutex_lock_enter); - ATTACH_URETPROBE_CHECKED(skel,pthread_mutex_lock,pthread_mutex_lock_exit); - ATTACH_UPROBE_CHECKED(skel,__pthread_mutex_trylock,__pthread_mutex_trylock_enter); - ATTACH_URETPROBE_CHECKED(skel,__pthread_mutex_trylock,__pthread_mutex_trylock_exit); - ATTACH_UPROBE_CHECKED(skel,pthread_mutex_unlock,pthread_mutex_unlock_enter); - ATTACH_URETPROBE_CHECKED(skel,pthread_mutex_unlock,pthread_mutex_unlock_exit); - - ATTACH_UPROBE_CHECKED(skel,__pthread_rwlock_rdlock,__pthread_rwlock_rdlock_enter); - ATTACH_URETPROBE_CHECKED(skel,__pthread_rwlock_rdlock,__pthread_rwlock_rdlock_exit); - ATTACH_UPROBE_CHECKED(skel,__pthread_rwlock_tryrdlock,__pthread_rwlock_tryrdlock_enter); - ATTACH_URETPROBE_CHECKED(skel,__pthread_rwlock_tryrdlock,__pthread_rwlock_tryrdlock_exit); - - ATTACH_UPROBE_CHECKED(skel,__pthread_rwlock_wrlock,__pthread_rwlock_wrlock_enter); - ATTACH_URETPROBE_CHECKED(skel,__pthread_rwlock_wrlock,__pthread_rwlock_wrlock_exit); - ATTACH_UPROBE_CHECKED(skel,__pthread_rwlock_trywrlock,__pthread_rwlock_trywrlock_enter); - ATTACH_URETPROBE_CHECKED(skel,__pthread_rwlock_trywrlock,__pthread_rwlock_trywrlock_exit); - - ATTACH_UPROBE_CHECKED(skel,__pthread_rwlock_unlock,__pthread_rwlock_unlock_enter); - ATTACH_URETPROBE_CHECKED(skel,__pthread_rwlock_unlock,__pthread_rwlock_unlock_exit); - - err = lock_image_bpf__attach(skel); - CHECK_ERR(err, "Failed to attach BPF lock skeleton"); - - return 0; -} - -static int keytime_attach(struct keytime_image_bpf *skel) -{ - int err; - - ATTACH_URETPROBE_CHECKED(skel,fork,fork_exit); - ATTACH_URETPROBE_CHECKED(skel,vfork,vfork_exit); - ATTACH_UPROBE_CHECKED(skel,pthread_create,pthread_create_enter); - ATTACH_URETPROBE_CHECKED(skel,pthread_create,pthread_create_exit); - - err = keytime_image_bpf__attach(skel); - CHECK_ERR(err, "Failed to attach BPF keytime skeleton"); - - return 0; -} - -void *enable_function(void *arg) { - env.create_thread = true; - sleep(1); - env.enable_output = true; - env.create_thread = false; - env.exit_thread = true; - - return NULL; -} - -static void sig_handler(int signo) -{ - exiting = true; -} - -int main(int argc, char **argv) -{ - struct resource_image_bpf *resource_skel; - struct syscall_image_bpf *syscall_skel; - struct ring_buffer *syscall_rb = NULL; - struct lock_image_bpf *lock_skel; - struct ring_buffer *lock_rb = NULL; - struct keytime_image_bpf *keytime_skel; - struct ring_buffer *keytime_rb = NULL; - pthread_t thread_enable; - 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; - - libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - /* 设置libbpf错误和调试信息回调 */ - libbpf_set_print(libbpf_print_fn); - - signal(SIGALRM,sig_handler); - - if(env.enable_resource){ - resource_skel = resource_image_bpf__open(); - if(!resource_skel) { - fprintf(stderr, "Failed to open BPF resource skeleton\n"); - return 1; - } - - resource_skel->rodata->target_pid = env.pid; - resource_skel->rodata->target_cpu_id = env.cpu_id; - - err = resource_image_bpf__load(resource_skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF resource skeleton\n"); - goto cleanup; - } - - err = resource_image_bpf__attach(resource_skel); - if (err) { - fprintf(stderr, "Failed to attach BPF resource skeleton\n"); - goto cleanup; - } - - } - - - if(env.enable_syscall){ - syscall_skel = syscall_image_bpf__open(); - if(!syscall_skel) { - fprintf(stderr, "Failed to open BPF syscall skeleton\n"); - return 1; - } - - syscall_skel->rodata->target_pid = env.pid; - - err = syscall_image_bpf__load(syscall_skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF syscall skeleton\n"); - goto cleanup; - } - - err = syscall_image_bpf__attach(syscall_skel); - if (err) { - fprintf(stderr, "Failed to attach BPF syscall skeleton\n"); - goto cleanup; - } - - /* 设置环形缓冲区轮询 */ - //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 - syscall_rb = ring_buffer__new(bpf_map__fd(syscall_skel->maps.syscall_rb), print_syscall, NULL, NULL); - if (!syscall_rb) { - err = -1; - fprintf(stderr, "Failed to create syscall ring buffer\n"); - goto cleanup; - } - } - - if(env.enable_lock){ - lock_skel = lock_image_bpf__open(); - if (!lock_skel) { - fprintf(stderr, "Failed to open BPF lock skeleton\n"); - return 1; - } - - err = lock_image_bpf__load(lock_skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF lock skeleton\n"); - goto cleanup; - } - - /* 附加跟踪点处理程序 */ - err = lock_attach(lock_skel); - if (err) { - fprintf(stderr, "Failed to attach BPF lock skeleton\n"); - goto cleanup; - } - - /* 设置环形缓冲区轮询 */ - //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 - lock_rb = ring_buffer__new(bpf_map__fd(lock_skel->maps.lock_rb), print_lock, NULL, NULL); - if (!lock_rb) { - err = -1; - fprintf(stderr, "Failed to create lock ring buffer\n"); - goto cleanup; - } - } - - if(env.enable_keytime){ - keytime_skel = keytime_image_bpf__open(); - if (!keytime_skel) { - fprintf(stderr, "Failed to open BPF keytime skeleton\n"); - return 1; - } - - keytime_skel->rodata->target_pid = env.pid; - - err = keytime_image_bpf__load(keytime_skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF keytime skeleton\n"); - goto cleanup; - } - - /* 附加跟踪点处理程序 */ - err = keytime_attach(keytime_skel); - if (err) { - fprintf(stderr, "Failed to attach BPF keytime skeleton\n"); - goto cleanup; - } - - /* 设置环形缓冲区轮询 */ - //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 - keytime_rb = ring_buffer__new(bpf_map__fd(keytime_skel->maps.keytime_rb), print_keytime, NULL, NULL); - if (!keytime_rb) { - err = -1; - fprintf(stderr, "Failed to create keytime ring buffer\n"); - goto cleanup; - } - } - - /* 处理事件 */ - while (!exiting) { - // 等待新线程结束,回收资源 - if(env.exit_thread){ - env.exit_thread = false; - if (pthread_join(thread_enable, NULL) != 0) { - perror("pthread_join"); - exit(EXIT_FAILURE); - } - } - - // 创建新线程,设置 env.enable_output - if(!env.create_thread){ - if (pthread_create(&thread_enable, NULL, enable_function, NULL) != 0) { - perror("pthread_create"); - exit(EXIT_FAILURE); - } - } - - if(env.enable_resource && env.enable_output){ - err = print_resource(resource_skel->maps.total); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - break; - } - } - - if(env.enable_syscall){ - err = ring_buffer__poll(syscall_rb, 0); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling syscall ring buffer: %d\n", err); - break; - } - } - - if(env.enable_lock){ - err = ring_buffer__poll(lock_rb, 0); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling lock ring buffer: %d\n", err); - break; - } - } - - if(env.enable_keytime){ - err = ring_buffer__poll(keytime_rb, 0); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling keytime ring buffer: %d\n", err); - break; - } - } - } - -/* 卸载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); - - return err < 0 ? -err : 0; -} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/helpers.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/helpers.h similarity index 100% rename from eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/helpers.h rename to eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/helpers.h 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 e880aa983..45c8aa041 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 @@ -16,171 +16,51 @@ // // Variable definitions and help functions for keytime in the process -#include -#include -#include -#include "proc_image.h" - -const volatile int max_args = DEFAULT_MAXARGS; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1); - __type(key, pid_t); - __type(value, struct event); -} keytime SEC(".maps"); - -static int record_enter_execve(struct trace_event_raw_sys_enter* ctx, pid_t target_pid, void *events) -{ - struct task_struct *task = (struct task_struct *)bpf_get_current_task(); - int pid = BPF_CORE_READ(task,pid); - if(pid == target_pid){ - int ret; - int i; - struct event *event; - const char **args = (const char **)(ctx->args[1]); - const char *argp; - - if (bpf_map_update_elem(&keytime, &pid, &empty_event, BPF_NOEXIST)) - return 0; - - event = bpf_map_lookup_elem(&keytime, &pid); - if (!event) - return 0; - - event->type = 3; - event->pid = pid; - event->ppid = (pid_t)BPF_CORE_READ(task, real_parent, pid); - event->cpu_id = bpf_get_smp_processor_id(); - bpf_get_current_comm(&event->comm, sizeof(event->comm)); - event->start = bpf_ktime_get_ns(); - event->args_count = 0; - event->args_size = 0; - event->enable_char_args = true; - - ret = bpf_probe_read_user_str(event->args, ARGSIZE, (const char*)ctx->args[0]); - if (ret < 0) { - output_event(ctx,event,events); - return 0; - } - if (ret <= ARGSIZE) { - event->args_size += ret; - } else { - /* 写一个空字符串 */ - event->args[0] = '\0'; - event->args_size++; - } - - event->args_count++; - #pragma unroll - for (i = 1; i < TOTAL_MAX_ARGS && i < max_args; i++) { - ret = bpf_probe_read_user(&argp, sizeof(argp), &args[i]); - if (ret < 0){ - output_event(ctx,event,events); - return 0; - } - - if (event->args_size > LAST_ARG){ - output_event(ctx,event,events); - return 0; - } - - ret = bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp); - if (ret < 0){ - output_event(ctx,event,events); - return 0; - } - - event->args_count++; - event->args_size += ret; - } - /* 试着再读一个参数来检查是否有 */ - ret = bpf_probe_read_user(&argp, sizeof(argp), &args[max_args]); - if (ret < 0){ - output_event(ctx,event,events); - return 0; - } - - /* 指向max_args+1的指针不为空,假设我们有更多的参数 */ - event->args_count++; - - output_event(ctx,event,events); - } - - return 0; -} - -static int record_exit_execve(struct trace_event_raw_sys_exit* ctx, pid_t target_pid, void *events) +// 记录开始时间,并输出 +static int child_create(int type, pid_t child_pid, pid_t pid, void *child, void *keytime_rb) { - struct task_struct *task = (struct task_struct *)bpf_get_current_task(); - int pid = BPF_CORE_READ(task,pid); - if(pid == target_pid){ - int ret; - struct event *event; - - ret = ctx->ret; - if (ret < 0) - goto cleanup; - - event = bpf_map_lookup_elem(&keytime, &pid); - if (!event){ - if (bpf_map_update_elem(&keytime, &pid, &empty_event, BPF_NOEXIST)) - return 0; - - event = bpf_map_lookup_elem(&keytime, &pid); - if (!event) - return 0; - - event->type = 4; - event->pid = pid; - event->ppid = (pid_t)BPF_CORE_READ(task, real_parent, pid); - event->cpu_id = bpf_get_smp_processor_id(); - bpf_get_current_comm(&event->comm, sizeof(event->comm)); - event->exit = bpf_ktime_get_ns(); - event->retval = ret; - }else{ - event->type = 4; - event->exit = bpf_ktime_get_ns(); - event->retval = ret; - } - - output_event(ctx,event,events); - - cleanup: - bpf_map_delete_elem(&keytime, &pid); - } + struct child_info child_info = {}; + child_info.type = type; + child_info.ppid = pid; + if(bpf_map_update_elem(child, &child_pid, &child_info, BPF_ANY)) + return 0; + + struct keytime_event* e; + e = bpf_ringbuf_reserve(keytime_rb, sizeof(*e), 0); + if(!e) + return 0; + + e->type = type; + e->pid = pid; + e->enable_char_info = false; + e->info_count = 1; + e->info[0] = child_pid; + + bpf_ringbuf_submit(e, 0); return 0; } -static int record_exit(struct trace_event_raw_sys_enter* ctx, pid_t target_pid, void *events) +// 记录退出时间,并输出 +static int child_exit(void *child, void *keytime_rb) { - struct task_struct *task = (struct task_struct *)bpf_get_current_task(); - int pid = BPF_CORE_READ(task,pid); - if(pid == target_pid){ - struct event *event; - - if (bpf_map_update_elem(&keytime, &pid, &empty_event, BPF_NOEXIST)) - return 0; - - event = bpf_map_lookup_elem(&keytime, &pid); - if (!event) + pid_t child_pid = bpf_get_current_pid_tgid(); + struct child_info *child_info = bpf_map_lookup_elem(child, &child_pid); + if(child_info){ + struct keytime_event* e; + e = bpf_ringbuf_reserve(keytime_rb, sizeof(*e), 0); + if(!e) return 0; - - event->type = 5; - event->pid = pid; - event->ppid = (pid_t)BPF_CORE_READ(task, real_parent, pid); - event->cpu_id = bpf_get_smp_processor_id(); - bpf_get_current_comm(&event->comm, sizeof(event->comm)); - event->start = bpf_ktime_get_ns(); - event->enable_char_args = false; - event->args_count = 1; - event->ctx_args[0] = ctx->args[0]; - output_event(ctx,event,events); + e->type = child_info->type + 1; + e->pid = child_info->ppid; + e->enable_char_info = false; + e->info_count = 1; + e->info[0] = child_pid; - bpf_map_delete_elem(&keytime, &pid); + bpf_ringbuf_submit(e, 0); + bpf_map_delete_elem(child,&child_pid); } return 0; -} +} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lifecycle_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lifecycle_image.h deleted file mode 100644 index 52e719583..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/lifecycle_image.h +++ /dev/null @@ -1,175 +0,0 @@ -// 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 -// -// Variable definitions and help functions for lifecycle in the process - -#include -#include -#include -#include -#include "proc_image.h" - -static const struct event empty_event = {}; - -// 以便于对0号进程进行画像(0号进程是每cpu进程) -struct proc_id{ - int pid; - int cpu_id; -}; - -struct proc_oncpu{ - int oncpu_id; - long long unsigned int oncpu_time; -}; - -struct proc_offcpu{ - int offcpu_id; - long long unsigned int offcpu_time; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1); - __type(key, struct proc_id); - __type(value, struct proc_oncpu); -} oncpu SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1); - __type(key, struct proc_id); - __type(value, struct proc_offcpu); -} offcpu SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1); - __type(key, struct proc_id); - __type(value, struct event); -} cpu SEC(".maps"); - -static void output_event(void *ctx, struct event *event, void *events) -{ - size_t len = EVENT_SIZE(event); - if (len <= sizeof(*event)) - bpf_perf_event_output(ctx, events, BPF_F_CURRENT_CPU, event, len); -} - -static int record_cputime(void *ctx, struct task_struct *prev, struct task_struct *next, pid_t target_pid, int target_cpu_id, void *events) -{ - pid_t next_pid = BPF_CORE_READ(next,pid); - pid_t prev_pid = BPF_CORE_READ(prev,pid); - int cpu_id = bpf_get_smp_processor_id(); - - // 第一种情况:目标进程从offcpu转变为oncpu - if((target_pid!= 0 && prev_pid!= target_pid && next_pid==target_pid) || - (target_pid==0 && prev_pid!= target_pid && next_pid==target_pid && cpu_id==target_cpu_id)) - { - u64 oncpu_time = bpf_ktime_get_ns(); - struct proc_id proc_id = {}; - struct proc_offcpu * proc_offcpu; - - proc_id.pid = target_pid; - proc_id.cpu_id = target_cpu_id; - - proc_offcpu = bpf_map_lookup_elem(&offcpu, &proc_id); - if(proc_offcpu){ - // 完成一次cpu_event(offcpu)的输出 - struct event *cpu_event; - - if (bpf_map_update_elem(&cpu, &proc_id, &empty_event, BPF_NOEXIST)) - return 0; - - cpu_event = bpf_map_lookup_elem(&cpu, &proc_id); - if (!cpu_event) - return 0; - - cpu_event->type = 1; - cpu_event->pid = target_pid; - cpu_event->ppid = (pid_t)BPF_CORE_READ(next, real_parent, pid); - cpu_event->cpu_id = cpu_id; - for(int i = 0; i <= TASK_COMM_LEN - 1; i++){ - cpu_event->comm[i] = BPF_CORE_READ(next,comm[i]); - if (BPF_CORE_READ(next,comm[i]) == '\0') - break; - } - cpu_event->start = proc_offcpu->offcpu_time; - cpu_event->exit = oncpu_time; - - output_event(ctx,cpu_event,events); - - bpf_map_delete_elem(&cpu, &proc_id); - bpf_map_delete_elem(&offcpu, &proc_id); - } - - // 记录pro_oncpu - struct proc_oncpu proc_oncpu = {}; - - proc_oncpu.oncpu_id = cpu_id; - proc_oncpu.oncpu_time = oncpu_time; - - if(bpf_map_update_elem(&oncpu, &proc_id, &proc_oncpu, BPF_ANY)) - return 0; - - // 第二中情况:目标进程从oncpu转变为offcpu - }else if((target_pid!= 0 && prev_pid==target_pid && next_pid!=target_pid) || - (target_pid==0 && prev_pid==target_pid && next_pid!=target_pid && cpu_id==target_cpu_id)) - { - u64 offcpu_time = bpf_ktime_get_ns(); - struct proc_id proc_id = {}; - struct proc_oncpu * proc_oncpu; - - proc_id.pid = target_pid; - proc_id.cpu_id = target_cpu_id; - - proc_oncpu = bpf_map_lookup_elem(&oncpu, &proc_id); - if(proc_oncpu){ - // 完成一次cpu_event(oncpu)的输出 - struct event *cpu_event; - - if (bpf_map_update_elem(&cpu, &proc_id, &empty_event, BPF_NOEXIST)) - return 0; - - cpu_event = bpf_map_lookup_elem(&cpu, &proc_id); - if (!cpu_event) - return 0; - - cpu_event->type = 2; - cpu_event->pid = target_pid; - cpu_event->ppid = (pid_t)BPF_CORE_READ(prev, real_parent, pid); - cpu_event->cpu_id = cpu_id; - bpf_get_current_comm(&cpu_event->comm, sizeof(cpu_event->comm)); - cpu_event->start = proc_oncpu->oncpu_time; - cpu_event->exit = offcpu_time; - - output_event(ctx,cpu_event,events); - - bpf_map_delete_elem(&cpu, &proc_id); - bpf_map_delete_elem(&oncpu, &proc_id); - } - - // 记录pro_offcpu - struct proc_offcpu proc_offcpu = {}; - - proc_offcpu.offcpu_id = cpu_id; - proc_offcpu.offcpu_time = offcpu_time; - - if(bpf_map_update_elem(&offcpu, &proc_id, &proc_offcpu, BPF_ANY)) - return 0; - } - - return 0; -} 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 3a4b8e49b..de9c6c73d 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,185 +16,127 @@ // // Variable definitions and help functions for lock in the process -#include -#include -#include -#include -#include "proc_image.h" - -struct proc_flag{ - int pid; - // 1代表用户态互斥锁 - // 2代表内核态互斥锁 - // 3代表用户态读写锁 - int flag; -}; - -struct proc_lockptr{ - int pid; - long long unsigned int lock_ptr; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1024); - __type(key, struct proc_flag); - __type(value, u64); -} proc_lock SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1024); - __type(key, struct proc_flag); - __type(value, u64); -} proc_unlock SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1024); - __type(key, struct proc_lockptr); - __type(value, struct event); -} lock SEC(".maps"); - -static int record_lock_enter(void *ctx,int type,int flag,void *__lock,int target_pid,void *events) +static int record_lock_enter(int lock_status,int flag,void *__lock,void *lock_rb,void *proc_lock) { - pid_t pid = target_pid; - struct task_struct *current = (struct task_struct *)bpf_get_current_task(); - - if(BPF_CORE_READ(current,pid) == pid) - { - u64 lock_ptr = (u64)__lock; - struct proc_lockptr proc_lockptr = {}; - struct proc_flag proc_flag = {}; - struct event *event; - - proc_flag.pid = pid; - proc_flag.flag = flag; - - if(bpf_map_update_elem(&proc_lock, &proc_flag, &lock_ptr, BPF_ANY)) - return 0; - - proc_lockptr.pid = pid; - proc_lockptr.lock_ptr = lock_ptr; - - - if (bpf_map_update_elem(&lock, &proc_lockptr, &empty_event, BPF_NOEXIST)) - return 0; - - event = bpf_map_lookup_elem(&lock, &proc_lockptr); - if (!event) - return 0; - - event->type = type; - event->pid = pid; - event->ppid = (pid_t)BPF_CORE_READ(current, real_parent, pid); - event->cpu_id = bpf_get_smp_processor_id(); - bpf_get_current_comm(&event->comm, sizeof(event->comm)); - event->start = bpf_ktime_get_ns(); - event->enable_char_args = false; - event->args_count = 1; - event->ctx_args[0] = lock_ptr; - - output_event(ctx,event,events); - } + pid_t pid = bpf_get_current_pid_tgid(); + u64 lock_ptr = (u64)__lock; + struct proc_flag proc_flag = {}; + + proc_flag.pid = pid; + proc_flag.flag = flag; + if(bpf_map_update_elem(proc_lock, &proc_flag, &lock_ptr, BPF_ANY)) + return 0; + + struct lock_event* e; + e = bpf_ringbuf_reserve(lock_rb, sizeof(*e), 0); + if(!e) + return 0; + + e->lock_status = lock_status; + e->pid = pid; + e->lock_ptr = lock_ptr; + e->time = bpf_ktime_get_ns(); + + bpf_ringbuf_submit(e, 0); return 0; } -static int record_lock_exit(void *ctx,int flag,int ret,int target_pid,void *events) +static int record_lock_exit(int lock_status,int flag,int ret,void *lock_rb,void *proc_lock,void *locktype) { - pid_t pid = target_pid; - struct task_struct *current = (struct task_struct *)bpf_get_current_task(); + pid_t pid = bpf_get_current_pid_tgid(); + u64 *lock_ptr; + u64 temp_lock_ptr; + struct proc_flag proc_flag = {}; - if(BPF_CORE_READ(current,pid) == pid) - { - u64 *lock_ptr; - struct proc_lockptr proc_lockptr = {}; - struct event *event; - struct proc_flag proc_flag = {}; + proc_flag.pid = pid; + proc_flag.flag = flag; - proc_flag.pid = pid; - proc_flag.flag = flag; + lock_ptr = bpf_map_lookup_elem(proc_lock, &proc_flag); + if(!lock_ptr) + return 0; + temp_lock_ptr = *lock_ptr; + bpf_map_delete_elem(proc_lock, &proc_flag); - lock_ptr = bpf_map_lookup_elem(&proc_lock, &proc_flag); - if(!lock_ptr) - return 0; + if((lock_status==5 || lock_status==8) && ret==0){ + int type; - proc_lockptr.pid = pid; - proc_lockptr.lock_ptr = *lock_ptr; + if(lock_status == 5) type= 1; + else type= 2; - event = bpf_map_lookup_elem(&lock, &proc_lockptr); - if(!event) + if(bpf_map_update_elem(locktype, &temp_lock_ptr, &type, BPF_ANY)) return 0; + } - event->type ++; - event->exit = bpf_ktime_get_ns(); - event->retval = ret; - - output_event(ctx,event,events); - - event->start = event->exit; + struct lock_event* e; + e = bpf_ringbuf_reserve(lock_rb, sizeof(*e), 0); + if(!e) + return 0; - bpf_map_delete_elem(&proc_lock, &proc_flag); - } + e->lock_status = lock_status; + e->pid = pid; + e->ret = ret; + e->lock_ptr = temp_lock_ptr; + e->time = bpf_ktime_get_ns(); + + bpf_ringbuf_submit(e, 0); return 0; } -static int record_unlock_enter(int flag,void *__lock,int target_pid) +static int record_unlock_enter(int flag,void *__lock,void *proc_unlock) { - pid_t pid = target_pid; - struct task_struct *current = (struct task_struct *)bpf_get_current_task(); + pid_t pid = bpf_get_current_pid_tgid(); + u64 lock_ptr = (u64)__lock; + struct proc_flag proc_flag = {}; - if(BPF_CORE_READ(current,pid) == pid) - { - u64 lock_ptr = (u64)__lock; - struct proc_flag proc_flag = {}; + proc_flag.pid = pid; + proc_flag.flag = flag; - proc_flag.pid = pid; - proc_flag.flag = flag; - - if(bpf_map_update_elem(&proc_unlock, &proc_flag, &lock_ptr, BPF_ANY)) - return 0; - } + bpf_map_update_elem(proc_unlock, &proc_flag, &lock_ptr, BPF_ANY); return 0; } -static int record_unlock_exit(void *ctx,int flag,int target_pid,void *events) +static int record_unlock_exit(int lock_status,int flag,void *lock_rb,void *proc_unlock,void *locktype) { - pid_t pid = target_pid; - struct task_struct *current = (struct task_struct *)bpf_get_current_task(); - - if(BPF_CORE_READ(current,pid) == pid) - { - u64 *lock_ptr; - struct proc_lockptr proc_lockptr = {}; - struct event *event; - struct proc_flag proc_flag = {}; - - proc_flag.pid = pid; - proc_flag.flag = flag; - - lock_ptr = bpf_map_lookup_elem(&proc_unlock, &proc_flag); - if(!lock_ptr) - return 0; - - proc_lockptr.pid = pid; - proc_lockptr.lock_ptr = *lock_ptr; - - event = bpf_map_lookup_elem(&lock, &proc_lockptr); - if(!event) + pid_t pid = bpf_get_current_pid_tgid(); + u64 *lock_ptr; + u64 temp_lock_ptr; + struct proc_flag proc_flag = {}; + + proc_flag.pid = pid; + proc_flag.flag = flag; + + lock_ptr = bpf_map_lookup_elem(proc_unlock, &proc_flag); + if(!lock_ptr) + return 0; + temp_lock_ptr = *lock_ptr; + bpf_map_delete_elem(proc_unlock, &proc_flag); + + if(lock_status ==0){ + int *type; + + type = bpf_map_lookup_elem(locktype, &temp_lock_ptr); + if(!type) return 0; - event->type ++; - event->exit = bpf_ktime_get_ns(); - - output_event(ctx,event,events); - - bpf_map_delete_elem(&proc_unlock, &proc_flag); - - bpf_map_delete_elem(&lock, &proc_lockptr); + + if(*type == 1) lock_status = 6; + else if(*type == 2) lock_status = 9; + bpf_map_delete_elem(locktype, &temp_lock_ptr); } + + struct lock_event* e; + e = bpf_ringbuf_reserve(lock_rb, sizeof(*e), 0); + if(!e) + return 0; + + e->lock_status = lock_status; + e->pid = pid; + e->lock_ptr = temp_lock_ptr; + e->time = bpf_ktime_get_ns(); + + bpf_ringbuf_submit(e, 0); return 0; -} +} \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/newlife_image.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/newlife_image.h deleted file mode 100644 index 03b5274de..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/newlife_image.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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 -// -// Variable definitions and help functions for newlife in the process - -#include -#include -#include -#include -#include "proc_image.h" - -struct bind_pid{ - int pid; - int newlife_pid; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 1024); - __type(key, struct bind_pid); - __type(value, struct event); -} newlife SEC(".maps"); - -// 记录开始时间,并输出 -static int newlife_create(void *ctx, int type, pid_t newlife_pid, pid_t target_pid, void *events) -{ - struct bind_pid bind_pid = {}; - struct event *event; - - bind_pid.pid = target_pid; - bind_pid.newlife_pid = newlife_pid; - - if (bpf_map_update_elem(&newlife, &bind_pid, &empty_event, BPF_NOEXIST)) - return 0; - - event = bpf_map_lookup_elem(&newlife, &bind_pid); - if (!event) - return 0; - - event->type = type; - event->pid = newlife_pid; - event->ppid = target_pid; - event->cpu_id = bpf_get_smp_processor_id(); -// bpf_get_current_comm(&event->comm, sizeof(event->comm)); - event->start = bpf_ktime_get_ns(); - - output_event(ctx,event,events); - - return 0; -} - -// 记录退出时间,并输出 -static int newlife_exit(void *ctx, pid_t target_pid, void *events) -{ - struct bind_pid bind_pid = {}; - struct event *event; - - bind_pid.pid = target_pid; - bind_pid.newlife_pid = bpf_get_current_pid_tgid(); - - event = bpf_map_lookup_elem(&newlife, &bind_pid); - if(!event) - return 0; - - event->type ++; - event->exit = bpf_ktime_get_ns(); - - output_event(ctx,event,events); - - bpf_map_delete_elem(&newlife, &bind_pid); - - return 0; -} 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 6bf701a07..1d383cb11 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 @@ -19,40 +19,85 @@ #ifndef __PROC_IMAGE_H #define __PROC_IMAGE_H +#define MAX_SYSCALL_COUNT 116 #define ARGSIZE 128 -#define TASK_COMM_LEN 16 #define TOTAL_MAX_ARGS 60 #define DEFAULT_MAXARGS 20 -#define FULL_MAX_ARGS_ARR (TOTAL_MAX_ARGS * ARGSIZE) -#define BASE_EVENT_SIZE (size_t)(&((struct event*)0)->args) -#define EVENT_SIZE(e) (BASE_EVENT_SIZE + e->args_size) +#define FULL_MAX_ARGS_ARR 440 #define LAST_ARG (FULL_MAX_ARGS_ARR - ARGSIZE) -struct event { - /* type: - 1代表on_cpu;2代表off_cpu; - 3代表exec_enter;4代表exec_exit;5代表exit - 6代表umutex_req;7代表umutex_lock;8代表umutex_unlock - 9代表kmutex_req;10代表kmutex_lock;11代表kmutex_unlock - 12代表rdlock_req;13代表rdlock_lock;14代表rdlock_unlock - 15代表wrlock_req;16代表wrlock_lock;17代表wrlock_unlock - 18代表fork_begin;19代表fork_end - 20代表vfork_begin;21代表vfork_end - 22代表pthread_begin;23代表pthread_end +// resource_image +struct proc_id{ + int pid; + int cpu_id; +}; + +struct start_rsc{ + long long unsigned int time; + long long unsigned int readchar; + long long unsigned int writechar; +}; + +struct total_rsc{ + int pid; + int cpu_id; + long long unsigned int time; + long unsigned int memused; + long long unsigned int readchar; + long long unsigned int writechar; +}; + +//syscall_image +struct syscall_seq{ + int pid; + long long unsigned int oncpu_time; + long long unsigned int offcpu_time; + int count; // 若count值超过MAX_SYSCALL_COUNT,则record_syscall数组最后一个元素的值用-1表示以作说明 + int record_syscall[MAX_SYSCALL_COUNT]; +}; + +// lock_image +struct proc_flag{ + int pid; + // 1代表用户态互斥锁 + // 2代表用户态读写锁 + int flag; +}; + +struct lock_event{ + /* lock_status: + 1代表mutex_req;2代表mutex_lock;3代表mutex_unlock + 4代表rdlock_req;5代表rdlock_lock;6代表rdlock_unlock + 7代表wrlock_req;8代表wrlock_lock;9代表wrlock_unlock */ + int lock_status; + int pid; + int ret; + long long unsigned int lock_ptr; + long long unsigned int time; +}; + +// keytime_image +struct child_info{ + int type; + int ppid; +}; + +struct keytime_event{ + /* type: + 1代表exec_enter;2代表exec_exit + 3代表exit + 4代表forkP_enter;5代表forkP_exit + 6代表vforkP_enter;7代表vforkP_exit + 8代表createT_enter;9代表createT_exit + */ int type; - pid_t pid; - pid_t ppid; - int cpu_id; - char comm[TASK_COMM_LEN]; - long long unsigned int start; - long long unsigned int exit; - int retval; - bool enable_char_args; - int args_count; - long long unsigned int ctx_args[6]; - unsigned int args_size; - char args[FULL_MAX_ARGS_ARR]; + int pid; + bool enable_char_info; + int info_count; + long long unsigned int info[6]; + unsigned int info_size; + char char_info[FULL_MAX_ARGS_ARR]; }; -#endif /* __PROC_IMAGE_H */ \ No newline at end of file +#endif /* __PROCESS_H */ \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/vmlinux.h b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/vmlinux.h similarity index 100% rename from eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/developing/include/vmlinux.h rename to eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/include/vmlinux.h diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.bpf.c b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.bpf.c deleted file mode 100644 index 3b0a86ca7..000000000 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.bpf.c +++ /dev/null @@ -1,396 +0,0 @@ -// 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 -// -// kernel-mode code for the process image - -#include -#include -#include -#include -#include "include/proc_image.h" -#include "include/lifecycle_image.h" -#include "include/keytime_image.h" -#include "include/lock_image.h" -#include "include/newlife_image.h" - -char LICENSE[] SEC("license") = "Dual BSD/GPL"; - -const volatile pid_t target_pid = 0; -const volatile int target_cpu_id = 0; - -/* lifecycle_image */ -const volatile bool enable_cputime = false; - -/* keytime_image */ -const volatile bool enable_execve = false; -const volatile bool enable_exit = false; - -/* lock_image */ -const volatile bool enable_u_mutex = false; -const volatile bool enable_k_mutex = false; -const volatile bool enable_u_rwlock_rd = false; -const volatile bool enable_u_rwlock_wr = false; - -/* newlife_image */ -const volatile bool enable_fork = false; -const volatile bool enable_vfork = false; -const volatile bool enable_newthread = false; - -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u32)); -} events SEC(".maps"); - -/* lifecycle_image */ -SEC("tp_btf/sched_switch") -int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_struct *next) -{ - if(enable_cputime){ - record_cputime(ctx, prev, next, target_pid, target_cpu_id, &events); - } - - return 0; -} - -/* keytime_image */ -SEC("tracepoint/syscalls/sys_enter_execve") -int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx) -{ - if(enable_execve){ - record_enter_execve(ctx, target_pid, &events); - } - - return 0; -} - -SEC("tracepoint/syscalls/sys_exit_execve") -int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) -{ - if(enable_execve){ - record_exit_execve(ctx, target_pid, &events); - } - - return 0; -} - -SEC("tracepoint/syscalls/sys_enter_exit_group") -int tracepoint__syscalls__sys_enter_exit_group(struct trace_event_raw_sys_enter* ctx) -{ - if(enable_exit){ - record_exit(ctx, target_pid, &events); - } - - /* newlife_image,记录 fork 和 vfork 子进程的退出时间,并输出 */ - if(enable_fork || enable_vfork){ - newlife_exit(ctx,target_pid,&events); - } - - return 0; -} - -SEC("tracepoint/syscalls/sys_enter_exit") -int tracepoint__syscalls__sys_enter_exit(struct trace_event_raw_sys_enter* ctx) -{ - if(enable_exit){ - record_exit(ctx, target_pid, &events); - } - - /* newlife_image,// 记录 pthread_create 新线程的退出时间,并输出 */ - if(enable_newthread){ - newlife_exit(ctx,target_pid,&events); - } - - return 0; -} - -/* lock_image */ -// 用户态互斥锁 -SEC("uprobe/pthread_mutex_lock") -int BPF_KPROBE(pthread_mutex_lock_enter, void *__mutex) -{ - if(enable_u_mutex){ - record_lock_enter(ctx,6,1,__mutex,target_pid,&events); - } - - return 0; -} - -SEC("uretprobe/pthread_mutex_lock") -int BPF_KRETPROBE(pthread_mutex_lock_exit,int ret) -{ - if(enable_u_mutex){ - record_lock_exit(ctx,1,ret,target_pid,&events); - } - - return 0; -} - -SEC("uprobe/__pthread_mutex_trylock") -int BPF_KPROBE(__pthread_mutex_trylock_enter, void *__mutex) -{ - if(enable_u_mutex){ - record_lock_enter(ctx,6,1,__mutex,target_pid,&events); - } - - return 0; -} - -SEC("uretprobe/__pthread_mutex_trylock") -int BPF_KRETPROBE(__pthread_mutex_trylock_exit,int ret) -{ - if(enable_u_mutex){ - record_lock_exit(ctx,1,ret,target_pid,&events); - } - - return 0; -} - -SEC("uprobe/pthread_mutex_unlock") -int BPF_KPROBE(pthread_mutex_unlock_enter, void *__rwlock) -{ - if(enable_u_mutex){ - record_unlock_enter(1,__rwlock,target_pid); - } - - return 0; -} - -SEC("uretprobe/pthread_mutex_unlock") -int BPF_KRETPROBE(pthread_mutex_unlock_exit) -{ - if(enable_u_mutex){ - record_unlock_exit(ctx,1,target_pid,&events); - } - - return 0; -} - -// 内核态互斥锁 -SEC("kprobe/mutex_lock") -int kprobe__mutex_lock(struct pt_regs *ctx) -{ - if(enable_k_mutex){ - struct mutex *lock = (struct mutex *)PT_REGS_PARM1(ctx); - record_lock_enter(ctx,9,2,lock,target_pid,&events); - } - - return 0; -} - -SEC("kretprobe/mutex_lock") -int kretprobe__mutex_lock(struct pt_regs *ctx) -{ - if(enable_k_mutex){ - record_lock_exit(ctx,2,0,target_pid,&events); - } - - return 0; -} - -SEC("kprobe/mutex_trylock") -int kprobe__mutex_trylock(struct pt_regs *ctx) -{ - if(enable_k_mutex){ - struct mutex *lock = (struct mutex *)PT_REGS_PARM1(ctx); - record_lock_enter(ctx,9,2,lock,target_pid,&events); - } - - return 0; -} - -SEC("kretprobe/mutex_trylock") -int kretprobe__mutex_trylock(struct pt_regs *ctx) -{ - if(enable_k_mutex){ - record_lock_exit(ctx,2,0,target_pid,&events); - } - - return 0; -} - -SEC("kprobe/mutex_unlock") -int kprobe__mutex_unlock(struct pt_regs *ctx) -{ - if(enable_k_mutex){ - struct mutex *lock = (struct mutex *)PT_REGS_PARM1(ctx); - record_unlock_enter(2,lock,target_pid); - } - - return 0; -} - -SEC("kretprobe/mutex_unlock") -int kretprobe__mutex_unlock(struct pt_regs *ctx) -{ - if(enable_k_mutex){ - record_unlock_exit(ctx,2,target_pid,&events); - } - - return 0; -} - -// 用户态读写锁 -SEC("uprobe/__pthread_rwlock_rdlock") -int BPF_KPROBE(__pthread_rwlock_rdlock_enter, void *__rwlock) -{ - if(enable_u_rwlock_rd){ - record_lock_enter(ctx,12,3,__rwlock,target_pid,&events); - } - - return 0; -} - -SEC("uretprobe/__pthread_rwlock_rdlock") -int BPF_KRETPROBE(__pthread_rwlock_rdlock_exit,int ret) -{ - if(enable_u_rwlock_rd){ - record_lock_exit(ctx,3,ret,target_pid,&events); - } - - return 0; -} - -SEC("uprobe/__pthread_rwlock_tryrdlock") -int BPF_KPROBE(__pthread_rwlock_tryrdlock_enter, void *__rwlock) -{ - if(enable_u_rwlock_rd){ - record_lock_enter(ctx,12,3,__rwlock,target_pid,&events); - } - - return 0; -} - -SEC("uretprobe/__pthread_rwlock_tryrdlock") -int BPF_KRETPROBE(__pthread_rwlock_tryrdlock_exit,int ret) -{ - if(enable_u_rwlock_rd){ - record_lock_exit(ctx,3,ret,target_pid,&events); - } - - return 0; -} - -SEC("uprobe/__pthread_rwlock_wrlock") -int BPF_KPROBE(__pthread_rwlock_wrlock_enter, void *__rwlock) -{ - if(enable_u_rwlock_wr){ - record_lock_enter(ctx,15,3,__rwlock,target_pid,&events); - } - - return 0; -} - -SEC("uretprobe/__pthread_rwlock_wrlock") -int BPF_KRETPROBE(__pthread_rwlock_wrlock_exit,int ret) -{ - if(enable_u_rwlock_wr){ - record_lock_exit(ctx,3,ret,target_pid,&events); - } - - return 0; -} - -SEC("uprobe/__pthread_rwlock_trywrlock") -int BPF_KPROBE(__pthread_rwlock_trywrlock_enter, void *__rwlock) -{ - if(enable_u_rwlock_wr){ - record_lock_enter(ctx,15,3,__rwlock,target_pid,&events); - } - - return 0; -} - -SEC("uretprobe/__pthread_rwlock_trywrlock") -int BPF_KRETPROBE(__pthread_rwlock_trywrlock_exit,int ret) -{ - if(enable_u_rwlock_wr){ - record_lock_exit(ctx,3,ret,target_pid,&events); - } - - return 0; -} - -SEC("uprobe/__pthread_rwlock_unlock") -int BPF_KPROBE(__pthread_rwlock_unlock_enter, void *__rwlock) -{ - if(enable_u_rwlock_rd || enable_u_rwlock_wr){ - record_unlock_enter(3,__rwlock,target_pid); - } - - return 0; -} - -SEC("uretprobe/__pthread_rwlock_unlock") -int BPF_KRETPROBE(__pthread_rwlock_unlock_exit) -{ - if(enable_u_rwlock_rd || enable_u_rwlock_wr){ - record_unlock_exit(ctx,3,target_pid,&events); - } - - return 0; -} - -/* newlife_image */ -// 记录 fork 子进程的开始时间,并输出 -SEC("uretprobe/fork") -int BPF_KRETPROBE(fork_exit,int ret) -{ - if(enable_fork){ - // 判断是否为子进程触发 - if(ret != 0) return 0; - - pid_t child_pid = bpf_get_current_pid_tgid(); - newlife_create(ctx,18,child_pid,target_pid,&events); - } - - return 0; -} - -// 记录 vfork 子进程的开始时间,并输出 -SEC("uretprobe/vfork") -int BPF_KRETPROBE(vfork_exit,int ret) -{ - if(enable_vfork){ - // 判断是否为子进程触发 - if(ret != 0) return 0; - - pid_t child_pid = bpf_get_current_pid_tgid(); - newlife_create(ctx,20,child_pid,target_pid,&events); - } - - return 0; -} - -// 记录 pthread_create 新线程的开始时间,并输出 -SEC("tracepoint/syscalls/sys_exit_clone3") -int tracepoint__syscalls__sys_exit_clone3(struct trace_event_raw_sys_exit* ctx) -{ - if(enable_newthread){ - pid_t current = bpf_get_current_pid_tgid(); - - if(current == target_pid) - { - pid_t new_thread = ctx->ret; - // 排除clone3错误返回的情况 - if(new_thread <= 0) return 0; - - newlife_create(ctx,22,new_thread,target_pid,&events); - } - } - - return 0; -} \ No newline at end of file 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 3ab28b586..cd9bc28c4 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c @@ -25,117 +25,75 @@ #include #include #include +#include #include #include -#include "include/proc_image.h" -#include "proc_image.skel.h" - -#define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ - do \ - { \ - LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, \ - .retprobe = is_retprobe, \ - .func_name = #sym_name); \ - skel->links.prog_name = bpf_program__attach_uprobe_opts( \ - skel->progs.prog_name, \ - env.pid, \ - object, \ - 0, \ - &uprobe_opts); \ - } while (false) - -#define __CHECK_PROGRAM(skel, prog_name) \ - do \ - { \ - if (!skel->links.prog_name) \ - { \ - fprintf(stderr, "[%s] no program attached for" #prog_name "\n", strerror(errno)); \ - return -errno; \ - } \ - } while (false) - -#define __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, is_retprobe) \ - do \ - { \ - __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe); \ - __CHECK_PROGRAM(skel, prog_name); \ - } while (false) - -#define ATTACH_UPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, false) -#define ATTACH_URETPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, true) - -#define ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, false) -#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, true) - -#define CHECK_ERR(cond, info) \ - if (cond) \ - { \ - fprintf(stderr, "[%s]" info "\n", strerror(errno)); \ - return -1; \ - } - -#define PERF_BUFFER_PAGES 64 -#define PERF_POLL_TIMEOUT_MS 100 -#define warn(...) fprintf(stderr, __VA_ARGS__) - +#include "proc_image.h" +#include "resource_image.skel.h" +#include "syscall_image.skel.h" +#include "lock_image.skel.h" +#include "keytime_image.skel.h" +#include "helpers.h" + +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 time; - int cpu_id; - bool enable_cputime; - bool enable_execve; - bool enable_exit; - bool quote; - int max_args; - bool enable_u_mutex; - bool enable_k_mutex; - bool enable_u_rwlock_rd; - bool enable_u_rwlock_wr; - bool enable_fork; - bool enable_vfork; - bool enable_newthread; + int pid; + int cpu_id; + int time; + bool enable_output; + bool create_thread; + bool exit_thread; + bool enable_resource; + bool first_rsc; + bool enable_syscall; + bool enable_lock; + bool quote; + int max_args; + bool enable_keytime; } env = { - .pid = 0, - .time = 0, - .cpu_id = 0, - .enable_cputime = false, - .enable_execve = false, - .enable_exit = false, + .pid = -1, + .cpu_id = -1, + .time = 0, + .enable_output = false, + .create_thread = false, + .exit_thread = false, + .enable_resource = false, + .first_rsc = true, + .enable_syscall = false, + .enable_lock = false, .quote = false, .max_args = DEFAULT_MAXARGS, - .enable_u_mutex = false, - .enable_k_mutex = false, - .enable_u_rwlock_rd = false, - .enable_u_rwlock_wr = false, - .enable_fork = false, - .enable_vfork = false, - .enable_newthread = false, + .enable_keytime = false, }; +static struct timespec prevtime; +static struct timespec currentime; + +char *lock_status[] = {"", "mutex_req", "mutex_lock", "mutex_unlock", + "rdlock_req", "rdlock_lock", "rdlock_unlock", + "wrlock_req", "wrlock_lock", "wrlock_unlock"}; + +char *keytime_type[] = {"", "exec_enter", "exec_exit", + "exit", + "forkP_enter", "forkP_exit", + "vforkP_enter", "vforkP_exit", + "createT_enter", "createT_exit"}; + 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" }, + { "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)" }, - { "cpuid", 'C', "CPUID", 0, "Set For Tracing per-CPU Process(other processes don't need to set this parameter)" }, - { "cputime", 'c', NULL, 0, "Process on_off_CPU time information" }, - { "execve", 'e', NULL, 0, "Trace execve syscall of the process" }, - { "exit", 'E', NULL, 0, "Trace exit syscall of the process" }, + { "all", 'a', NULL, 0, "Start all functions" }, + { "resource", 'r', NULL, 0, "Collects resource usage information about processes" }, + { "syscall", 's', NULL, 0, "Collects syscall sequence information about processes" }, + { "lock", 'l', NULL, 0, "Collects lock information about processes" }, { "quote", 'q', NULL, 0, "Add quotemarks (\") around arguments" }, - { "keytime", 'K',NULL, 0, "Trace process key time" }, - { "user-mutex", 'm', NULL, 0, "process user mutex image" }, - { "kernel-mutex", 'M', NULL, 0, "process kernel mutex image" }, - { "user-rwlock-rd", 'r', NULL, 0, "process user rwlock image in read mode" }, - { "user-rwlock-wr", 'w', NULL, 0, "process user rwlock image in write mode" }, - { "lock", 'L', NULL, 0, "Trace process lock information" }, - { "fork", 'f', NULL, 0, "the child process image of fork" }, - { "vfork", 'F', NULL, 0, "the child process image of vfork" }, - { "newthread", 'T', NULL, 0, "the new thread image" }, - { "child", 'S',NULL, 0, "Trace process child information" }, - { "all", 'A',NULL, 0, "Enable all functions for process image" }, - { NULL, 'h', NULL, OPTION_HIDDEN, "show the full help" }, + { "keytime", 'k', NULL, 0, "Collects keytime information about processes" }, + { NULL, 'h', NULL, OPTION_HIDDEN, "show the full help" }, {}, }; @@ -154,11 +112,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) } env.pid = pid; break; - case 't': - env.time = strtol(arg, NULL, 10); - if(env.time) alarm(env.time); - break; - case 'C': + case 'c': cpu_id = strtol(arg, NULL, 10); if(cpu_id < 0){ warn("Invalid CPUID: %s\n", arg); @@ -166,80 +120,159 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) } env.cpu_id = cpu_id; break; - case 'c': - env.enable_cputime = true; - break; - case 'e': - env.enable_execve = true; - break; - case 'E': - env.enable_exit = true; + case 't': + env.time = strtol(arg, NULL, 10); + if(env.time) alarm(env.time); break; - case 'q': - env.quote = true; + case 'a': + env.enable_resource = true; + env.enable_syscall = true; + env.enable_lock = true; + env.enable_keytime = true; break; - case 'K': - env.enable_execve = true; - env.enable_exit = true; + case 'r': + env.enable_resource = true; break; - case 'm': - env.enable_u_mutex = true; - break; - case 'M': - env.enable_k_mutex = true; - break; - case 'r': - env.enable_u_rwlock_rd = true; - break; - case 'w': - env.enable_u_rwlock_wr = true; - break; - case 'L': - env.enable_u_mutex = true; - env.enable_k_mutex = true; - env.enable_u_rwlock_rd = true; - env.enable_u_rwlock_wr = true; - break; - case 'f': - env.enable_fork = true; - break; - case 'F': - env.enable_vfork = true; - break; - case 'T': - env.enable_newthread = true; - break; - case 'S': - env.enable_fork = true; - env.enable_vfork = true; - env.enable_newthread = true; + case 's': + env.enable_syscall = true; + break; + case 'l': + env.enable_lock = true; break; - case 'A': - env.enable_cputime = true; - env.enable_execve = true; - env.enable_exit = true; - env.enable_u_mutex = true; - env.enable_k_mutex = true; - env.enable_u_rwlock_rd = true; - env.enable_u_rwlock_wr = true; - env.enable_fork = true; - env.enable_vfork = true; - env.enable_newthread = true; + case 'q': env.quote = true; break; + case 'k': + env.enable_keytime = true; + break; case 'h': argp_state_help(state, stderr, ARGP_HELP_STD_HELP); break; - default: + default: return ARGP_ERR_UNKNOWN; } return 0; } -static void sig_handler(int signo) +static int print_resource(struct bpf_map *map) +{ + struct proc_id lookup_key = {-1}, next_key; + int err, fd = bpf_map__fd(map); + + if(env.first_rsc){ + env.first_rsc = false; + goto delete_elem; + } + + struct total_rsc event; + float pcpu,pmem; + double read_rate,write_rate; + unsigned long memtotal = sysconf(_SC_PHYS_PAGES); + time_t now = time(NULL); + struct tm *localTime = localtime(&now); + int hour = localTime->tm_hour; + int min = localTime->tm_min; + int sec = localTime->tm_sec; + long long unsigned int interval; + + while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { + if(prev_image != RESOURCE_IMAGE){ + printf("RESOURCE------------------------------------------------------------\n"); + printf("%-8s %-6s %-6s %-6s %-6s %-12s %-12s\n","TIME","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); + return -1; + } + + clock_gettime(CLOCK_REALTIME, ¤time); + interval = currentime.tv_nsec-prevtime.tv_nsec+(currentime.tv_sec-prevtime.tv_sec)*1000000000; + + if(interval>0 && memtotal>0 && event.time>0){ + pcpu = (100.0*event.time)/interval; + pmem = (100.0*event.memused)/memtotal; + read_rate = (1.0*event.readchar)/1024/((1.0*event.time)/1000000000); // kb/s + write_rate = (1.0*event.writechar)/1024/((1.0*event.time)/1000000000); // kb/s + }else{ + goto next_elem; + } + + if(pcpu<=100 && pmem<=100){ + printf("%02d:%02d:%02d %-6d %-6d %-6.3f %-6.3f %-12.2lf %-12.2lf\n", + hour,min,sec,event.pid,event.cpu_id,pcpu,pmem,read_rate,write_rate); + } + +next_elem: + lookup_key = next_key; + } + +delete_elem: + lookup_key.pid = -1; + lookup_key.cpu_id = -1; + while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { + err = bpf_map_delete_elem(fd, &next_key); + if (err < 0) { + fprintf(stderr, "failed to cleanup infos: %d\n", err); + return -1; + } + lookup_key = next_key; + } + + // 获取当前高精度时间 + clock_gettime(CLOCK_REALTIME, &prevtime); + env.enable_output = false; + + return 0; +} + +static int print_syscall(void *ctx, void *data,unsigned long data_sz) { - exiting = 1; + const struct syscall_seq *e = data; + int count = e->count; + + if(count == 0) return 0; + + if(prev_image != SYSCALL_IMAGE){ + printf("SYSCALL-------------------------------------------------------------\n"); + printf("%-29s %-6s %-8s\n","TIME(oncpu-offcpu)","PID","SYSCALLS"); + + prev_image = SYSCALL_IMAGE; + } + + printf("%-14lld-%14lld %-6d ",e->oncpu_time,e->offcpu_time,e->pid); + for(int i=0; irecord_syscall[i]); + else printf("%d,",e->record_syscall[i]); + } + + putchar('\n'); + + return 0; +} + +static int print_lock(void *ctx, void *data,unsigned long data_sz) +{ + const struct lock_event *e = data; + + if(prev_image != LOCK_IMAGE){ + printf("USERLOCK------------------------------------------------------------\n"); + printf("%-14s %-6s %-15s %s\n","TIME","PID","LockAddr","LockStatus"); + + prev_image = LOCK_IMAGE; + } + + printf("%-14lld %-6d %-15lld ",e->time,e->pid,e->lock_ptr); + if(e->lock_status==2 || e->lock_status==5 || e->lock_status==8){ + printf("%s-%d\n",lock_status[e->lock_status],e->ret); + }else{ + printf("%s\n",lock_status[e->lock_status]); + } + + return 0; } static void inline quoted_symbol(char c) { @@ -262,22 +295,22 @@ static void inline quoted_symbol(char c) { } } -static void print_args1(const struct event *e, bool quote) +static void print_info1(const struct keytime_event *e) { int i, args_counter = 0; if (env.quote) putchar('"'); - for (i = 0; i < e->args_size && args_counter < e->args_count; i++) { - char c = e->args[i]; + 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->args_count) { + if (args_counter < e->info_count) { putchar('"'); } } else { @@ -292,155 +325,52 @@ static void print_args1(const struct event *e, bool quote) } } } - if (e->args_count == env.max_args + 1) { + if (e->info_count == env.max_args + 1) { fputs(" ...", stdout); } } -static void print_args2(const struct event *e) +static void print_info2(const struct keytime_event *e) { int i=0; - for(int tmp=e->args_count; tmp>0 ; tmp--){ + for(int tmp=e->info_count; tmp>0 ; tmp--){ if(env.quote){ - printf("\"%llu\" ",e->ctx_args[i++]); + printf("\"%llu\" ",e->info[i++]); }else{ - printf("%llu ",e->ctx_args[i++]); + printf("%llu ",e->info[i++]); } } } -static void handle_event(void *ctx, int cpu, void *data, __u32 data_sz) +static int print_keytime(void *ctx, void *data,unsigned long data_sz) { - const struct event *e = data; - char *c; - char *pad = "\\"; - char *miss = "miss"; - double time; - - switch (e->type) { - case 1: - c = "on_cpu"; - break; - case 2: - c = "off_cpu"; - break; - case 3: - c = "exec_enter"; - break; - case 4: - c = "exec_exit"; - break; - case 5: - c = "exit_enter"; - break; - case 6: - c = "umutex_req"; - break; - case 7: - c = "umutex_lock"; - break; - case 8: - c = "umutex_unlock"; - break; - case 9: - c = "kmutex_req"; - break; - case 10: - c = "kmutex_lock"; - break; - case 11: - c = "kmutex_unlock"; - break; - case 12: - c = "rdlock_req"; - break; - case 13: - c = "rdlock_lock"; - break; - case 14: - c = "rdlock_unlock"; - break; - case 15: - c = "wrlock_req"; - break; - case 16: - c = "wrlock_lock"; - break; - case 17: - c = "wrlock_unlock"; - break; - case 18: - c = "fork_begin"; - break; - case 19: - c = "fork_end"; - break; - case 20: - c = "vfork_begin"; - break; - case 21: - c = "vfork_end"; - break; - case 22: - c = "pthread_begin"; - break; - case 23: - c = "pthread_end"; - break; - default: - c = "?"; - } - - if(e->start!=0 && e->exit!=0){ - time = (e->exit - e->start)*1.0/1000.0; - printf("%-15llu %-15s %-16s %-6d %-6d %-3d %-15.3lf ", e->exit, c, e->comm, e->pid, e->ppid, e->cpu_id, time); - }else if(e->start==0 && e->exit!=0){ - printf("%-15llu %-15s %-16s %-6d %-6d %-3d %-15s ", e->exit, c, e->comm, e->pid, e->ppid, e->cpu_id, miss); - }else{ - printf("%-15llu %-15s %-16s %-6d %-6d %-3d %-15s ", e->start, c, e->comm, e->pid, e->ppid, e->cpu_id, pad); - } - - if(e->type==1 || e->type==2 || (e->type>=18 && e->type<=23)){ - printf("\\ \\"); - } + const struct keytime_event *e = data; + time_t now = time(NULL); + struct tm *localTime = localtime(&now); + int hour = localTime->tm_hour; + int min = localTime->tm_min; + int sec = localTime->tm_sec; + + if(prev_image != KEYTIME_IMAGE){ + printf("KEYTIME_IMAGE-------------------------------------------------------\n"); + printf("%-8s %-6s %-15s %s\n","TIME","PID","EVENT","ARGS/RET/OTHERS"); - if(e->type==3 || e->type==4 || e->type==5){ - if(e->start!=0 && e->exit!=0){ - printf("%-3d ",e->retval); - if(e->enable_char_args){ - print_args1(e, env.quote); - }else{ - print_args2(e); - } - }else if(e->start==0 && e->exit!=0){ - printf("%-3d %s", e->retval,pad); - }else{ - printf("%-3s ",pad); - if(e->enable_char_args){ - print_args1(e, env.quote); - }else{ - print_args2(e); - } - } - } + prev_image = KEYTIME_IMAGE; + } - if(e->type==6 || e->type==9 || e->type==12 || e->type==15){ - printf("\\ "); - print_args2(e); + printf("%02d:%02d:%02d %-6d %-15s ",hour,min,sec,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){ + printf("child_pid:"); } - - if(e->type==7 || e->type==8 || e->type==10 || e->type==11 || - e->type==13 || e->type==14 || e->type==16 || e->type==17){ - printf("%-3d ",e->retval); - print_args2(e); + if(e->enable_char_info){ + print_info1(e); + }else{ + print_info2(e); } putchar('\n'); -} -static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt) -{ - fprintf(stderr, "Lost %llu events on CPU #%d!\n", lost_cnt, cpu); + return 0; } static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) @@ -448,7 +378,7 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va return vfprintf(stderr, format, args); } -static int attach(struct proc_image_bpf *skel) +static int lock_attach(struct lock_image_bpf *skel) { int err; @@ -471,20 +401,53 @@ static int attach(struct proc_image_bpf *skel) ATTACH_UPROBE_CHECKED(skel,__pthread_rwlock_unlock,__pthread_rwlock_unlock_enter); ATTACH_URETPROBE_CHECKED(skel,__pthread_rwlock_unlock,__pthread_rwlock_unlock_exit); + + err = lock_image_bpf__attach(skel); + CHECK_ERR(err, "Failed to attach BPF lock skeleton"); + + return 0; +} + +static int keytime_attach(struct keytime_image_bpf *skel) +{ + int err; ATTACH_URETPROBE_CHECKED(skel,fork,fork_exit); ATTACH_URETPROBE_CHECKED(skel,vfork,vfork_exit); - - err = proc_image_bpf__attach(skel); - CHECK_ERR(err, "Failed to attach BPF skeleton"); - + ATTACH_UPROBE_CHECKED(skel,pthread_create,pthread_create_enter); + ATTACH_URETPROBE_CHECKED(skel,pthread_create,pthread_create_exit); + + err = keytime_image_bpf__attach(skel); + CHECK_ERR(err, "Failed to attach BPF keytime skeleton"); + return 0; } +void *enable_function(void *arg) { + env.create_thread = true; + sleep(1); + env.enable_output = true; + env.create_thread = false; + env.exit_thread = true; + + return NULL; +} + +static void sig_handler(int signo) +{ + exiting = true; +} + int main(int argc, char **argv) { - struct perf_buffer *pb = NULL; - struct proc_image_bpf *skel; + struct resource_image_bpf *resource_skel; + struct syscall_image_bpf *syscall_skel; + struct ring_buffer *syscall_rb = NULL; + struct lock_image_bpf *lock_skel; + struct ring_buffer *lock_rb = NULL; + struct keytime_image_bpf *keytime_skel; + struct ring_buffer *keytime_rb = NULL; + pthread_t thread_enable; int err; static const struct argp argp = { .options = opts, @@ -500,72 +463,206 @@ int main(int argc, char **argv) /* 设置libbpf错误和调试信息回调 */ libbpf_set_print(libbpf_print_fn); - /* 更干净地处理Ctrl-C - SIGINT:由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程 - SIGTERM:请求中止进程,kill命令发送 - */ - signal(SIGINT, sig_handler); - signal(SIGTERM, sig_handler); signal(SIGALRM,sig_handler); - /* 打开BPF应用程序 */ - skel = proc_image_bpf__open(); - if (!skel) { - fprintf(stderr, "Failed to open BPF skeleton\n"); - return 1; + if(env.enable_resource){ + resource_skel = resource_image_bpf__open(); + if(!resource_skel) { + fprintf(stderr, "Failed to open BPF resource skeleton\n"); + return 1; + } + + resource_skel->rodata->target_pid = env.pid; + resource_skel->rodata->target_cpu_id = env.cpu_id; + + err = resource_image_bpf__load(resource_skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF resource skeleton\n"); + goto cleanup; + } + + err = resource_image_bpf__attach(resource_skel); + if (err) { + fprintf(stderr, "Failed to attach BPF resource skeleton\n"); + goto cleanup; + } + } - skel->rodata->target_pid = env.pid; - skel->rodata->target_cpu_id = env.cpu_id; - skel->rodata->enable_cputime = env.enable_cputime; - skel->rodata->enable_execve = env.enable_execve; - skel->rodata->enable_exit = env.enable_exit; - skel->rodata->enable_u_mutex = env.enable_u_mutex; - skel->rodata->enable_k_mutex = env.enable_k_mutex; - skel->rodata->enable_u_rwlock_rd = env.enable_u_rwlock_rd; - skel->rodata->enable_u_rwlock_wr = env.enable_u_rwlock_wr; - skel->rodata->enable_fork = env.enable_fork; - skel->rodata->enable_vfork = env.enable_vfork; - skel->rodata->enable_newthread = env.enable_newthread; - - /* 加载并验证BPF程序 */ - err = proc_image_bpf__load(skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto cleanup; + + if(env.enable_syscall){ + syscall_skel = syscall_image_bpf__open(); + if(!syscall_skel) { + fprintf(stderr, "Failed to open BPF syscall skeleton\n"); + return 1; + } + + syscall_skel->rodata->target_pid = env.pid; + + err = syscall_image_bpf__load(syscall_skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF syscall skeleton\n"); + goto cleanup; + } + + err = syscall_image_bpf__attach(syscall_skel); + if (err) { + fprintf(stderr, "Failed to attach BPF syscall skeleton\n"); + goto cleanup; + } + + /* 设置环形缓冲区轮询 */ + //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 + syscall_rb = ring_buffer__new(bpf_map__fd(syscall_skel->maps.syscall_rb), print_syscall, NULL, NULL); + if (!syscall_rb) { + err = -1; + fprintf(stderr, "Failed to create syscall ring buffer\n"); + goto cleanup; + } } - /* 附加跟踪点处理程序 */ - err = attach(skel); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto cleanup; + if(env.enable_lock){ + lock_skel = lock_image_bpf__open(); + if (!lock_skel) { + fprintf(stderr, "Failed to open BPF lock skeleton\n"); + return 1; + } + + err = lock_image_bpf__load(lock_skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF lock skeleton\n"); + goto cleanup; + } + + /* 附加跟踪点处理程序 */ + err = lock_attach(lock_skel); + if (err) { + fprintf(stderr, "Failed to attach BPF lock skeleton\n"); + goto cleanup; + } + + /* 设置环形缓冲区轮询 */ + //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 + lock_rb = ring_buffer__new(bpf_map__fd(lock_skel->maps.lock_rb), print_lock, NULL, NULL); + if (!lock_rb) { + err = -1; + fprintf(stderr, "Failed to create lock ring buffer\n"); + goto cleanup; + } } - printf("%-15s %-15s %-16s %-6s %-6s %-3s %-15s %3s %s\n", "TIME", "TYPE", "COMM", "PID", "PPID", "CPU", "time(us)", "RET", "ARGS"); + if(env.enable_keytime){ + keytime_skel = keytime_image_bpf__open(); + if (!keytime_skel) { + fprintf(stderr, "Failed to open BPF keytime skeleton\n"); + return 1; + } + + keytime_skel->rodata->target_pid = env.pid; - /* 设置事件回调 */ - pb = perf_buffer__new(bpf_map__fd(skel->maps.events), PERF_BUFFER_PAGES, - handle_event, handle_lost_events, NULL, NULL); - if (!pb) { - err = -errno; - fprintf(stderr, "failed to open perf buffer: %d\n", err); - goto cleanup; + err = keytime_image_bpf__load(keytime_skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF keytime skeleton\n"); + goto cleanup; + } + + /* 附加跟踪点处理程序 */ + err = keytime_attach(keytime_skel); + if (err) { + fprintf(stderr, "Failed to attach BPF keytime skeleton\n"); + goto cleanup; + } + + /* 设置环形缓冲区轮询 */ + //ring_buffer__new() API,允许在不使用额外选项数据结构下指定回调 + keytime_rb = ring_buffer__new(bpf_map__fd(keytime_skel->maps.keytime_rb), print_keytime, NULL, NULL); + if (!keytime_rb) { + err = -1; + fprintf(stderr, "Failed to create keytime ring buffer\n"); + goto cleanup; + } } + /* 处理事件 */ while (!exiting) { - err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS); - if (err < 0 && err != -EINTR) { - fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); - goto cleanup; + // 等待新线程结束,回收资源 + if(env.exit_thread){ + env.exit_thread = false; + if (pthread_join(thread_enable, NULL) != 0) { + perror("pthread_join"); + exit(EXIT_FAILURE); + } + } + + // 创建新线程,设置 env.enable_output + if(!env.create_thread){ + if (pthread_create(&thread_enable, NULL, enable_function, NULL) != 0) { + perror("pthread_create"); + exit(EXIT_FAILURE); + } + } + + if(env.enable_resource && env.enable_output){ + err = print_resource(resource_skel->maps.total); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + break; + } + } + + if(env.enable_syscall){ + err = ring_buffer__poll(syscall_rb, 0); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + printf("Error polling syscall ring buffer: %d\n", err); + break; + } + } + + if(env.enable_lock){ + err = ring_buffer__poll(lock_rb, 0); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + printf("Error polling lock ring buffer: %d\n", err); + break; + } + } + + if(env.enable_keytime){ + err = ring_buffer__poll(keytime_rb, 0); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + printf("Error polling keytime ring buffer: %d\n", err); + break; + } } - /* 如果退出,将err重置为返回0 */ - err = 0; } +/* 卸载BPF程序 */ cleanup: - perf_buffer__free(pb); - proc_image_bpf__destroy(skel); - - return err != 0; -} + 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); + + return err < 0 ? -err : 0; +} \ No newline at end of file From c69f8205e422b33c055c02f82b3ffa927b1322d7 Mon Sep 17 00:00:00 2001 From: zhangzihengya Date: Fri, 22 Dec 2023 16:54:51 +0800 Subject: [PATCH 7/7] md detail --- .../CPU_Subsystem/eBPF_proc_image/proc_image.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) 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 cd9bc28c4..ca9a1d02f 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c @@ -440,12 +440,12 @@ static void sig_handler(int signo) int main(int argc, char **argv) { - struct resource_image_bpf *resource_skel; - struct syscall_image_bpf *syscall_skel; + struct resource_image_bpf *resource_skel = NULL; + struct syscall_image_bpf *syscall_skel = NULL; struct ring_buffer *syscall_rb = NULL; - struct lock_image_bpf *lock_skel; + struct lock_image_bpf *lock_skel = NULL; struct ring_buffer *lock_rb = NULL; - struct keytime_image_bpf *keytime_skel; + struct keytime_image_bpf *keytime_skel = NULL; struct ring_buffer *keytime_rb = NULL; pthread_t thread_enable; int err; @@ -489,7 +489,6 @@ int main(int argc, char **argv) } - if(env.enable_syscall){ syscall_skel = syscall_image_bpf__open(); if(!syscall_skel) {