Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化代码输出结果 #578

Merged
merged 25 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1edfd84
Upload 2023.6.29 会议纪要.md
nanshuaibo Jun 13, 2023
2d0eea9
Merge branch 'linuxkerneltravel:develop' into develop
nanshuaibo Jul 11, 2023
f5caeb1
Add files via upload
nanshuaibo Jul 11, 2023
c41296e
Merge branch 'linuxkerneltravel:develop' into develop
nanshuaibo Aug 7, 2023
071a871
上传2023.8.4会议纪要
nanshuaibo Aug 7, 2023
38a20ba
Update 2023.8.4 会议纪要.md
nanshuaibo Aug 7, 2023
687dab7
Merge branch 'linuxkerneltravel:develop' into develop
nanshuaibo Sep 20, 2023
ecd9e61
Add files via upload
nanshuaibo Sep 20, 2023
8860390
Merge branch 'linuxkerneltravel:develop' into develop
nanshuaibo Oct 27, 2023
6afcb1a
add kvm_watcher dir
nanshuaibo Oct 27, 2023
62764a3
modify directory name
nanshuaibo Oct 27, 2023
398a108
add kvm_watcher.yml
nanshuaibo Oct 27, 2023
3269f7b
update yml
nanshuaibo Nov 2, 2023
8d07c57
update .yml
nanshuaibo Nov 2, 2023
b8d639d
update kvm_exit.c
nanshuaibo Nov 2, 2023
57f1f1c
update .yml
nanshuaibo Nov 2, 2023
5bdfba7
load kvm mod
nanshuaibo Nov 2, 2023
90aa90a
添加文件头信息
nanshuaibo Nov 3, 2023
4955ce5
Merge branch 'linuxkerneltravel:develop' into develop
nanshuaibo Nov 10, 2023
1a61d23
优化结果输出
nanshuaibo Nov 10, 2023
f25e04c
Update kvm_exits.bpf.c
nanshuaibo Nov 10, 2023
90cd78b
调整Action文件
nanshuaibo Nov 10, 2023
40d54a6
Merge branch 'develop' of github.com:nanshuaibo/lmp into develop
nanshuaibo Nov 10, 2023
1d72cef
Update kvm_exits.c
nanshuaibo Nov 10, 2023
3e62c21
Update kvm_exits.c
nanshuaibo Nov 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/kvm_watcher.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
run: |
cd eBPF_Supermarket/kvm_watcher/kvm_exits
make
sudo ./kvm_exits
sudo ./kvm_exits -t 5
51 changes: 28 additions & 23 deletions eBPF_Supermarket/kvm_watcher/kvm_exits/kvm_exits.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ struct {
} rb SEC(".maps");

