From 045ac0dce97108e9ac4e8202db033536f49d8c7b Mon Sep 17 00:00:00 2001 From: syxl-time <953879556@qq.com> Date: Fri, 31 May 2024 16:53:55 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=AF=B9=E7=94=A8=E6=88=B7=E6=80=81?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=AE=80=E5=8C=96=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mem_watcher/mem_watcher.c | 559 ++++++++---------- 1 file changed, 248 insertions(+), 311 deletions(-) diff --git a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c index 5156eb2b1..8f596b55d 100644 --- a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c +++ b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c @@ -47,6 +47,7 @@ static size_t g_stacks_size = 0; static struct blaze_symbolizer *symbolizer; static int attach_pid; +pid_t own_pid; static char binary_path[128] = { 0 }; struct allocation { @@ -57,6 +58,8 @@ struct allocation { static struct allocation *allocs; +static volatile bool exiting = false; + #define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ do { \ LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, \ @@ -90,6 +93,48 @@ static struct allocation *allocs; #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 PROCESS_SKEL(skel, func) \ + skel = func##_bpf__open(); \ + if (!skel) { \ + fprintf(stderr, "Failed to open and load BPF skeleton\n"); \ + return 1; \ + } \ + process_##func(skel) + +#define POLL_RING_BUFFER(rb, timeout, err) \ + while (!exiting) { \ + err = ring_buffer__poll(rb, timeout); \ + if (err == -EINTR) { \ + err = 0; \ + break; \ + } \ + if (err < 0) { \ + printf("Error polling perf buffer: %d\n", err); \ + break; \ + } \ + } + +#define LOAD_AND_ATTACH_SKELETON(skel, event) \ + do { \ + skel->bss->user_pid = own_pid; \ + err = event##_bpf__load(skel); \ + if (err) { \ + fprintf(stderr, "Failed to load and verify BPF skeleton\n"); \ + goto event##_cleanup; \ + } \ + \ + err = event##_bpf__attach(skel); \ + if (err) { \ + fprintf(stderr, "Failed to attach BPF skeleton\n"); \ + goto event##_cleanup; \ + } \ + \ + rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event_##event, NULL, NULL); \ + if (!rb) { \ + fprintf(stderr, "Failed to create ring buffer\n"); \ + goto event##_cleanup; \ + } \ + } while(0) static struct env { int time; @@ -148,43 +193,23 @@ static const struct argp_option opts[] = { }; static error_t parse_arg(int key, char *arg, struct argp_state *state) { - switch (key) { - case 't': - env.time = strtol(arg, NULL, 10); - if (env.time) - alarm(env.time); - break; - case 'a': - env.paf = true; - break; - case 'p': - env.pr = true; - break; - case 'r': - env.procstat = true; - break; - case 's': - env.sysstat = true; - break; - case 'n': - env.part2 = true; - break; - case 'h': - argp_state_help(state, stderr, ARGP_HELP_STD_HELP); - break; - case 'P': - env.choose_pid = strtol(arg, NULL, 10); - break; - case 'R': - env.rss = true; - break; - case 'l': - env.memleak = true; - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; + switch (key) { + case 't': + env.time = strtol(arg, NULL, 10); + if (env.time) alarm(env.time); + break; + case 'a': env.paf = true; break; + case 'p': env.pr = true; break; + case 'r': env.procstat = true; break; + case 's': env.sysstat = true; break; + case 'n': env.part2 = true; break; + case 'h': argp_state_help(state, stderr, ARGP_HELP_STD_HELP); break; + case 'P': env.choose_pid = strtol(arg, NULL, 10); break; + case 'R': env.rss = true; break; + case 'l': env.memleak = true; break; + default: return ARGP_ERR_UNKNOWN; + } + return 0; } static const struct argp argp = { @@ -193,6 +218,80 @@ static const struct argp argp = { .doc = argp_program_doc, }; +// Function prototypes +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args); +static void sig_handler(int sig); +static void setup_signals(void); +static void disable_kernel_tracepoints(struct memleak_bpf *skel); +static void print_frame(const char *name, uintptr_t input_addr, uintptr_t addr, uint64_t offset, const blaze_symbolize_code_info *code_info); +static void show_stack_trace(__u64 *stack, int stack_sz, pid_t pid); +static int print_outstanding_allocs(struct memleak_bpf *skel); +static int print_outstanding_combined_allocs(struct memleak_bpf *skel, pid_t pid); +static int handle_event_paf(void *ctx, void *data, size_t data_sz); +static int handle_event_pr(void *ctx, void *data, size_t data_sz); +static int handle_event_procstat(void *ctx, void *data, size_t data_sz); +static int handle_event_sysstat(void *ctx, void *data, size_t data_sz); +static int attach_uprobes(struct memleak_bpf *skel); +static int process_paf(struct paf_bpf *skel_paf); +static int process_pr(struct pr_bpf *skel_pr); +static int process_procstat(struct procstat_bpf *skel_procstat); +static int process_sysstat(struct sysstat_bpf *skel_sysstat); +static int process_memleak(struct memleak_bpf *skel_memleak, struct env); + +// Main function +int main(int argc, char **argv) { + int err; + struct paf_bpf *skel_paf; + struct pr_bpf *skel_pr; + struct procstat_bpf *skel_procstat; + struct sysstat_bpf *skel_sysstat; + struct memleak_bpf *skel_memleak; + + err = argp_parse(&argp, argc, argv, 0, NULL, NULL); + if (err) + return err; + + own_pid = getpid(); + libbpf_set_strict_mode(LIBBPF_STRICT_ALL); + libbpf_set_print(libbpf_print_fn); + + setup_signals(); + + if (env.paf) { + PROCESS_SKEL(skel_paf, paf); + } else if (env.pr) { + PROCESS_SKEL(skel_pr, pr); + } else if (env.procstat) { + PROCESS_SKEL(skel_procstat, procstat); + } else if (env.sysstat) { + PROCESS_SKEL(skel_sysstat, sysstat); + } else if (env.memleak) { + if (env.choose_pid != 0) { + printf("用户态内存泄漏\n"); + env.kernel_trace = false; + attach_pid = env.choose_pid; + } + else + attach_pid = 0; + + strcpy(binary_path, "/lib/x86_64-linux-gnu/libc.so.6"); + + allocs = calloc(ALLOCS_MAX_ENTRIES, sizeof(*allocs)); + + /* Set up libbpf errors and debug info callback */ + libbpf_set_print(libbpf_print_fn); + + /* Load and verify BPF application */ + skel_memleak = memleak_bpf__open(); + if (!skel_memleak) { + fprintf(stderr, "Failed to open BPF skeleton\n"); + return 1; + } + process_memleak(skel_memleak, env); + } + return 0; +} + int alloc_size_compare(const void *a, const void *b) { const struct allocation *x = (struct allocation *)a; @@ -437,13 +536,17 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va return vfprintf(stderr, format, args); } -static volatile bool exiting = false; - static void sig_handler(int sig) { exiting = true; exit(EXIT_SUCCESS); } +static void setup_signals(void) { + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + signal(SIGALRM, sig_handler); +} + /* static char* flags(int flag) { @@ -551,8 +654,6 @@ static int handle_event_sysstat(void *ctx, void *data, size_t data_sz) { return 0; } -pid_t own_pid; - int attach_uprobes(struct memleak_bpf *skel) { ATTACH_UPROBE_CHECKED(skel, malloc, malloc_enter); ATTACH_URETPROBE_CHECKED(skel, malloc, malloc_exit); @@ -593,315 +694,151 @@ int attach_uprobes(struct memleak_bpf *skel) { return 0; } -int main(int argc, char **argv) { - struct ring_buffer *rb = NULL; - struct paf_bpf *skel_paf; - struct pr_bpf *skel_pr; - struct procstat_bpf *skel_procstat; - struct sysstat_bpf *skel_sysstat; - struct memleak_bpf *skel; - - int err, i; - LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts); - - err = argp_parse(&argp, argc, argv, 0, NULL, NULL); - if (err) - return err; - own_pid = getpid(); - libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - - /* Set up libbpf errors and debug info callback */ - libbpf_set_print(libbpf_print_fn); - - /* Cleaner handling of Ctrl-C */ - signal(SIGINT, sig_handler); - signal(SIGTERM, sig_handler); - signal(SIGALRM, sig_handler); - - if (env.paf) { - /* Load and verify BPF application */ - skel_paf = paf_bpf__open(); - if (!skel_paf) { - fprintf(stderr, "Failed to open and load BPF skeleton\n"); - return 1; - } +// Functions to process different BPF programs +static int process_paf(struct paf_bpf *skel_paf) { + int err; + struct ring_buffer *rb; - skel_paf->bss->user_pid = own_pid; + LOAD_AND_ATTACH_SKELETON(skel_paf, paf); - /* Load & verify BPF programs */ - err = paf_bpf__load(skel_paf); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto paf_cleanup; - } + printf("%-8s %-8s %-8s %-8s %-8s\n", "MIN", "LOW", "HIGH", "PRESENT", "FLAG"); - /* Attach tracepoints */ - err = paf_bpf__attach(skel_paf); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto paf_cleanup; - } + POLL_RING_BUFFER(rb, 1000, err); - /* Set up ring buffer polling */ - rb = ring_buffer__new(bpf_map__fd(skel_paf->maps.rb), handle_event_paf, NULL, NULL); - if (!rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer\n"); - goto paf_cleanup; - } +paf_cleanup: + ring_buffer__free(rb); + paf_bpf__destroy(skel_paf); + return err; +} - /* Process events */ - printf("%-8s %-8s %-8s %-8s %-8s\n", "MIN", "LOW", "HIGH", "PRESENT", "FLAG"); - } - else if (env.pr) { - /* Load and verify BPF application */ - skel_pr = pr_bpf__open(); - if (!skel_pr) { - fprintf(stderr, "Failed to open and load BPF skeleton\n"); - return 1; - } +static int process_pr(struct pr_bpf *skel_pr) { + int err; + struct ring_buffer *rb; - skel_pr->bss->user_pid = own_pid; + LOAD_AND_ATTACH_SKELETON(skel_pr, pr); - /* Load & verify BPF programs */ - err = pr_bpf__load(skel_pr); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto pr_cleanup; - } + printf("%-8s %-8s %-8s %-8s %-8s\n", "RECLAIM", "RECLAIMED", "UNQUEUE", "CONGESTED", "WRITEBACK"); - /* Attach tracepoints */ - err = pr_bpf__attach(skel_pr); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto pr_cleanup; - } + POLL_RING_BUFFER(rb, 1000, err); - /* Set up ring buffer polling */ - rb = ring_buffer__new(bpf_map__fd(skel_pr->maps.rb), handle_event_pr, NULL, NULL); - if (!rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer\n"); - goto pr_cleanup; - } +pr_cleanup: + ring_buffer__free(rb); + pr_bpf__destroy(skel_pr); + return err; +} - /* Process events */ - printf("%-8s %-8s %-8s %-8s %-8s\n", "RECLAIM", "RECLAIMED", "UNQUEUE", "CONGESTED", "WRITEBACK"); - } +static int process_procstat(struct procstat_bpf *skel_procstat) { + int err; + struct ring_buffer *rb; - else if (env.procstat) { - /* Load and verify BPF application */ - skel_procstat = procstat_bpf__open(); - if (!skel_procstat) { - fprintf(stderr, "Failed to open and load BPF skeleton\n"); - return 1; - } + LOAD_AND_ATTACH_SKELETON(skel_procstat, procstat); - skel_procstat->bss->user_pid = own_pid; + if (env.rss) { + printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s\n", "TIME", "PID", "VMSIZE", "VMDATA", "VMSTK", "VMPTE", "VMSWAP"); + } else { + printf("%-8s %-8s %-8s %-8s %-8s %-8s\n", "TIME", "PID", "SIZE", "RSSANON", "RSSFILE", "RSSSHMEM"); + } - /* Load & verify BPF programs */ - err = procstat_bpf__load(skel_procstat); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto procstat_cleanup; - } + POLL_RING_BUFFER(rb, 1000, err); - /* Attach tracepoints */ - err = procstat_bpf__attach(skel_procstat); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto procstat_cleanup; - } +procstat_cleanup: + ring_buffer__free(rb); + procstat_bpf__destroy(skel_procstat); + return err; +} - /* Set up ring buffer polling */ - rb = ring_buffer__new(bpf_map__fd(skel_procstat->maps.rb), handle_event_procstat, NULL, NULL); - if (!rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer\n"); - goto procstat_cleanup; - } +static int process_sysstat(struct sysstat_bpf *skel_sysstat) { + int err; + struct ring_buffer *rb; - /* Process events */ - if (env.rss == true) { - printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s\n", "TIME", "PID", "VMSIZE", "VMDATA", "VMSTK", "VMPTE", "VMSWAP"); - } - else { - printf("%-8s %-8s %-8s %-8s %-8s %-8s\n", "TIME", "PID", "SIZE", "RSSANON", "RSSFILE", "RSSSHMEM"); - } - } + LOAD_AND_ATTACH_SKELETON(skel_sysstat, sysstat); - else if (env.sysstat) { - /* Load and verify BPF application */ - skel_sysstat = sysstat_bpf__open(); - if (!skel_sysstat) { - fprintf(stderr, "Failed to open and load BPF skeleton\n"); - return 1; - } + if (env.part2) { + printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s\n", "KRECLM", "SLAB", "SRECLM", "SUNRECL", "NFSUNSTB", "WRITEBACKTMP", "KMAP", "UNMAP", "PAGE"); + } else { + printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s\n", "TIME", "PID", "CPU", "MEM", "READ", "WRITE", "IOWAIT", "SWAP"); + } + POLL_RING_BUFFER(rb, 1000, err); - skel_sysstat->bss->user_pid = own_pid; +sysstat_cleanup: + ring_buffer__free(rb); + sysstat_bpf__destroy(skel_sysstat); + return err; +} - /* Load & verify BPF programs */ - err = sysstat_bpf__load(skel_sysstat); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto sysstat_cleanup; - } +static int process_memleak(struct memleak_bpf *skel_memleak, struct env env) { + skel_memleak->rodata->stack_flags = env.kernel_trace ? KERN_STACKID_FLAGS : USER_STACKID_FLAGS; - /* Attach tracepoints */ - err = sysstat_bpf__attach(skel_sysstat); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto sysstat_cleanup; - } + bpf_map__set_value_size(skel_memleak->maps.stack_traces, perf_max_stack_depth * sizeof(__u64)); + bpf_map__set_max_entries(skel_memleak->maps.stack_traces, stack_map_max_entries); - /* Set up ring buffer polling */ - rb = ring_buffer__new(bpf_map__fd(skel_sysstat->maps.rb), handle_event_sysstat, NULL, NULL); - if (!rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer\n"); - goto sysstat_cleanup; - } + if (!env.kernel_trace) + disable_kernel_tracepoints(skel_memleak); - /* Process events */ - if (env.part2 == true) { - printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s\n", "KRECLM", "SLAB", "SRECLM", "SUNRECLMA", "UNSTABLE", "WRITEBK_T", "ANONHUGE", "SHMEMHUGE", "PMDMAPP"); - } - else { - printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s\n", "ACTIVE", "INACTVE", "ANON_ACT", "ANON_INA", "FILE_ACT", "FILE_INA", "UNEVICT", "DIRTY", "WRITEBK", "ANONPAG", "MAP", "SHMEM"); - } + int err = memleak_bpf__load(skel_memleak); + if (err) { + fprintf(stderr, "Failed to load BPF skeleton\n"); + goto memleak_cleanup; } - else if (env.memleak) { - if (env.choose_pid != 0) { - printf("用户态内存泄漏\n"); - env.kernel_trace = false; - attach_pid = env.choose_pid; - } - else - attach_pid = 0; - - strcpy(binary_path, "/lib/x86_64-linux-gnu/libc.so.6"); - - allocs = calloc(ALLOCS_MAX_ENTRIES, sizeof(*allocs)); - - /* Set up libbpf errors and debug info callback */ - libbpf_set_print(libbpf_print_fn); - - /* Load and verify BPF application */ - skel = memleak_bpf__open(); - if (!skel) { - fprintf(stderr, "Failed to open BPF skeleton\n"); - return 1; - } - //skel->rodata->stack_flags = KERN_STACKID_FLAGS; - skel->rodata->stack_flags = env.kernel_trace ? KERN_STACKID_FLAGS : USER_STACKID_FLAGS; - - bpf_map__set_value_size(skel->maps.stack_traces, perf_max_stack_depth * sizeof(__u64)); - bpf_map__set_max_entries(skel->maps.stack_traces, stack_map_max_entries); - - if (!env.kernel_trace) - disable_kernel_tracepoints(skel); - - /* Load & verify BPF programs */ - err = memleak_bpf__load(skel); + if (!env.kernel_trace) { + err = attach_uprobes(skel_memleak); if (err) { - fprintf(stderr, "Failed to load BPF skeleton\n"); + fprintf(stderr, "Failed to attach uprobes\n"); goto memleak_cleanup; } + } - if (!env.kernel_trace) { - err = attach_uprobes(skel); - if (err) { - fprintf(stderr, "failed to attach uprobes\n"); - - goto memleak_cleanup; - } - } - - /* Let libbpf perform auto-attach for uprobe_sub/uretprobe_sub - * NOTICE: we provide path and symbol info in SEC for BPF programs - */ - err = memleak_bpf__attach(skel); - if (err) { - fprintf(stderr, "Failed to auto-attach BPF skeleton: %d\n", err); - goto memleak_cleanup; - } + err = memleak_bpf__attach(skel_memleak); + if (err) { + fprintf(stderr, "Failed to auto-attach BPF skeleton: %d\n", err); + goto memleak_cleanup; + } - g_stacks_size = perf_max_stack_depth * sizeof(*g_stacks); - g_stacks = (__u64 *)malloc(g_stacks_size); - memset(g_stacks, 0, g_stacks_size); + g_stacks_size = perf_max_stack_depth * sizeof(*g_stacks); + g_stacks = (__u64 *)malloc(g_stacks_size); + if (!g_stacks) { + fprintf(stderr, "Failed to allocate memory\n"); + err = -1; + goto memleak_cleanup; + } + memset(g_stacks, 0, g_stacks_size); - symbolizer = blaze_symbolizer_new(); - if (!symbolizer) { - fprintf(stderr, "Fail to create a symbolizer\n"); - err = -1; - goto memleak_cleanup; - } + symbolizer = blaze_symbolizer_new(); + if (!symbolizer) { + fprintf(stderr, "Fail to create a symbolizer\n"); + err = -1; + goto memleak_cleanup; + } - for (i = 0;; i++) { - /* trigger our BPF programs */ - if (!env.kernel_trace) - print_outstanding_combined_allocs(skel, attach_pid); - else - print_outstanding_allocs(skel); + for (;;) { + if (!env.kernel_trace) + print_outstanding_combined_allocs(skel_memleak, attach_pid); + else + print_outstanding_allocs(skel_memleak); - sleep(1); - } + sleep(1); } while (!exiting) { - if (env.paf || env.pr || env.procstat || env.sysstat) { - err = ring_buffer__poll(rb, 1000 /* timeout, ms */); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling perf buffer: %d\n", err); - break; - } - } - else if (env.memleak) { - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling perf buffer: %d\n", err); - break; - } + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; } - else { - printf("请输入要使用的功能...\n"); + if (err < 0) { + printf("Error polling perf buffer: %d\n", err); break; } } -paf_cleanup: - ring_buffer__free(rb); - paf_bpf__destroy(skel_paf); - return err < 0 ? -err : 0; - -pr_cleanup: - ring_buffer__free(rb); - pr_bpf__destroy(skel_pr); - return err < 0 ? -err : 0; - -procstat_cleanup: - ring_buffer__free(rb); - procstat_bpf__destroy(skel_procstat); - return err < 0 ? -err : 0; - -sysstat_cleanup: - ring_buffer__free(rb); - sysstat_bpf__destroy(skel_sysstat); - return err < 0 ? -err : 0; - memleak_cleanup: - memleak_bpf__destroy(skel); - blaze_symbolizer_free(symbolizer); - free(g_stacks); - return err < 0 ? -err : 0; + memleak_bpf__destroy(skel_memleak); + if (symbolizer) + blaze_symbolizer_free(symbolizer); + if (g_stacks) + free(g_stacks); + if (allocs) + free(allocs); + return err; } \ No newline at end of file From 39119b4bef5d0cb3aa8bf5a8aff30fd792a99cfb Mon Sep 17 00:00:00 2001 From: syxl-time <953879556@qq.com> Date: Fri, 19 Jul 2024 19:20:07 +0800 Subject: [PATCH 2/3] =?UTF-8?q?mem=5Fwatcher:=E6=B7=BB=E5=8A=A0=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E9=A1=B5=E9=9D=A2=E4=BF=AE=E9=A5=B0=E7=AC=A6=E6=A0=87?= =?UTF-8?q?=E5=BF=97gfp=5Fmask=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mem_watcher/include/mem_watcher.h | 75 ++++++++------- .../mem_watcher/mem_watcher.c | 96 +++++++++++++------ 2 files changed, 103 insertions(+), 68 deletions(-) diff --git a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/include/mem_watcher.h b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/include/mem_watcher.h index 3b65256eb..de3729d1e 100644 --- a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/include/mem_watcher.h +++ b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/include/mem_watcher.h @@ -4,44 +4,45 @@ #define TASK_COMM_LEN 16 #define MAX_FILENAME_LEN 127 -#define ___GFP_DMA 0x01u -#define ___GFP_HIGHMEM 0x02u -#define ___GFP_DMA32 0x04u -#define ___GFP_MOVABLE 0x08u -#define ___GFP_RECLAIMABLE 0x10u -#define ___GFP_HIGH 0x20u -#define ___GFP_IO 0x40u -#define ___GFP_FS 0x80u -#define ___GFP_WRITE 0x100u -#define ___GFP_NOWARN 0x200u -#define ___GFP_RETRY_MAYFAIL 0x400u -#define ___GFP_NOFAIL 0x800u -#define ___GFP_NORETRY 0x1000u -#define ___GFP_MEMALLOC 0x2000u -#define ___GFP_COMP 0x4000u -#define ___GFP_ZERO 0x8000u -#define ___GFP_NOMEMALLOC 0x10000u -#define ___GFP_HARDWALL 0x20000u -#define ___GFP_THISNODE 0x40000u -#define ___GFP_ATOMIC 0x80000u -#define ___GFP_ACCOUNT 0x100000u -#define ___GFP_DIRECT_RECLAIM 0x200000u -#define ___GFP_KSWAPD_RECLAIM 0x400000u +#define ___GFP_DMA 0x01u +#define ___GFP_HIGHMEM 0x02u +#define ___GFP_DMA32 0x04u +#define ___GFP_MOVABLE 0x08u +#define ___GFP_RECLAIMABLE 0x10u +#define ___GFP_HIGH 0x20u +#define ___GFP_IO 0x40u +#define ___GFP_FS 0x80u +#define ___GFP_ZERO 0x100u +#define ___GFP_ATOMIC 0x200u +#define ___GFP_DIRECT_RECLAIM 0x400u +#define ___GFP_KSWAPD_RECLAIM 0x800u +#define ___GFP_WRITE 0x1000u +#define ___GFP_NOWARN 0x2000u +#define ___GFP_RETRY_MAYFAIL 0x4000u +#define ___GFP_NOFAIL 0x8000u +#define ___GFP_NORETRY 0x10000u +#define ___GFP_MEMALLOC 0x20000u +#define ___GFP_COMP 0x40000u +#define ___GFP_NOMEMALLOC 0x80000u +#define ___GFP_HARDWALL 0x100000u +#define ___GFP_THISNODE 0x200000u +#define ___GFP_ACCOUNT 0x400000u +#define ___GFP_ZEROTAGS 0x800000u +#define ___GFP_SKIP_KASAN_POISON 0x1000000u -#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM) -#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS) -#define GFP_KERNEL_ACCOUNT (GFP_KERNEL | __GFP_ACCOUNT) -#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM) -#define GFP_NOIO (__GFP_RECLAIM) -#define GFP_NOFS (__GFP_RECLAIM | __GFP_IO) -#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL) -#define GFP_DMA __GFP_DMA -#define GFP_DMA32 __GFP_DMA32 -#define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM) -#define GFP_HIGHUSER_MOVABLE (GFP_HIGHUSER | __GFP_MOVABLE) -#define GFP_TRANSHUGE_LIGHT ((GFP_HIGHUSER_MOVABLE | __GFP_COMP | \ - __GFP_NOMEMALLOC | __GFP_NOWARN) & ~__GFP_RECLAIM) -#define GFP_TRANSHUGE (GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM) +#define GFP_ATOMIC (___GFP_HIGH|___GFP_ATOMIC|___GFP_KSWAPD_RECLAIM) +#define GFP_KERNEL (___GFP_RECLAIMABLE | ___GFP_IO | ___GFP_FS) +#define GFP_KERNEL_ACCOUNT (GFP_KERNEL | ___GFP_ACCOUNT) +#define GFP_NOWAIT (___GFP_KSWAPD_RECLAIM) +#define GFP_NOIO (___GFP_RECLAIMABLE) +#define GFP_NOFS (___GFP_RECLAIMABLE | ___GFP_IO) +#define GFP_USER (___GFP_RECLAIMABLE | ___GFP_IO | ___GFP_FS | ___GFP_HARDWALL) +#define GFP_DMA ___GFP_DMA +#define GFP_DMA32 ___GFP_DMA32 +#define GFP_HIGHUSER (GFP_USER | ___GFP_HIGHMEM) +#define GFP_HIGHUSER_MOVABLE (GFP_HIGHUSER | ___GFP_MOVABLE | ___GFP_SKIP_KASAN_POISON) +#define GFP_TRANSHUGE_LIGHT ((GFP_HIGHUSER_MOVABLE | ___GFP_COMP | ___GFP_NOMEMALLOC | ___GFP_NOWARN) & ~___GFP_RECLAIMABLE) +#define GFP_TRANSHUGE (GFP_TRANSHUGE_LIGHT | ___GFP_DIRECT_RECLAIM) struct paf_event { unsigned long min; diff --git a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c index 6f851f007..5c8da7cc0 100644 --- a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c +++ b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c @@ -296,6 +296,7 @@ static int handle_event_pr(void *ctx, void *data, size_t data_sz); static int handle_event_procstat(void *ctx, void *data, size_t data_sz); static int handle_event_sysstat(void *ctx, void *data, size_t data_sz); static int attach_uprobes(struct memleak_bpf *skel); +static void print_flag_modifiers(int flag); static int process_paf(struct paf_bpf *skel_paf); static int process_pr(struct pr_bpf *skel_pr); static int process_procstat(struct procstat_bpf *skel_procstat); @@ -769,36 +770,67 @@ static void setup_signals(void) signal(SIGALRM, sig_handler); } -/* -static char* flags(int flag) -{ - if(flag & GFP_ATOMIC) - return "GFP_ATOMIC"; - if(flag & GFP_KERNEL) - return "GFP_KERNEL"; - if(flag & GFP_KERNEL_ACCOUNT) - return "GFP_KERNEL_ACCOUNT"; - if(flag & GFP_NOWAIT) - return "GFP_NOWAIT"; - if(flag & GFP_NOIO ) - return "GFP_NOIO "; - if(flag & GFP_NOFS) - return "GFP_NOFS"; - if(flag & GFP_USER) - return "GFP_USER"; - if(flag & GFP_DMA) - return "GFP_DMA"; - if(flag & GFP_DMA32) - return "GFP_DMA32"; - if(flag & GFP_HIGHUSER) - return "GFP_HIGHUSER"; - if(flag & GFP_HIGHUSER_MOVABLE) - return "GFP_HIGHUSER_MOVABLE"; - if(flag & GFP_TRANSHUGE_LIGHT) - return "GFP_TRANSHUGE_LIGHT"; - return; +static void print_flag_modifiers(int flag) { + char combined[512] = {0}; // 用于保存组合修饰符 + char separate[512] = {0}; // 用于保存单独标志位 + char buffer[64]; // 用于临时存储每个修饰符 + + // 检查组合修饰符 + if ((flag & GFP_ATOMIC) == GFP_ATOMIC) strcat(combined, "GFP_ATOMIC | "); + if ((flag & GFP_KERNEL) == GFP_KERNEL) strcat(combined, "GFP_KERNEL | "); + if ((flag & GFP_KERNEL_ACCOUNT) == GFP_KERNEL_ACCOUNT) strcat(combined, "GFP_KERNEL_ACCOUNT | "); + if ((flag & GFP_NOWAIT) == GFP_NOWAIT) strcat(combined, "GFP_NOWAIT | "); + if ((flag & GFP_NOIO) == GFP_NOIO) strcat(combined, "GFP_NOIO | "); + if ((flag & GFP_NOFS) == GFP_NOFS) strcat(combined, "GFP_NOFS | "); + if ((flag & GFP_USER) == GFP_USER) strcat(combined, "GFP_USER | "); + if ((flag & GFP_DMA) == GFP_DMA) strcat(combined, "GFP_DMA | "); + if ((flag & GFP_DMA32) == GFP_DMA32) strcat(combined, "GFP_DMA32 | "); + if ((flag & GFP_HIGHUSER) == GFP_HIGHUSER) strcat(combined, "GFP_HIGHUSER | "); + if ((flag & GFP_HIGHUSER_MOVABLE) == GFP_HIGHUSER_MOVABLE) strcat(combined, "GFP_HIGHUSER_MOVABLE | "); + if ((flag & GFP_TRANSHUGE_LIGHT) == GFP_TRANSHUGE_LIGHT) strcat(combined, "GFP_TRANSHUGE_LIGHT | "); + if ((flag & GFP_TRANSHUGE) == GFP_TRANSHUGE) strcat(combined, "GFP_TRANSHUGE | "); + + // 移除最后一个 " | " 字符串的末尾 + if (strlen(combined) > 3) { + combined[strlen(combined) - 3] = '\0'; + } + + // 检查单独标志位 + if (flag & ___GFP_DMA) strcat(separate, "___GFP_DMA | "); + if (flag & ___GFP_HIGHMEM) strcat(separate, "___GFP_HIGHMEM | "); + if (flag & ___GFP_DMA32) strcat(separate, "___GFP_DMA32 | "); + if (flag & ___GFP_MOVABLE) strcat(separate, "___GFP_MOVABLE | "); + if (flag & ___GFP_RECLAIMABLE) strcat(separate, "___GFP_RECLAIMABLE | "); + if (flag & ___GFP_HIGH) strcat(separate, "___GFP_HIGH | "); + if (flag & ___GFP_IO) strcat(separate, "___GFP_IO | "); + if (flag & ___GFP_FS) strcat(separate, "___GFP_FS | "); + if (flag & ___GFP_ZERO) strcat(separate, "___GFP_ZERO | "); + if (flag & ___GFP_ATOMIC) strcat(separate, "___GFP_ATOMIC | "); + if (flag & ___GFP_DIRECT_RECLAIM) strcat(separate, "___GFP_DIRECT_RECLAIM | "); + if (flag & ___GFP_KSWAPD_RECLAIM) strcat(separate, "___GFP_KSWAPD_RECLAIM | "); + if (flag & ___GFP_WRITE) strcat(separate, "___GFP_WRITE | "); + if (flag & ___GFP_NOWARN) strcat(separate, "___GFP_NOWARN | "); + if (flag & ___GFP_RETRY_MAYFAIL) strcat(separate, "___GFP_RETRY_MAYFAIL | "); + if (flag & ___GFP_NOFAIL) strcat(separate, "___GFP_NOFAIL | "); + if (flag & ___GFP_NORETRY) strcat(separate, "___GFP_NORETRY | "); + if (flag & ___GFP_MEMALLOC) strcat(separate, "___GFP_MEMALLOC | "); + if (flag & ___GFP_COMP) strcat(separate, "___GFP_COMP | "); + if (flag & ___GFP_NOMEMALLOC) strcat(separate, "___GFP_NOMEMALLOC | "); + if (flag & ___GFP_HARDWALL) strcat(separate, "___GFP_HARDWALL | "); + if (flag & ___GFP_THISNODE) strcat(separate, "___GFP_THISNODE | "); + if (flag & ___GFP_ACCOUNT) strcat(separate, "___GFP_ACCOUNT | "); + if (flag & ___GFP_ZEROTAGS) strcat(separate, "___GFP_ZEROTAGS | "); + if (flag & ___GFP_SKIP_KASAN_POISON) strcat(separate, "___GFP_SKIP_KASAN_POISON | "); + + // 移除最后一个 " | " 字符串的末尾 + if (strlen(separate) > 3) { + separate[strlen(separate) - 3] = '\0'; + } + + // 打印组合修饰符和单独标志位 + printf("%-50s %-100s\n", combined, separate); } -*/ + static int handle_event_paf(void *ctx, void *data, size_t data_sz) { const struct paf_event *e = data; @@ -810,8 +842,10 @@ static int handle_event_paf(void *ctx, void *data, size_t data_sz) tm = localtime(&t); strftime(ts, sizeof(ts), "%H:%M:%S", tm); - printf("%-8lu %-8lu %-8lu %-8lu %-8x\n", - e->min, e->low, e->high, e->present, e->flag); + printf("%-8lu %-8lu %-8lu %-8lu %-8x ", + e->min, e->low, e->high, e->present, e->flag); + print_flag_modifiers(e->flag); + printf("\n"); return 0; } From 9ab83d2602615baaf9e0fbe35d22018e6a0bae5a Mon Sep 17 00:00:00 2001 From: syxl-time <953879556@qq.com> Date: Tue, 23 Jul 2024 10:19:12 +0800 Subject: [PATCH 3/3] =?UTF-8?q?mem=5Fwatcher:=E4=BF=AE=E6=94=B9=E4=B8=BAfo?= =?UTF-8?q?r=E5=BE=AA=E7=8E=AF=E5=88=A4=E6=96=AD=E6=A0=87=E5=BF=97?= =?UTF-8?q?=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mem_watcher/mem_watcher.c | 102 +++++++++++------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c index 5c8da7cc0..2a780473d 100644 --- a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c +++ b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/mem_watcher.c @@ -39,6 +39,57 @@ #include "blazesym.h" +// 定义标志结构体 +typedef struct { + int flag; + const char *name; +} Flag; + +// 定义所有组合修饰符和单独标志位 +Flag gfp_combined_list[] = { + {GFP_ATOMIC, "GFP_ATOMIC"}, + {GFP_KERNEL, "GFP_KERNEL"}, + {GFP_KERNEL_ACCOUNT, "GFP_KERNEL_ACCOUNT"}, + {GFP_NOWAIT, "GFP_NOWAIT"}, + {GFP_NOIO, "GFP_NOIO"}, + {GFP_NOFS, "GFP_NOFS"}, + {GFP_USER, "GFP_USER"}, + {GFP_DMA, "GFP_DMA"}, + {GFP_DMA32, "GFP_DMA32"}, + {GFP_HIGHUSER, "GFP_HIGHUSER"}, + {GFP_HIGHUSER_MOVABLE, "GFP_HIGHUSER_MOVABLE"}, + {GFP_TRANSHUGE_LIGHT, "GFP_TRANSHUGE_LIGHT"}, + {GFP_TRANSHUGE, "GFP_TRANSHUGE"}, +}; + +Flag gfp_separate_list[] = { + {___GFP_DMA, "___GFP_DMA"}, + {___GFP_HIGHMEM, "___GFP_HIGHMEM"}, + {___GFP_DMA32, "___GFP_DMA32"}, + {___GFP_MOVABLE, "___GFP_MOVABLE"}, + {___GFP_RECLAIMABLE, "___GFP_RECLAIMABLE"}, + {___GFP_HIGH, "___GFP_HIGH"}, + {___GFP_IO, "___GFP_IO"}, + {___GFP_FS, "___GFP_FS"}, + {___GFP_ZERO, "___GFP_ZERO"}, + {___GFP_ATOMIC, "___GFP_ATOMIC"}, + {___GFP_DIRECT_RECLAIM, "___GFP_DIRECT_RECLAIM"}, + {___GFP_KSWAPD_RECLAIM, "___GFP_KSWAPD_RECLAIM"}, + {___GFP_WRITE, "___GFP_WRITE"}, + {___GFP_NOWARN, "___GFP_NOWARN"}, + {___GFP_RETRY_MAYFAIL, "___GFP_RETRY_MAYFAIL"}, + {___GFP_NOFAIL, "___GFP_NOFAIL"}, + {___GFP_NORETRY, "___GFP_NORETRY"}, + {___GFP_MEMALLOC, "___GFP_MEMALLOC"}, + {___GFP_COMP, "___GFP_COMP"}, + {___GFP_NOMEMALLOC, "___GFP_NOMEMALLOC"}, + {___GFP_HARDWALL, "___GFP_HARDWALL"}, + {___GFP_THISNODE, "___GFP_THISNODE"}, + {___GFP_ACCOUNT, "___GFP_ACCOUNT"}, + {___GFP_ZEROTAGS, "___GFP_ZEROTAGS"}, + {___GFP_SKIP_KASAN_POISON, "___GFP_SKIP_KASAN_POISON"}, +}; + static const int perf_max_stack_depth = 127; // stack id 对应的堆栈的深度 static const int stack_map_max_entries = 10240; // 最大允许存储多少个stack_id static __u64 *g_stacks = NULL; @@ -773,22 +824,14 @@ static void setup_signals(void) static void print_flag_modifiers(int flag) { char combined[512] = {0}; // 用于保存组合修饰符 char separate[512] = {0}; // 用于保存单独标志位 - char buffer[64]; // 用于临时存储每个修饰符 // 检查组合修饰符 - if ((flag & GFP_ATOMIC) == GFP_ATOMIC) strcat(combined, "GFP_ATOMIC | "); - if ((flag & GFP_KERNEL) == GFP_KERNEL) strcat(combined, "GFP_KERNEL | "); - if ((flag & GFP_KERNEL_ACCOUNT) == GFP_KERNEL_ACCOUNT) strcat(combined, "GFP_KERNEL_ACCOUNT | "); - if ((flag & GFP_NOWAIT) == GFP_NOWAIT) strcat(combined, "GFP_NOWAIT | "); - if ((flag & GFP_NOIO) == GFP_NOIO) strcat(combined, "GFP_NOIO | "); - if ((flag & GFP_NOFS) == GFP_NOFS) strcat(combined, "GFP_NOFS | "); - if ((flag & GFP_USER) == GFP_USER) strcat(combined, "GFP_USER | "); - if ((flag & GFP_DMA) == GFP_DMA) strcat(combined, "GFP_DMA | "); - if ((flag & GFP_DMA32) == GFP_DMA32) strcat(combined, "GFP_DMA32 | "); - if ((flag & GFP_HIGHUSER) == GFP_HIGHUSER) strcat(combined, "GFP_HIGHUSER | "); - if ((flag & GFP_HIGHUSER_MOVABLE) == GFP_HIGHUSER_MOVABLE) strcat(combined, "GFP_HIGHUSER_MOVABLE | "); - if ((flag & GFP_TRANSHUGE_LIGHT) == GFP_TRANSHUGE_LIGHT) strcat(combined, "GFP_TRANSHUGE_LIGHT | "); - if ((flag & GFP_TRANSHUGE) == GFP_TRANSHUGE) strcat(combined, "GFP_TRANSHUGE | "); + for (int i = 0; i < sizeof(gfp_combined_list) / sizeof(gfp_combined_list[0]); ++i) { + if ((flag & gfp_combined_list[i].flag) == gfp_combined_list[i].flag) { + strcat(combined, gfp_combined_list[i].name); + strcat(combined, " | "); + } + } // 移除最后一个 " | " 字符串的末尾 if (strlen(combined) > 3) { @@ -796,31 +839,12 @@ static void print_flag_modifiers(int flag) { } // 检查单独标志位 - if (flag & ___GFP_DMA) strcat(separate, "___GFP_DMA | "); - if (flag & ___GFP_HIGHMEM) strcat(separate, "___GFP_HIGHMEM | "); - if (flag & ___GFP_DMA32) strcat(separate, "___GFP_DMA32 | "); - if (flag & ___GFP_MOVABLE) strcat(separate, "___GFP_MOVABLE | "); - if (flag & ___GFP_RECLAIMABLE) strcat(separate, "___GFP_RECLAIMABLE | "); - if (flag & ___GFP_HIGH) strcat(separate, "___GFP_HIGH | "); - if (flag & ___GFP_IO) strcat(separate, "___GFP_IO | "); - if (flag & ___GFP_FS) strcat(separate, "___GFP_FS | "); - if (flag & ___GFP_ZERO) strcat(separate, "___GFP_ZERO | "); - if (flag & ___GFP_ATOMIC) strcat(separate, "___GFP_ATOMIC | "); - if (flag & ___GFP_DIRECT_RECLAIM) strcat(separate, "___GFP_DIRECT_RECLAIM | "); - if (flag & ___GFP_KSWAPD_RECLAIM) strcat(separate, "___GFP_KSWAPD_RECLAIM | "); - if (flag & ___GFP_WRITE) strcat(separate, "___GFP_WRITE | "); - if (flag & ___GFP_NOWARN) strcat(separate, "___GFP_NOWARN | "); - if (flag & ___GFP_RETRY_MAYFAIL) strcat(separate, "___GFP_RETRY_MAYFAIL | "); - if (flag & ___GFP_NOFAIL) strcat(separate, "___GFP_NOFAIL | "); - if (flag & ___GFP_NORETRY) strcat(separate, "___GFP_NORETRY | "); - if (flag & ___GFP_MEMALLOC) strcat(separate, "___GFP_MEMALLOC | "); - if (flag & ___GFP_COMP) strcat(separate, "___GFP_COMP | "); - if (flag & ___GFP_NOMEMALLOC) strcat(separate, "___GFP_NOMEMALLOC | "); - if (flag & ___GFP_HARDWALL) strcat(separate, "___GFP_HARDWALL | "); - if (flag & ___GFP_THISNODE) strcat(separate, "___GFP_THISNODE | "); - if (flag & ___GFP_ACCOUNT) strcat(separate, "___GFP_ACCOUNT | "); - if (flag & ___GFP_ZEROTAGS) strcat(separate, "___GFP_ZEROTAGS | "); - if (flag & ___GFP_SKIP_KASAN_POISON) strcat(separate, "___GFP_SKIP_KASAN_POISON | "); + for (int i = 0; i < sizeof(gfp_separate_list) / sizeof(gfp_separate_list[0]); ++i) { + if (flag & gfp_separate_list[i].flag) { + strcat(separate, gfp_separate_list[i].name); + strcat(separate, " | "); + } + } // 移除最后一个 " | " 字符串的末尾 if (strlen(separate) > 3) {