Skip to content

Commit

Permalink
add cswch & runqlen
Browse files Browse the repository at this point in the history
  • Loading branch information
albertxu216 committed Nov 3, 2023
1 parent 538a555 commit a0fd77e
Show file tree
Hide file tree
Showing 3 changed files with 130,568 additions and 18 deletions.
157 changes: 152 additions & 5 deletions eBPF_Supermarket/CPU_Subsystem/libbpf_sar/libbpf_sar.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,60 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL";

const volatile long long unsigned int forks_addr = 0;

// 计数表格,第0项为上下文切换次数,第1项为总共新建进程个数
// 计数表格,第0项为所统计fork数,第1项为进程切换数,第2项为运行队列长度
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 3);
__uint(type, BPF_MAP_TYPE_ARRAY);//基于数组的映射
__uint(max_entries, 3);//countMap 可以存储最多 3 对键值对
__type(key, int);
__type(value, u64);
} countMap SEC(".maps");

// 记录开始的时间
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__type(value, u64);
} start SEC(".maps");//记录时间戳;

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

//cswch_args结构体
struct cswch_args {
u64 pad;
char prev_comm[16];
pid_t prev_pid;
int prev_prio;
long prev_state;
char next_comm[16];
pid_t next_pid;
int next_prio;
};

// 储存运行队列rq的全局变量
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, struct rq);
} rq_map SEC(".maps");


struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, int);
} runqlen SEC(".maps");//多CPU数组



// 统计fork数
SEC("kprobe/finish_task_switch.isra.0")
SEC("kprobe/finish_task_switch")
int kprobe__finish_task_switch(struct pt_regs *ctx)
{
u32 key = 0;
Expand All @@ -51,4 +95,107 @@ int kprobe__finish_task_switch(struct pt_regs *ctx)
}

return 0;
}
}



//获取进程切换数;
SEC("tracepoint/sched/sched_switch")//静态挂载点
int trace_sched_switch2(struct cswch_args *info) {
//从参数info中获取上一个(prev)和下一个(next)进程的进程号
pid_t prev = info->prev_pid, next = info->next_pid;//定义上一个、下一个进程的进程号

// 只有当上一个进程和下一个进程不相同时才执行以下操作,相同则代表是同一个进程
if (prev != next) {
u32 key = 1;
u64 *valp, delta, cur;
struct task_struct *ts;

// 将下一个进程的进程号赋给pid
pid_t pid = next;
u64 time = bpf_ktime_get_ns()/1000;//获取当前时间,ms;

// Step1: 记录next进程的起始时间
bpf_map_update_elem(&start,&pid,&time,BPF_ANY);//上传当前时间到start map中
//procStartTime.update(&pid, &time);//python

// Step2: Syscall时间处理
// record_sysc(time, prev, next);

// Step3: UserMode时间处理
// record_user(time, prev, next);

// Step4: 记录上下文切换的总次数
valp = bpf_map_lookup_elem(&countMap,&key);
if (!valp) {
// 没有找到表项
u64 initval = 1;
bpf_map_update_elem(&countMap,&key,&initval,BPF_ANY);//初始化切换次数到countMap中
}
else *valp += 1;
//bpf_map_update_elem(&countMap,&key,&valp,BPF_ANY);//上传当前切换次数到countMap中
}

return 0;
}

