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

cpu_watcher:实现sar功能百分比输出&调度延迟输出进程名 #797

Merged
merged 16 commits into from
May 17, 2024
Merged
14 changes: 14 additions & 0 deletions eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,20 @@ $(TARGETS): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT)
$(call msg,BINARY,$@)
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@

SUCCESS_MESSAGE:
@echo "\e[38;2;255;0;0m __ __ \e[0m"
@echo "\e[38;2;255;128;0m _________ __ __ _ ______ _/ /______/ /_ ___ _____\e[0m"
@echo "\e[38;2;255;255;0m / ___/ __ \/ / / / | | /| / / __ / __/ ___/ __ \/ _ \/ ___/\e[0m"
@echo "\e[38;2;128;255;0m/ /__/ /_/ / /_/ / | |/ |/ / /_/ / /_/ /__/ / / / __/ / \e[0m"
@echo "\e[38;2;0;255;0m\___/ .___/\__,_/ |__/|__/\__,_/\__/\___/_/ /_/\___/_/ \e[0m"
@echo "\e[38;2;0;255;128m /_/ \e[0m"
@echo "\e[38;2;0;255;255mSuccessful to compile cpu_watcher tools: \e[0m"
@echo "\e[38;2;0;255;255mPlease start your use ~ \e[0m"


all: $(TARGETS) SUCCESS_MESSAGE


# delete failed targets
.DELETE_ON_ERROR:

Expand Down
88 changes: 81 additions & 7 deletions eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
#include <time.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include <sys/sysinfo.h>
#include <sys/select.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>
#include "cpu_watcher.h"
Expand All @@ -35,6 +38,7 @@

typedef long long unsigned int u64;
typedef unsigned int u32;
#define MAX_BUF 512

