Skip to content

Commit

Permalink
cpu_watcher:实现sar功能百分比输出&调度延迟输出进程名 (#797)
Browse files Browse the repository at this point in the history
* 添加第三方库

* 添加工具说明文档

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* cpu_watcher:修改部分warning&schedule_delay功能扩充

* 输出净化

* 在用户态直接输出最大最小调度时延进程名

* sar功能添加百分比输出功能

* .
  • Loading branch information
vvzxy authored May 17, 2024
1 parent 635deeb commit eea66dc
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 7 deletions.
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 @@ -619,7 +691,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 @@ -648,7 +720,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 @@ -681,7 +755,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

0 comments on commit eea66dc

Please sign in to comment.