Skip to content

Commit

Permalink
add comments (#652)
Browse files Browse the repository at this point in the history
  • Loading branch information
Monkey857 authored Jan 23, 2024
1 parent d6c2360 commit 2c8d082
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 25 deletions.
12 changes: 10 additions & 2 deletions eBPF_Supermarket/kvm_watcher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ BPF program used for monitoring KVM event
## 五、测试

可以按照如下流程测试程序输出:

- **查看本地是否支持虚拟化**
```
grep -Eoc '(vmx|svm)' /proc/cpuinfo
若大于0,则支持
```
- **安装依赖**

```
Expand All @@ -134,7 +138,11 @@ BPF program used for monitoring KVM event
```
sudo qemu-system-x86_64 -enable-kvm -cpu host -m 2048 -drive file=cirros-0.5.1-x86_64-disk.img,format=qcow2 -boot c -nographic
```

- **也可以使用virt-manager图形化工具来创建并启动虚拟机**
```
sudo apt install qemu qemu-kvm libvirt-daemon-system libvirt-clients virt-manager virtinst bridge-utils
接下来就可以使用virt-manager图形化工具来设置虚拟机了
```
- **编译&&运行程序**

```
Expand Down
8 changes: 4 additions & 4 deletions eBPF_Supermarket/kvm_watcher/include/kvm_exits.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>

//定义哈希结构,存储时间信息
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
Expand All @@ -38,7 +38,7 @@ struct {
__type(key, u32);
__type(value, u32);
} counts SEC(".maps");

//记录退出的信息
struct exit {
u64 pad;
unsigned int exit_reason;
Expand All @@ -52,7 +52,7 @@ struct exit {
};

int total = 0;

//记录vm_exit的原因以及时间
static int trace_kvm_exit(struct exit *ctx, pid_t vm_pid) {
u64 id, ts;
id = bpf_get_current_pid_tgid();
Expand All @@ -79,7 +79,7 @@ static int trace_kvm_exit(struct exit *ctx, pid_t vm_pid) {
}
return 0;
}

//通过kvm_exit所记录的信息,来计算出整个处理的时间
static int trace_kvm_entry(void *rb, struct common_event *e) {
struct reason_info *reas;
pid_t pid, tid;
Expand Down
4 changes: 2 additions & 2 deletions eBPF_Supermarket/kvm_watcher/include/kvm_vcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct {
__type(key, u32);
__type(value, u32);
} vcpu_tid SEC(".maps");

//记录vcpu_halt的id信息
static int trace_kvm_vcpu_halt(struct kvm_vcpu *vcpu, pid_t vm_pid) {
CHECK_PID(vm_pid) {
u32 tid = bpf_get_current_pid_tgid();
Expand All @@ -63,7 +63,7 @@ static int trace_kvm_vcpu_halt(struct kvm_vcpu *vcpu, pid_t vm_pid) {
}
return 0;
}

//使用kvm_vcpu_halt记录的数据,来获取vcpu的启动信息
static int trace_kvm_vcpu_wakeup(struct vcpu_wakeup *ctx, void *rb,
struct common_event *e, pid_t vm_pid) {
CHECK_PID(vm_pid) {
Expand Down
10 changes: 6 additions & 4 deletions eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,33 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL";
const volatile pid_t vm_pid = -1;
static struct common_event *e;

//定义环形缓冲区maps
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

//获取vcpu的id
SEC("fentry/kvm_vcpu_halt")
int BPF_PROG(fentry_kvm_vcpu_halt, struct kvm_vcpu *vcpu) {
return trace_kvm_vcpu_halt(vcpu, vm_pid);
}

//追踪vcpu运行信息
SEC("tp/kvm/kvm_vcpu_wakeup")
int tp_vcpu_wakeup(struct vcpu_wakeup *ctx) {
return trace_kvm_vcpu_wakeup(ctx, &rb, e, vm_pid);
}

//记录vcpu的halt_poll(暂停轮询)时间变化
SEC("tp/kvm/kvm_halt_poll_ns")
int tp_kvm_halt_poll_ns(struct halt_poll_ns *ctx) {
return trace_kvm_halt_poll_ns(ctx, &rb, e, vm_pid);
}

//记录vm_exit的时间
SEC("tp/kvm/kvm_exit")
int tp_exit(struct exit *ctx) {
return trace_kvm_exit(ctx, vm_pid);
}

//记录vm_entry和vm_exit的时间差
SEC("tp/kvm/kvm_entry")
int tp_entry(struct exit *ctx) {
return trace_kvm_entry(&rb, e);
Expand Down
34 changes: 21 additions & 13 deletions eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include <unistd.h>
#include "../include/kvm_watcher.h"
#include "kvm_watcher.skel.h"

//定义具体的退出原因
struct ExitReason exitReasons[] = {{0, "EXCEPTION_NMI"},
{1, "EXTERNAL_INTERRUPT"},
{2, "TRIPLE_FAULT"},
Expand Down Expand Up @@ -169,7 +169,7 @@ void freeExitInfoList(Node *head) {
free(temp);
}
}

//打印退出的信息
void printExitInfo(Node *head) {
Node *current = head;
CLEAR_SCREEN();
Expand All @@ -185,7 +185,7 @@ void printExitInfo(Node *head) {
current = current->next;
}
}

//检查具有给定 PID 的进程是否存在
int doesVmProcessExist(pid_t pid) {
char proc_name[256];
snprintf(proc_name, sizeof(proc_name), "/proc/%d/cmdline", pid);
Expand All @@ -197,6 +197,7 @@ int doesVmProcessExist(pid_t pid) {
if (proc_name[size - 1] == '\n') {
proc_name[size - 1] = '\0'; // Remove newline character
}
//查看是否进程文件中是否出现"qemu-system"字符串
if (strstr(proc_name, "qemu-system") != NULL) {
fclose(file);
return 1; // VmProcess name contains the target string
Expand All @@ -223,7 +224,7 @@ struct KeyValPair {
int compare(const void *a, const void *b) {
return ((struct KeyValPair *)b)->value - ((struct KeyValPair *)a)->value;
}

//保存脏页信息到./temp/dirty_temp文件中
int save_count_dirtypagemap_to_file(struct bpf_map *map) {
const char *directory = "./temp";
const char *filename = "./temp/dirty_temp";
Expand Down Expand Up @@ -289,7 +290,7 @@ int save_count_dirtypagemap_to_file(struct bpf_map *map) {
free(pairs);
return 0;
}

//定义env结构体,用来存储程序中的事件信息
static struct env {
bool execute_vcpu_wakeup;
bool execute_exit;
Expand Down Expand Up @@ -320,7 +321,7 @@ const char *argp_program_version = "kvm_watcher 1.0";
const char *argp_program_bug_address = "<[email protected]>";
const char argp_program_doc[] = "BPF program used for monitoring KVM event\n";
int option_selected = 0; // 功能标志变量,确保激活子功能

//具体解释命令行参数
static const struct argp_option opts[] = {
{"vcpu_wakeup", 'w', NULL, 0, "Monitoring the wakeup of vcpu."},
{"vm_exit", 'e', NULL, 0, "Monitoring the event of vm exit."},
Expand All @@ -340,7 +341,7 @@ static const struct argp_option opts[] = {
{"monitoring_time", 't', "SEC", 0, "Time for monitoring."},
{},
};

//解析命令行参数
static error_t parse_arg(int key, char *arg, struct argp_state *state) {
switch (key) {
case 'w':
Expand Down Expand Up @@ -407,7 +408,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) {
}
return 0;
}

//定义解析参数的处理函数
static const struct argp argp = {
.options = opts,
.parser = parse_arg,
Expand All @@ -420,7 +421,7 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format,
}

static volatile bool exiting = false;

//设置信号来控制是否打印信息
static void sig_handler(int sig) {
exiting = true;
}
Expand All @@ -447,7 +448,7 @@ static int determineEventType(struct env *env) {
}
return 0;
}

//获取中断控制器的类型
const char *get_irqchip(unsigned char chip) {
if (chip >= KVM_NR_IRQCHIPS) {
return "Invalid";
Expand All @@ -461,7 +462,7 @@ const char *get_irqchip(unsigned char chip) {
return "Unknown";
}
}

/*环形缓冲区的处理函数,用来打印ringbuff中的数据(最后展示的数据行)*/
static int handle_event(void *ctx, void *data, size_t data_sz) {
struct common_event *e = data;
switch (env.event_type) {
Expand Down Expand Up @@ -569,7 +570,7 @@ static int handle_event(void *ctx, void *data, size_t data_sz) {

return 0;
}

/*通过env->event_type属性来选择需要打印的信息表头*/
static int print_event_head(struct env *env) {
if (!env->event_type) {
// 处理无效参数,可以选择抛出错误或返回
Expand Down Expand Up @@ -610,7 +611,7 @@ static int print_event_head(struct env *env) {
}
return 0;
}

/*通过env结构体的属性真值来判断是否加载某个挂载函数*/
static void set_disable_load(struct kvm_watcher_bpf *skel) {
bpf_program__set_autoload(skel->progs.tp_vcpu_wakeup,
env.execute_vcpu_wakeup ? true : false);
Expand Down Expand Up @@ -639,16 +640,19 @@ static void set_disable_load(struct kvm_watcher_bpf *skel) {
}

int main(int argc, char **argv) {
//定义一个环形缓冲区
struct ring_buffer *rb = NULL;
struct kvm_watcher_bpf *skel;
int err;

/* Parse command line arguments */
/*解析命令行参数*/
err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
if (err)
return err;

/* Set up libbpf errors and debug info callback */
/*设置libbpf的错误和调试信息回调*/
libbpf_set_print(libbpf_print_fn);

/* Cleaner handling of Ctrl-C */
Expand All @@ -666,23 +670,27 @@ int main(int argc, char **argv) {
skel->rodata->vm_pid = env.vm_pid;

/* Disable or load kernel hook functions */
/* 禁用或加载内核挂钩函数 */
set_disable_load(skel);

/* Load & verify BPF programs */
/* 加载并验证BPF程序 */
err = kvm_watcher_bpf__load(skel);
if (err) {
fprintf(stderr, "Failed to load and verify BPF skeleton\n");
goto cleanup;
}

/* Attach tracepoint handler */
/* 附加跟踪点处理程序 */
err = kvm_watcher_bpf__attach(skel);
if (err) {
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto cleanup;
}

/* Set up ring buffer polling */
/* 设置环形缓冲区轮询 */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
Expand Down

0 comments on commit 2c8d082

Please sign in to comment.