struct exit{
u64 pad;
unsigned int exit_reason;
u64 pad;
unsigned int exit_reason;
unsigned long guest_rip;
u32 isa;
u64 info1;
Expand All @@ -55,31 +55,36 @@ struct exit{
};

int total=0;
const volatile pid_t vm_pid = 0;


SEC("tp/kvm/kvm_exit")
int handle_kvm_exit(struct exit *ctx)
{
pid_t tid;
u64 id,ts;
id = bpf_get_current_pid_tgid();
pid_t tid,pid;
u64 id,ts;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是缩进了 2 个 tab 吗?

id = bpf_get_current_pid_tgid();
tid = (u32)id;
ts = bpf_ktime_get_ns();
u32 reason;
reason=(u32)ctx->exit_reason;
struct reason_info reas={};
reas.reason=reason;
reas.time=ts;
u32 *count;
count=bpf_map_lookup_elem(&counts, &reason);
if(count){
(*count)++;
reas.count=*count;
}else{
u32 new_count = 1;
reas.count=new_count;
bpf_map_update_elem(&counts, &reason, &new_count, BPF_ANY);
}
bpf_map_update_elem(&times, &tid, &reas, BPF_ANY);
pid = id >> 32;
if (vm_pid == 0 || pid == vm_pid){
ts = bpf_ktime_get_ns();
u32 reason;
reason=(u32)ctx->exit_reason;
struct reason_info reas={};
reas.reason=reason;
reas.time=ts;
u32 *count;
count=bpf_map_lookup_elem(&counts, &reason);
if(count){
(*count)++;
reas.count=*count;
}else{
u32 new_count = 1;
reas.count=new_count;
bpf_map_update_elem(&counts, &reason, &new_count, BPF_ANY);
}
bpf_map_update_elem(&times, &tid, &reas, BPF_ANY);
}
return 0;
}

Expand All @@ -94,7 +99,7 @@ int handle_kvm_entry()
tid = (u32)id;
reas = bpf_map_lookup_elem(&times, &tid);
if(reas){
u32 reason;
u32 reason;
struct event *e;
int count=0;
duration_ns=bpf_ktime_get_ns() - reas->time;
Expand Down
187 changes: 179 additions & 8 deletions eBPF_Supermarket/kvm_watcher/kvm_exits/kvm_exits.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/resource.h>
#include <time.h>
#include <argp.h>
#include <bpf/libbpf.h>
#include "kvm_exits.skel.h"
#include "kvm_exits.h"

// 存储所有退出原因的映射关系

// 存储所有exit reason的映射关系
// from arch/x86/include/uapi/asm/vmx.h
struct ExitReason exitReasons[] = {
{0, "EXCEPTION_NMI"},
Expand Down Expand Up @@ -102,6 +106,163 @@ const char* getExitReasonName(int number) {
return "Unknown"; // 如果找不到对应的退出原因,返回一个默认值
}

typedef struct {
int exit_reason;
char info[256]; // 替换成适当的大小
unsigned long long total_dur;
unsigned long long avg_dur;
} ExitInfo;

// 链表节点
typedef struct Node {
ExitInfo data;
struct Node* next;
} Node;

Node* exitInfoBuffer = NULL;

void addExitInfo(Node** head, int exit_reason, const char* info,unsigned long long dur,int count) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data.exit_reason = exit_reason;
strncpy(newNode->data.info, info, sizeof(newNode->data.info));
newNode->next = NULL;
newNode->data.total_dur = dur;
newNode->data.avg_dur = dur / count;

// 检查是否已经存在相同 exit reason 的信息
Node* current = *head;
Node* previous = NULL;
while (current != NULL) {
if (current->data.exit_reason == exit_reason) {
// 更新已存在的信息
strncpy(current->data.info, info, sizeof(current->data.info));
current->data.total_dur=dur+current->data.total_dur;
current->data.avg_dur=current->data.total_dur/count;
free(newNode); // 释放新节点,因为信息已经更新
return;
}
previous = current;
current = current->next;
}
// 没有找到相同的 exit reason,将新节点添加到链表
if (previous != NULL) {
previous->next = newNode;
} else {
*head = newNode;
}
}

// 查找指定退出原因的信息
const char* findExitInfo(Node* head, int exit_reason) {
Node* current = head;
while (current != NULL) {
if (current->data.exit_reason == exit_reason) {
return current->data.info;
}
current = current->next;
}
return NULL;
}

// 释放链表
void freeExitInfoList(Node* head) {
while (head != NULL) {
Node* temp = head;
head = head->next;
free(temp);
}
}

void printExitInfo(Node* head) {
Node* current = head;
printf("%-23s %-10s %-14s %-8s %-13s \n", "EXIT_REASON", "COMM","PID/TID","COUNT","AVG_DURATION(ns)"/*,"PCT"*/);
while (current != NULL) {
printf("%-2d/%-20s %-32s %-13llu \n", current->data.exit_reason,getExitReasonName(current->data.exit_reason), current->data.info,current->data.avg_dur);
current = current->next;
}
}

int doesVmProcessExist(pid_t pid) {
char proc_name[256];
snprintf(proc_name, sizeof(proc_name), "/proc/%d/cmdline", pid);
FILE *file = fopen(proc_name, "r");
if (file) {
size_t size;
size = fread(proc_name, 1, sizeof(proc_name), file);
if (size > 0) {
if (proc_name[size - 1] == '\n') {
proc_name[size - 1] = '\0'; // Remove newline character
}
if (strstr(proc_name, "qemu-system-x86_64") != NULL) {
fclose(file);
return 1; // VmProcess name contains the target string
} else {
fclose(file);
fprintf(stderr, "Process exist!but is not vmprocess: %d\n", pid);
return 0; // VmProcess name does not contain the target string
}
}
fclose(file);
}
fprintf(stderr, "Process name does not find: %d\n", pid);
return 0; // VmProcess with the given PID not found
}

static struct env {
int monitoring_time;
pid_t vm_pid;
} env={
.monitoring_time=0,
.vm_pid=0,
};

const char *argp_program_version = "kvm_exits 1.0";
const char *argp_program_bug_address = "<[email protected]>";
const char argp_program_doc[] = "BPF program used for outputting VM exit reason\n";

static const struct argp_option opts[] = {
{ "monitoring_time", 't', "TIME-SEC", 0, "Set the time for profiling VM exit event reasons" },
{ "vm_pid", 'p', "PID", 0, "Specify the virtual machine pid to monitor." },
{},
};

static error_t parse_arg(int key, char *arg, struct argp_state *state)
{
switch (key) {
case 't':
errno = 0;
env.monitoring_time = strtol(arg, NULL, 10);
if (errno || env.monitoring_time <= 0) {
fprintf(stderr, "Invalid duration: %s\n", arg);
argp_usage(state);
}
else{
alarm(env.monitoring_time);
}
break;
case 'p':
env.vm_pid=strtol(arg, NULL, 10);
if(env.vm_pid<=0 || doesVmProcessExist(env.vm_pid)==0 ){
fprintf(stderr, "Invalid vm_pid: %s\n", arg);
argp_usage(state);
}
break;
case ARGP_KEY_ARG:
argp_usage(state);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}

static const struct argp argp = {
.options = opts,
.parser = parse_arg,
.doc = argp_program_doc,
};


static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
Expand All @@ -112,38 +273,47 @@ static volatile bool exiting = false;
static void sig_handler(int sig)
{
exiting = true;
printf("\n");
printf("---------------------------------------------------------------------------\n");
printExitInfo(exitInfoBuffer);
freeExitInfoList(exitInfoBuffer);
}

static int handle_event(void *ctx, void *data, size_t data_sz)
{
const struct event *e = data;
printf("%-2d/%-20s %-10s %-5u/%-8u %-10d %-12llu %.2f%%\n", e->reason_number,getExitReasonName(e->reason_number), e->comm, e->pid,e->tid,e->count,e->duration_ns,(double)e->count / e->total * 100.0);

char info_buffer[256];
printf("%-2d/%-20s %-10s %-5u/%-8u %-8d %-13llu \n", e->reason_number,getExitReasonName(e->reason_number), e->comm, e->pid,e->tid,e->count,e->duration_ns/*,(double)e->count / e->total * 100.0*/);
snprintf(info_buffer, sizeof(info_buffer), "%-10s %-5u/%-8u %-8d", e->comm, e->pid,e->tid,e->count);
addExitInfo(&exitInfoBuffer,e->reason_number,info_buffer,e->duration_ns,e->count);
return 0;
}

int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct ring_buffer *rb = NULL;
struct kvm_exits_bpf *skel;
int err;

alarm(3);
/* 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_set_print(libbpf_print_fn);

/* Cleaner handling of Ctrl-C */
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGALRM, sig_handler);
signal(SIGALRM, sig_handler);
/* Open BPF application */
skel = kvm_exits_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeleton\n");
return 1;
}

skel->rodata->vm_pid = env.vm_pid;
/* Load & verify BPF programs */
err = kvm_exits_bpf__load(skel);
if (err) {
Expand All @@ -166,7 +336,7 @@ int main(int argc, char **argv)
goto cleanup;
}
/* Process events */
printf("%-23s %-10s %-14s %-10s %-11s %-10s \n", "EXIT_REASON", "COMM","PID/TID","COUNT","DURATION(ns)","PCT");
printf("%-23s %-10s %-14s %-8s %-13s \n", "EXIT_REASON", "COMM","PID/TID","COUNT","DURATION(ns)"/*,"PCT"*/);
while (!exiting) {
err = ring_buffer__poll(rb, 10 /* timeout, ms */);
/* Ctrl-C will cause -EINTR */
Expand All @@ -180,6 +350,7 @@ int main(int argc, char **argv)
}
}
cleanup:
/* Clean up */
ring_buffer__free(rb);
kvm_exits_bpf__destroy(skel);
return -err;
Expand Down