/*
SEC("kprobe/finish_task_switch")//动态挂载点
int trace_sched_switch(struct cswch_args *info) {
//从参数info中获取上一个(prev)和下一个(next)进程的进程号
pid_t prev = info->prev_pid, next = info->next_pid;//定义上一个、下一个进程的进程号
// 只有当上一个进程和下一个进程不相同时才执行以下操作,相同则代表是同一个进程
if (prev != next) {
u32 key = 2;
u64 *valp, delta, cur;
struct task_struct *ts;
// 将下一个进程的进程号赋给pid
pid_t pid = next;
u64 time = bpf_ktime_get_ns()/1000;//获取当前时间,ms;
// Step1: 记录next进程的起始时间
bpf_map_update_elem(&start,&pid,&time,BPF_ANY);//上传当前时间到start map中
//procStartTime.update(&pid, &time);//python
// Step2: Syscall时间处理
// record_sysc(time, prev, next);
// Step3: UserMode时间处理
// record_user(time, prev, next);
// Step4: 记录上下文切换的总次数
valp = bpf_map_lookup_elem(&countMap,&key);
if (!valp) {
// 没有找到表项
u64 initval = 1;
bpf_map_update_elem(&countMap,&key,&initval,BPF_ANY);//初始化切换次数到countMap中
}
else *valp += 1;
//bpf_map_update_elem(&countMap,&key,&valp,BPF_ANY);//上传当前切换次数到countMap中
}
return 0;
}
*/


//统计运行队列长度
SEC("kprobe/update_rq_clock")
int kprobe_update_rq_clock(struct pt_regs *ctx){
u32 key = 2;
u32 rqkey = 0;
struct rq *p_rq = 0;
p_rq = (struct rq *)bpf_map_lookup_elem(&rq_map, &rqkey);
if (!p_rq) {
return 0;
}

bpf_probe_read_kernel(p_rq, sizeof(struct rq), (void *)PT_REGS_PARM1(ctx));
//使用bpf_probe_read_kernel函数将内核空间中的数据复制到p_rq所指向的内存区域中,以便后续对该数据进行访问和操作。
u64 val = p_rq->nr_running;
bpf_map_update_elem(&countMap,&key,&val,BPF_ANY);
return 0;
}

126 changes: 113 additions & 13 deletions eBPF_Supermarket/CPU_Subsystem/libbpf_sar/libbpf_sar.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,26 @@
#define warn(...) fprintf(stderr, __VA_ARGS__)
typedef long long unsigned int u64;

static volatile bool exiting = false;
static volatile bool exiting = false;//全局变量,表示程序是否正在退出

// 长期保存的数值
static u64 proc = 0;
static u64 sched =0;
static u64 sched2 =0;

static u64 sum[10] = {};
static u64 sum[10] = {};//用于存储要输出的各个数据结果;

static int line = 0;

// sar 工具的参数设置
static struct env {
int time;
bool enable_proc;
//bool enable_sched_prwitch;
} env = {
.time = 0,
.enable_proc = false,
//.enable_sched_prwitch = false,
};

const char argp_program_doc[] ="libbpf_sar is a program that simulates sar constructed by libbpf for dynamic CPU indicator monitoring.\n";
Expand Down Expand Up @@ -79,24 +83,91 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
static void sig_handler(int sig)
{
exiting = true;
}
}//正在退出程序;

