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

cs_delay&libbpf_sar合进cpuwatcher,sar新增Idle和Thread功能,可通过传参分别实现不同功能。 #606

Merged
merged 28 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a0fd77e
add cswch & runqlen
albertxu216 Nov 3, 2023
8a74846
del vmlinux.h
albertxu216 Nov 3, 2023
b905991
Update libbpf_sar.bpf.c
albertxu216 Nov 3, 2023
a1d4870
Merge branch 'linuxkerneltravel:develop' into develop
albertxu216 Nov 9, 2023
81cc698
libbpf_cs_delay可视化
albertxu216 Nov 9, 2023
17f39e1
修改Makefile
albertxu216 Nov 10, 2023
b154823
修改cs_delay.c
albertxu216 Nov 10, 2023
1fc7faa
Merge branch 'linuxkerneltravel:develop' into develop
albertxu216 Nov 10, 2023
42fd323
Update libbpf.yml
albertxu216 Nov 10, 2023
09740de
Merge branch 'linuxkerneltravel:develop' into develop
albertxu216 Nov 17, 2023
6365ace
add irqtime
albertxu216 Nov 17, 2023
a1fc33b
Merge branch 'linuxkerneltravel:develop' into develop
albertxu216 Nov 21, 2023
c35ba62
Create cpu_watcher
albertxu216 Nov 21, 2023
b292b35
Update libbpf_sar.bpf.c
albertxu216 Nov 21, 2023
445f661
Update libbpf.yml
albertxu216 Nov 21, 2023
446d3b9
Update system_cpu.yml
albertxu216 Nov 21, 2023
4b97afa
Merge branch 'linuxkerneltravel:develop' into develop
albertxu216 Nov 27, 2023
161a314
调整cpu_watcher文件夹
albertxu216 Nov 30, 2023
9472da9
Cs_dely & Libbpf_sar功能合进Cpuwatcher , Add Idle & Thread
albertxu216 Nov 30, 2023
b5d5124
Update system_cpu.yml
albertxu216 Nov 30, 2023
9610268
Update cpu_watcher.bpf.c
albertxu216 Nov 30, 2023
f7d6951
Update system_cpu.yml
albertxu216 Nov 30, 2023
76d337d
Update and rename libbpf.yml to cpu_watcher.yml
albertxu216 Nov 30, 2023
a728a9f
Update system_cpu.yml
albertxu216 Nov 30, 2023
1835ee4
Update cpu_watcher.yml
albertxu216 Nov 30, 2023
c142822
Update system_cpu.yml
albertxu216 Nov 30, 2023
2dcf383
Update system_cpu.yml
albertxu216 Nov 30, 2023
a6fbdc9
Update system_cpu.yml
albertxu216 Nov 30, 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
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name: libbpf
name: cpu_watcher

on:
push:
branches:
- "*"
paths:
- 'eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay/libbpf_cs_delay/**'
- '.github/workflows/libbpf.yml'
- 'eBPF_Supermarket/CPU_Subsystem/cpu_watcher/**'
- '.github/workflows/cpu_watcher.yml'
pull_request:
branches:
- "*"
paths:
- 'eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay/libbpf_cs_delay/**'
- '.github/workflows/libbpf.yml'
- 'eBPF_Supermarket/CPU_Subsystem/cpu_watcher/**'
- '.github/workflows/cpu_watcher.yml'

jobs:
libbpf-project-build-and-test:
Expand All @@ -26,8 +26,8 @@ jobs:
sudo apt install libbpf-dev clang llvm libelf-dev libpcap-dev gcc-multilib build-essential
git submodule update --init --recursive

- name: Run cs_delay
- name: Run cpu_watcher
run: |
cd eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay/libbpf_cs_delay
make cs_delay
sudo ./cs_delay
cd eBPF_Supermarket/CPU_Subsystem/cpu_watcher/
make cpu_watcher
sudo ./cpu_watcher
10 changes: 5 additions & 5 deletions .github/workflows/system_cpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
uname -r
./run.sh

libbpf_sar-project-build-and-test:
cpu_watcher-project-build-and-test:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
Expand All @@ -115,8 +115,8 @@ jobs:
sudo apt install libbpf-dev clang llvm libelf-dev libpcap-dev gcc-multilib build-essential
git submodule update --init --recursive