struct list_head {
struct list_head *next;
Expand All @@ -50,6 +54,8 @@ struct msg_msg {

static struct env {
int time;
int period;
bool percent;
bool enable_proc;
bool SAR;
bool CS_DELAY;
Expand All @@ -60,6 +66,8 @@ static struct env {
int freq;
} env = {
.time = 0,
.period = 1,
.percent = false,
.enable_proc = false,
.SAR = false,
.CS_DELAY = false,
Expand Down Expand Up @@ -87,6 +95,7 @@ unsigned long ktTime = 0;
unsigned long utTime = 0;
u64 tick_user = 0;


int sc_sum_time = 0 ;
int sc_max_time = 0 ;
int sc_min_time = SYSCALL_MIN_TIME ;
Expand All @@ -102,6 +111,8 @@ int preempt_start_print = 0 ;
const char argp_program_doc[] ="cpu wacher is in use ....\n";
static const struct argp_option opts[] = {
{ "time", 't', "TIME-SEC", 0, "Max Running Time(0 for infinite)" },
{ "period", 'i', "INTERVAL", 0, "Period interval in seconds" },
{"percent",'P',0,0,"format data as percentages"},
{"libbpf_sar", 's', 0,0,"print sar_info (the data of cpu)"},
{"cs_delay", 'c', 0,0,"print cs_delay (the data of cpu)"},
{"syscall_delay", 'S', 0,0,"print syscall_delay (the data of syscall)"},
Expand All @@ -118,6 +129,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
env.time = strtol(arg, NULL, 10);
if(env.time) alarm(env.time);
break;
case 'i':
env.period = strtol(arg, NULL, 10);
break;
case 'P':
env.percent = true;
break;
case 's':
env.SAR = true;
break;
Expand Down Expand Up @@ -219,6 +236,7 @@ u64 find_ksym(const char* target_symbol) {

static int print_all()
{
int nprocs = get_nprocs();
/*proc:*/
int key_proc = 1;
int err_proc, fd_proc = bpf_map__fd(sar_skel->maps.countMap);
Expand Down Expand Up @@ -334,10 +352,30 @@ static int print_all()
if(env.enable_proc){
time_t now = time(NULL);
struct tm *localTime = localtime(&now);
printf("%02d:%02d:%02d %8llu %8llu %6d %8llu %10llu %8llu %10lu %8llu %8llu %8llu\n",
if (env.percent == true){
printf("%02d:%02d:%02d %8llu %8llu %6d ",localTime->tm_hour, localTime->tm_min, localTime->tm_sec,__proc, __sched, runqlen);
// 大于百分之60的标红输出
double values[7] = {
(double)dtairqtime / 10000000 / nprocs / env.period,
(double)dtasoftirq / 10000000 / nprocs / env.period,
(double)dtaidle / 10000000 / nprocs / env.period,
(double)dtaKT / 10000000 / nprocs / env.period,
(double)dtaSysc / 10000000 / nprocs / env.period,
(double)dtaUTRaw / 10000000 / nprocs / env.period,
(double)dtaSys / 10000000 / nprocs / env.period
};
for (int i = 0; i < 7; i++) {
if (values[i] > 60.0) {
printf("\033[1;31m"); // 设置为红色
}
printf("%10.2f ", values[i]);
printf("\033[0m"); // 重置为默认颜色
}
printf("\n");
}else{printf("%02d:%02d:%02d %8llu %8llu %6d %8llu %10llu %8llu %10lu %8llu %8llu %8llu\n",
localTime->tm_hour, localTime->tm_min, localTime->tm_sec,
__proc,__sched,runqlen,dtairqtime/1000,dtasoftirq/1000,dtaidle/1000000,
dtaKT/1000,dtaSysc / 1000000,dtaUTRaw/1000000,dtaSys / 1000000);
dtaKT/1000,dtaSysc / 1000000,dtaUTRaw/1000000,dtaSys / 1000000);}
}
else{
env.enable_proc = true;
Expand Down Expand Up @@ -440,6 +478,32 @@ static int preempt_print(void *ctx, void *data, unsigned long data_sz)
return 0;
}

char* get_process_name_by_pid(int pid) {
static char buf[MAX_BUF];
char command[MAX_BUF];
snprintf(command, sizeof(command), "cat /proc/%d/status | grep Name", pid);
FILE* fp = popen(command, "r");
if (fp == NULL) {
perror("popen");
return NULL;
}
char* name = NULL;
while (fgets(buf, sizeof(buf), fp)) {
if (strncmp(buf, "Name:", 5) == 0) {
name = strdup(buf + 6);
break;
}
}
pclose(fp);
if (name != NULL) {
size_t len = strlen(name);
if (len > 0 && name[len - 1] == '\n') {
name[len - 1] = '\0';
}
}
return name;
}

static int schedule_print(struct bpf_map *sys_fd)
{
int key = 0;
Expand All @@ -460,8 +524,16 @@ static int schedule_print(struct bpf_map *sys_fd)
if(!ifprint){
ifprint=1;
}else{
printf("%02d:%02d:%02d %-15lf %-15lf %5d %15lf %10d\n",
hour, min, sec, avg_delay / 1000.0, info.max_delay / 1000.0,info.pid_max, info.min_delay / 1000.0,info.pid_min);
char* proc_name_max = get_process_name_by_pid(info.pid_max);
char* proc_name_min = get_process_name_by_pid(info.pid_min);
printf("%02d:%02d:%02d %-15lf %-15lf %10s %15lf %15s\n",
hour, min, sec, avg_delay / 1000.0, info.max_delay / 1000.0,proc_name_max,info.min_delay / 1000.0,proc_name_min);
if (proc_name_max != NULL) {
free(proc_name_max);
}
if (proc_name_min != NULL) {
free(proc_name_min);
}
}
return 0;
}
Expand Down Expand Up @@ -617,7 +689,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto schedule_cleanup;
}
printf("%-8s %s\n", " TIME ", "avg_delay/μs max_delay/μs max_pid min_delay/μs min_pid");
printf("%-8s %s\n", " TIME ", "avg_delay/μs max_delay/μs max_proc_name min_delay/μs min_proc_name");
}else if (env.SAR){
/* Load and verify BPF application */
sar_skel = sar_bpf__open();
Expand Down Expand Up @@ -646,7 +718,9 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto sar_cleanup;
}
printf(" time proc/s cswch/s runqlen irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms \n");
if (env.percent){
printf(" time proc/s cswch/s runqlen irqTime/%% softirq/%% idle/%% kthread/%% sysc/%% utime/%% sys/%% \n");
}else{printf(" time proc/s cswch/s runqlen irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms \n");}
}else if(env.MQ_DELAY){
/* Load and verify BPF application */
mq_skel = mq_delay_bpf__open();
Expand Down Expand Up @@ -678,7 +752,7 @@ int main(int argc, char **argv)
}
while (!exiting) {
if(env.SAR){
sleep(1);
sleep(env.period);
err = print_all();
if (err == -EINTR) {
err = 0;
Expand Down
Loading