static int print_countMap(struct bpf_map *map)
{
int key = 1;
int err, fd = bpf_map__fd(map);
unsigned long total_forks;


int key = 0;// 设置要查找的键值为1
int err, fd = bpf_map__fd(map);// 获取映射文件描述符
u64 total_forks;// 用于存储从映射中查找到的值
err = bpf_map_lookup_elem(fd, &key, &total_forks); // 从映射中查找键为1的值
if (err < 0) {//没找到
fprintf(stderr, "failed to lookup infos of total_forks: %d\n", err);
return -1;
}


key = 1;// 设置要查找的键值为1
u64 sched_total;// 用于存储从映射中查找到的值
//int err, fd = bpf_map__fd(map);// 获取映射文件描述符
err = bpf_map_lookup_elem(fd, &key, &sched_total); // 从映射中查找键为1的值
if (err < 0) {//没找到
fprintf(stderr, "failed to lookup infos of sched_total: %d\n", err);
return -1;
}

err = bpf_map_lookup_elem(fd, &key, &total_forks);
if (err < 0) {
fprintf(stderr, "failed to lookup infos: %d\n", err);

key=2;
int runqlen;// 用于存储从映射中查找到的值
err = bpf_map_lookup_elem(fd, &key, &runqlen); // 从映射中查找键为1的值
if (err < 0) {//没找到
fprintf(stderr, "failed to lookup infos of runqlen: %d\n", err);
return -1;
}


//proc:
u64 proc_s;
proc_s = total_forks-proc;
proc = total_forks;//统计差值;


//cswch:
u64 sched_pr;
sched_pr= sched_total - sched;//计算差值;
sched = sched_total;

//runqlen:
/*nothing*/

//判断打印:
if(env.enable_proc){
time_t now = time(NULL);// 获取当前时间
struct tm *localTime = localtime(&now);// 将时间转换为本地时间结构
printf("%02d:%02d:%02d %6lld %6lld %6d\n",
localTime->tm_hour, localTime->tm_min, localTime->tm_sec,proc_s,sched_pr,runqlen);
}else{ // 第一次的数据无法做差,所以不予输出
env.enable_proc = true;
}


/*
//只打印cswch/s
if(env.enable_sched_prwitch){
u64 sched_pr;//要输出的进程切换次数
time_t now = time(NULL);// 获取当前时间
struct tm *localTime = localtime(&now);// 将时间转换为本地时间结构
sched_pr= sched_total - sched;//计算差值;
sched = sched_total;
printf("%02d:%02d:%02d %6lld\n",
localTime->tm_hour, localTime->tm_min, localTime->tm_sec, sched_pr);
}else{ // 第一次的数据无法做差,所以不予输出
sched = sched_total;//全局变量proc
env.enable_sched_prwitch = true;
}
*/

//只打印proc
/*
if(env.enable_proc){
u64 proc_s;
time_t now = time(NULL);
struct tm *localTime = localtime(&now);
time_t now = time(NULL);// 获取当前时间
struct tm *localTime = localtime(&now);// 将时间转换为本地时间结构
line++;
proc_s = total_forks-proc;
Expand All @@ -107,10 +178,38 @@ static int print_countMap(struct bpf_map *map)
printf("%02d:%02d:%02d %6lld\n",
localTime->tm_hour, localTime->tm_min, localTime->tm_sec, proc_s);
}else{ // 第一次的数据无法做差,所以不予输出
proc = total_forks;
proc = total_forks;//全局变量proc
env.enable_proc = true;
}
*/

//同时打印proc、cswch/s 失败
/*if(env.enable_sched_prwitch||env.enable_proc){
u64 proc_pr;//要输出的新创建的进程数
u64 sched_pr;//要输出的进程切换次数
time_t now = time(NULL);// 获取当前时间
struct tm *localTime = localtime(&now);// 将时间转换为本地时间结构
line++;
proc_pr = proc_total-proc;
sum[0] += proc_pr;
proc_pr = sum[0]/line;
proc = proc_total;
sched_pr= sched_total - sched;//计算差值;
sched = sched_total;
printf("%02d:%02d:%02d %6lld %6lld\n",
localTime->tm_hour, localTime->tm_min, localTime->tm_sec, proc_pr,sched_pr);
}else{ // 第一次的数据无法做差,所以不予输出
proc = proc_total;//全局变量proc
env.enable_proc = true;
sched = sched_total;//全局变量proc
env.enable_sched_prwitch = true;
}
*/
return 0;
}

Expand Down Expand Up @@ -192,8 +291,9 @@ int main(int argc, char **argv)
}

printf("Tracing for Data's... Ctrl-C to end\n");
printf(" time proc/s cswch/s runqlen irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms BpfCnt\n");

//printf(" time proc/s cswch/s runqlen irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms BpfCnt\n");
printf(" time proc/s cswch/s runqlen\n");
/* 处理事件 */
while (!exiting) {
sleep(1);
Expand Down
Loading

0 comments on commit a0fd77e

Please sign in to comment.