diff --git a/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c b/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c index 5824bb774..60e11158a 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c +++ b/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c @@ -1,18 +1,19 @@ -#define BPF_NO_GLOBAL_DATA #include #include #include #include #include "fs_watcher.h" -#define TASK_COMM_LEN 100 -#define path_size 256 +char LICENSE[] SEC("license") = "GPL"; + +#define O_CREAT 0x0200 // 手动定义 O_CREAT 标志的常量值 +#define O_WRONLY 01 /* open for writing only */ struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 1024); __type(key, pid_t); - __type(value, char[TASK_COMM_LEN]); + __type(value, struct event_open); } data SEC(".maps"); struct { @@ -20,52 +21,84 @@ struct { __uint(max_entries, 256 * 1024); } rb SEC(".maps"); // 环形缓冲区 - SEC("tracepoint/syscalls/sys_enter_openat") int do_syscall_trace(struct trace_event_raw_sys_enter *ctx) { - struct event_open *e; - char comm[TASK_COMM_LEN]; - bpf_get_current_comm(&comm,sizeof(comm)); - e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); - if (!e) - return 0; + struct event_open e = {}; + pid_t pid = bpf_get_current_pid_tgid() >> 32; + e.pid = pid; + e.dfd = ctx->args[0];// 目录文件描述符 + bpf_probe_read_user_str(e.filename, sizeof(e.filename), (const char *)ctx->args[1]); // 文件路径 + e.flags = ctx->args[2]; // 打开标志 + + // 如果包含 O_CREAT 标志,则标记为文件创建 + if (e.flags & O_CREAT || (e.flags & O_WRONLY) ) { + e.is_created = true; + } else { + e.is_created = false; + } + + bpf_map_update_elem(&data,&pid,&e,BPF_ANY); + return 0; +} - char filename[path_size]; - struct task_struct *task = (struct task_struct *)bpf_get_current_task(), - *real_parent; - if (task == NULL) { - bpf_printk("task\n"); - bpf_ringbuf_discard(e, 0); +// 跟踪文件描述符分配过程 +SEC("kprobe/get_unused_fd_flags") +int kprobe_get_unused_fd_flags(struct pt_regs *ctx){ + pid_t pid = bpf_get_current_pid_tgid() >> 32; + struct event_open *e = bpf_map_lookup_elem(&data,&pid); + if(!e){ + bpf_printk("get_unused_fd_flags is failed to found fd\n"); return 0; } - int pid = bpf_get_current_pid_tgid() >> 32, tgid; - - bpf_map_update_elem(&data, &pid, &comm, BPF_ANY); - - int ppid = BPF_CORE_READ(task, real_parent, tgid); - bpf_probe_read_str(e->path_name_, sizeof(e->path_name_), - (void *)(ctx->args[1])); + //获取分配的文件描述符 + e->fd = PT_REGS_RC(ctx); - bpf_printk("path name: %s,pid:%d,ppid:%d\n", e->path_name_, pid, ppid); + bpf_map_update_elem(&data,&pid,e,BPF_ANY); + return 0; +} - struct fdtable *fdt = BPF_CORE_READ(task, files, fdt); - if (fdt == NULL) { - bpf_printk("fdt\n"); - bpf_ringbuf_discard(e, 0); +// 跟踪 openat 系统调用的退出 +SEC("tracepoint/syscalls/sys_exit_openat") +int do_syscall_exit(struct trace_event_raw_sys_exit *ctx) +{ + pid_t pid = bpf_get_current_pid_tgid() >> 32; + struct event_open *e = bpf_map_lookup_elem(&data,&pid); + if(!e){ + bpf_printk("sys_exit_openat is failed to found fd\n"); return 0; } - unsigned int i = 0, count = 0, n = BPF_CORE_READ(fdt, max_fds); - bpf_printk("n:%d\n", n); - - e->n_ = n; - e->pid_ = pid; - - bpf_ringbuf_submit(e, 0); - + e->ret = ctx->ret; + + // 分配 ringbuf 空间 + struct event_open *new_e = bpf_ringbuf_reserve(&rb, sizeof(*new_e), 0); + if (!new_e) { + return 0; // 如果分配失败,提前返回 + } + + //复制数据 + new_e->dfd = e->dfd; + new_e->flags = e->flags; + new_e->fd = e->fd; + new_e->ret =e->ret; + new_e->is_created = e->is_created; + new_e->pid = e->pid; + + // 手动读取文件路径,确保不超过最大长度,并添加 '\0' 结束符 + int filename_len = 0; + while (filename_len < sizeof(new_e->filename) - 1) { + char c = 0; + // 读取路径中的每个字符 + bpf_probe_read(&c, sizeof(c), e->filename + filename_len); + if (c == '\0') break; // 如果遇到 null 字符就停止读取 + new_e->filename[filename_len++] = c; + } + // 确保字符串以 '\0' 结束 + new_e->filename[filename_len] = '\0'; + bpf_printk("Opening file: %s, pid: %d, flags: %d\n", new_e->filename, pid, e->flags); + + bpf_ringbuf_submit(new_e, 0); return 0; } - -char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h b/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h index 8c9cc1cdb..ed049ab13 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h +++ b/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h @@ -6,10 +6,13 @@ #define TASK_COMM_LEN 16 struct event_open { - int pid_; - char path_name_[path_size]; - int n_; - char comm[TASK_COMM_LEN]; + pid_t pid; + int dfd; + char filename[path_size]; + int flags; + int fd; // 文件描述符 + int ret; // 系统调用返回值 + bool is_created; // 标记文件是否创建 }; /*read*/ diff --git a/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c b/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c index beef03c45..9a6ef6c85 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c +++ b/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include // 包含文件打开标志宏 #include #include "fs/fs_watcher/open.skel.h" #include "fs/fs_watcher/read.skel.h" @@ -105,7 +107,6 @@ static struct env{ bool disk_io_visit; bool block_rq_issue; bool CacheTrack; - pid_t pid; }env = { .open = false, .read = false, @@ -113,7 +114,6 @@ static struct env{ .disk_io_visit = false, .block_rq_issue = false, .CacheTrack = false, - .pid = -1, }; static const struct argp_option opts[] = { @@ -123,7 +123,6 @@ static const struct argp_option opts[] = { {"disk_io_visit", 'd', 0, 0, "Print disk I/O visit report"}, {"block_rq_issue", 'b', 0, 0, "Print block I/O request submission events. Reports when block I/O requests are submitted to device drivers."}, {"CacheTrack", 't' , 0 ,0 , "WriteBack dirty lagency and other information"}, - {"pid", 'p', "PID", 0, "Specify pid number when report weite. Only support for write report now"}, {0} // 结束标记,用于指示选项列表的结束 }; @@ -142,19 +141,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { env.block_rq_issue = true;break; case 't': env.CacheTrack = true;break; - case 'p': - if (arg) { - env.pid = atoi(arg); - if (env.pid <= 0) { - fprintf(stderr, "Invalid PID value: %s\n", arg); - argp_usage(state); - } - } else { - fprintf(stderr, "-p option requires an argument\n"); - argp_usage(state); - } - break; - default: + default: return ARGP_ERR_UNKNOWN; } return 0; @@ -244,38 +231,65 @@ int main(int argc,char **argv){ } } +const char* flags_to_str(int flags) { + static char str[256]; + str[0] = '\0'; // 清空字符串 + + if (flags & O_RDONLY) strcat(str, "O_RDONLY "); + if (flags & O_WRONLY) strcat(str, "O_WRONLY "); + if (flags & O_RDWR) strcat(str, "O_RDWR "); + if (flags & O_CREAT) strcat(str, "O_CREAT "); + if (flags & O_EXCL) strcat(str, "O_EXCL "); + if (flags & O_TRUNC) strcat(str, "O_TRUNC "); + if (flags & O_APPEND) strcat(str, "O_APPEND "); + if (flags & O_NOFOLLOW) strcat(str, "O_NOFOLLOW "); + if (flags & O_CLOEXEC) strcat(str, "O_CLOEXEC "); + if (flags & O_NONBLOCK) strcat(str, "O_NONBLOCK "); + if (flags & O_SYNC) strcat(str, "O_SYNC "); + if (flags & O_DSYNC) strcat(str, "O_DSYNC "); + if (flags & O_RSYNC) strcat(str, "O_RSYNC "); + if (flags & O_DIRECTORY) strcat(str, "O_DIRECTORY "); + + // 条件编译部分:如果系统定义了 O_NOATIME 和 O_PATH +#ifdef O_NOATIME + if (flags & O_NOATIME) strcat(str, "O_NOATIME "); +#endif + +#ifdef O_PATH + if (flags & O_PATH) strcat(str, "O_PATH "); +#endif + + // 如果没有匹配到标志,返回 "Unknown" + if (str[0] == '\0') { + return "Unknown"; + } + + return str; +} + static int handle_event_open(void *ctx, void *data, size_t data_sz) { - struct event_open *e = (struct event_open *)data; - char *filename = strrchr(e->path_name_, '/'); - ++filename; - - char fd_path[path_size]; - char actual_path[path_size]; - char comm[TASK_COMM_LEN]; - int i = 0; - int map_fd = *(int *)ctx;//传递map得文件描述符 - - - for (; i < e->n_; ++i) { - snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", e->pid_, - i); - ssize_t len = - readlink(fd_path, actual_path, sizeof(actual_path) - 1); - if (len != -1) { - actual_path[len] = '\0'; - int result = strcmp(e->path_name_, actual_path); - if (result == 0) { - if(bpf_map_lookup_elem(map_fd,&e->pid_,&comm)==0){ - printf("%-60s %-8d %-8d %-8s\n", - e->path_name_, i,e->pid_,comm); - }else{ - fprintf(stderr, "Failed to lookup value for key %d\n", e->pid_); - } - - } - } - } + const struct event_open *e = data; + struct tm *tm; + char ts[32]; + time_t t; + + time(&t); + tm = localtime(&t); + strftime(ts, sizeof(ts), "%H:%M:%S", tm); + const char *ret_str; + // 如果返回值是负数,则是错误码,使用 strerror + if (e->ret < 0) { + ret_str = strerror(-e->ret); // 负数表示错误码 + } else { + // 正数表示文件描述符,直接打印文件描述符 + ret_str = "Success"; // 如果是文件描述符,表示成功 + } + + const char *flags_str = flags_to_str(e->flags); + + printf("%-8s %-8d %-8d %-100s %-8s %-8d %-8s %-8s\n", + ts, e->dfd, e->pid,e->filename, flags_str, e->fd, ret_str, e->is_created ? "true" : "false"); return 0; } @@ -352,7 +366,7 @@ static int process_open(struct open_bpf *skel_open){ LOAD_AND_ATTACH_SKELETON_MAP(skel_open,open); - printf("%-60s %-8s %-8s %-8s\n","filenamename","fd","pid","comm"); + printf("%-8s %-8s %-8s %-100s %-8s %-8s %-8s %-8s\n", "TIME","dfd","PID", "filename", "flags", "fd", "ret", "is_created"); POLL_RING_BUFFER(rb, 1000, err); open_cleanup: @@ -381,22 +395,9 @@ static int process_read(struct read_bpf *skel_read){ static int process_write(struct write_bpf *skel_write){ int err; struct ring_buffer *rb; - int arg_index = 0; - - struct dist_args d_args = {-1}; - LOAD_AND_ATTACH_SKELETON(skel_write,write); - d_args.pid = env.pid; - struct bpf_map *arg_map = bpf_object__find_map_by_name((const struct bpf_object *)*(skel_write->skeleton->obj), "args_map"); - err = bpf_map__update_elem(arg_map, &arg_index, sizeof(arg_index), &d_args, sizeof(d_args), BPF_ANY); - - if (err < 0) { - fprintf(stderr, "ERROR: failed to update args map\n"); - goto write_cleanup; - } - printf("%-8s %-8s %-8s %-8s %-8s\n","ds","inode_number","pid","real_count","count"); POLL_RING_BUFFER(rb, 1000, err);