- name: Run libbpf_sar
- name: Run cpu_watcher
run: |
cd eBPF_Supermarket/CPU_Subsystem/cpu_watcher/libbpf_sar
make libbpf_sar
sudo ./libbpf_sar -t 1
cd eBPF_Supermarket/CPU_Subsystem/cpu_watcher
make cpu_watcher
sudo ./cpu_watcher
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
OUTPUT := .output
CLANG ?= clang
LIBBPF_SRC := $(abspath ../../../libbpf/src)
BPFTOOL_SRC := $(abspath ../../../bpftool/src)
LIBBPF_SRC := $(abspath ../libbpf/src)
BPFTOOL_SRC := $(abspath ../bpftool/src)
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool)
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
LIBBLAZESYM_SRC := $(abspath ../../../blazesym/)
LIBBLAZESYM_SRC := $(abspath ../blazesym/)
LIBBLAZESYM_INC := $(abspath $(LIBBLAZESYM_SRC)/include)
LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a)
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
Expand All @@ -34,15 +34,15 @@ ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
| sed 's/mips.*/mips/' \
| sed 's/riscv64/riscv/' \
| sed 's/loongarch64/loongarch/')
VMLINUX := ../../../vmlinux/$(ARCH)/vmlinux.h
VMLINUX := ../vmlinux/$(ARCH)/vmlinux.h
# Use our own libbpf API headers and Linux UAPI headers distributed with
# libbpf to avoid dependency on system-wide headers, which could be missing or
# outdated
INCLUDES := -I$(OUTPUT) -I../../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC)
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)

APPS = cs_delay
APPS = cpu_watcher

CARGO ?= $(shell which cargo)
ifeq ($(strip $(CARGO)),)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,29 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#include "libbpf_sar.h"
#include "cpu_watcher.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

const volatile long long unsigned int forks_addr = 0;

// 计数表格,第0项为所统计fork数,第1项为进程切换数,第2项为运行队列长度
#define PF_IDLE 0x00000002 /* I am an IDLE thread */
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */

/*----------------------------------------------*/
/* cs_delay相关maps */
/*----------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__type(value, u64);
} start SEC(".maps");//记录时间戳;

/*----------------------------------------------*/
/* sar相关maps */
/*----------------------------------------------*/
// 计数表格,第0项为所统计fork数,第1项为进程切换数,
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);//基于数组的映射
__uint(max_entries, 3);//countMap 可以存储最多 3 对键值对
Expand All @@ -37,28 +53,17 @@ struct {
// 记录开始的时间
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__uint(max_entries, 4096);
__type(key, pid_t);
__type(value, u64);
} start SEC(".maps");//记录时间戳;
} procStartTime 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 {
Expand All @@ -70,17 +75,12 @@ __type(value, struct rq);


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

struct __softirq_info {
u64 pad;
u32 vec;
};

struct {
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
__uint(max_entries, 4096);
Expand Down Expand Up @@ -111,33 +111,94 @@ __type(key, u32);
__type(value, u64);
} irq_Last_time SEC(".maps");

struct __irq_info {
u64 pad;
u32 irq;
};
// 储存cpu进入空闲的起始时间
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 128);
__type(key, u32);
__type(value, u64);
} idleStart SEC(".maps");

// 储存cpu进入空闲的持续时间
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, u64);
} idleLastTime SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, u64);
} kt_LastTime SEC(".maps");

/*----------------------------------------------*/
/* cs_delay跟踪函数 */
/*----------------------------------------------*/

SEC("kprobe/schedule")
int BPF_KPROBE(schedule)
{
u64 t1;
t1 = bpf_ktime_get_ns()/1000; //bpf_ktime_get_ns返回自系统启动以来所经过的时间(以纳秒为单位)。不包括系统挂起的时间。
int key =0;
bpf_map_update_elem(&start,&key,&t1,BPF_ANY);
return 0;
}

SEC("kretprobe/schedule")
int BPF_KRETPROBE(schedule_exit)
{
u64 t2 = bpf_ktime_get_ns()/1000;
u64 t1,delay;
int key = 0;
u64 *val = bpf_map_lookup_elem(&start,&key);
if (val != 0)
{
t1 = *val;
delay = t2 - t1;
bpf_map_delete_elem(&start, &key);
}else{
return 0;
}

struct event *e;
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (!e) return 0;

e->t1=t1;//开始时间
e->t2=t2;//结束时间
e->delay=delay;//时间间隔

/* 成功地将其提交到用户空间进行后期处理 */
bpf_ringbuf_submit(e, 0);

return 0;
}

/*----------------------------------------------*/
/* sar跟踪函数 */
/*----------------------------------------------*/
// 统计fork数
SEC("kprobe/finish_task_switch.isra.0")
int kprobe__finish_task_switch(struct pt_regs *ctx)
{
u32 key = 0;
u64 val, *valp = NULL;
unsigned long total_forks;

if(forks_addr !=0){
valp = (u64 *)forks_addr;
bpf_probe_read_kernel(&total_forks, sizeof(unsigned long), valp);
key = 1;
val = total_forks;
bpf_map_update_elem(&countMap,&key,&val,BPF_ANY);
}

return 0;
}



//获取进程切换数;
SEC("tracepoint/sched/sched_switch")//静态挂载点
int trace_sched_switch2(struct cswch_args *info) {
Expand All @@ -146,7 +207,7 @@ int trace_sched_switch2(struct cswch_args *info) {

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

Expand All @@ -155,7 +216,7 @@ int trace_sched_switch2(struct cswch_args *info) {
u64 time = bpf_ktime_get_ns()/1000;//获取当前时间,ms;

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

// Step2: Syscall时间处理
Expand All @@ -178,6 +239,25 @@ int trace_sched_switch2(struct cswch_args *info) {
return 0;
}

SEC("kprobe/finish_task_switch.isra.0")
int BPF_KPROBE(finish_task_switch,struct task_struct *prev){
pid_t pid=BPF_CORE_READ(prev,pid);
u64 *val, time = bpf_ktime_get_ns();
u64 delta;
// Step1: 记录内核进程(非IDLE)运行时间
if ((BPF_CORE_READ(prev,flags) & PF_KTHREAD) && pid!= 0) {
val = bpf_map_lookup_elem(&procStartTime, &pid);
if (val) {
u32 key = 0;
delta = time - *val*1000;
val = bpf_map_lookup_elem(&kt_LastTime, &key);
if (val) *val += delta;
else bpf_map_update_elem(&kt_LastTime, &key, &delta, BPF_ANY);
}
}
return 0;
}

/*
SEC("kprobe/finish_task_switch")//动态挂载点
int trace_sched_switch(struct cswch_args *info) {
Expand All @@ -195,7 +275,7 @@ int trace_sched_switch(struct cswch_args *info) {
u64 time = bpf_ktime_get_ns()/1000;//获取当前时间,ms;

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

// Step2: Syscall时间处理
Expand Down Expand Up @@ -223,7 +303,7 @@ int trace_sched_switch(struct cswch_args *info) {
//统计运行队列长度
SEC("kprobe/update_rq_clock")
int kprobe_update_rq_clock(struct pt_regs *ctx){
u32 key = 2;
u32 key = 0;
u32 rqkey = 0;
struct rq *p_rq = 0;
p_rq = (struct rq *)bpf_map_lookup_elem(&rq_map, &rqkey);
Expand All @@ -234,7 +314,7 @@ int kprobe_update_rq_clock(struct pt_regs *ctx){
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);
bpf_map_update_elem(&runqlen,&key,&val,BPF_ANY);
return 0;
}

Expand Down Expand Up @@ -313,3 +393,30 @@ int trace_irq_handler_exit(struct __irq_info *info) {
}


//tracepoint:power_cpu_idle 表征了CPU进入IDLE的状态,比较准确
SEC("tracepoint/power/cpu_idle")
int trace_cpu_idle(struct idleStruct *pIDLE) {
u64 delta, time = bpf_ktime_get_ns();
u32 key = pIDLE->cpu_id;
// 按cpuid记录空闲的开始,这十分重要,因为IDLE-0进程可同时运行在两个核上

if (pIDLE->state == -1) {
// 结束idle
u64 *valp = bpf_map_lookup_elem(&idleStart,&key);
if (valp && *valp != 0) {
/*找到初始idle时间*/
delta = time - *valp;//持续空闲时间=当前时间-进入空闲时间;
key = 0;
valp = bpf_map_lookup_elem(&idleLastTime,&key);
if (valp) *valp += delta;//找到持续空闲时间,持续空闲时间更新;
else bpf_map_update_elem(&idleLastTime,&key,&delta,BPF_ANY);//初次记录持续空闲时间;
}
} else {
// 开始idle
u64 val = time;
bpf_map_update_elem(&idleStart,&key,&time,BPF_ANY);
}
return 0;
}


Loading