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

增加developing文件夹,用于暂时存放工具新框架文件,代完全完成后再替代原有代码 #601

Merged
merged 7 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@
url = https://github.com/libbpf/libbpf-bootstrap.git
[submodule "eBPF_Supermarket/Stack_Analyser/speedscope"]
path = eBPF_Supermarket/Stack_Analyser/speedscope
url = https://github.com/jlfwong/speedscope
url = https://github.com/jlfwong/speedscope
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
// Copyright 2023 The LMP Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: [email protected]
//
// user-mode code for the process image

#include <argp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include "include/proc_image.h"
#include "resource_image.skel.h"

#define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \
do \
{ \
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, \
.retprobe = is_retprobe, \
.func_name = #sym_name); \
skel->links.prog_name = bpf_program__attach_uprobe_opts( \
skel->progs.prog_name, \
env.pid, \
object, \
0, \
&uprobe_opts); \
} while (false)

#define __CHECK_PROGRAM(skel, prog_name) \
do \
{ \
if (!skel->links.prog_name) \
{ \
fprintf(stderr, "[%s] no program attached for" #prog_name "\n", strerror(errno)); \
return -errno; \
} \
} while (false)

#define __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, is_retprobe) \
do \
{ \
__ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe); \
__CHECK_PROGRAM(skel, prog_name); \
} while (false)

#define ATTACH_UPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, false)
#define ATTACH_URETPROBE(skel, sym_name, prog_name) __ATTACH_UPROBE(skel, sym_name, prog_name, true)

#define ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, false)
#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, true)

#define CHECK_ERR(cond, info) \
if (cond) \
{ \
fprintf(stderr, "[%s]" info "\n", strerror(errno)); \
return -1; \
}

#define warn(...) fprintf(stderr, __VA_ARGS__)

#define RESOURCE_IMAGE 1

static int prev_image = 0;
static volatile bool exiting = false;
static const char object[] = "/usr/lib/x86_64-linux-gnu/libc.so.6";
static struct env {
int pid;
int cpu_id;
int time;
bool enable_resource;
} env = {
.pid = -1,
.cpu_id = -1,
.time = 0,
.enable_resource = false,
};

const char argp_program_doc[] ="Trace process to get process image.\n";

static const struct argp_option opts[] = {
{ "pid", 'p', "PID", 0, "Process ID to trace" },
{ "cpuid", 'c', "CPUID", 0, "Set For Tracing per-CPU Process(other processes don't need to set this parameter)" },
{ "time", 't', "TIME-SEC", 0, "Max Running Time(0 for infinite)" },
{ "resource", 'r', NULL, 0, "Collects resource usage information about a process" },
{},
};

static error_t parse_arg(int key, char *arg, struct argp_state *state)
{
long pid;
long cpu_id;
switch (key) {
case 'p':
errno = 0;
pid = strtol(arg, NULL, 10);
if (errno || pid < 0) {
warn("Invalid PID: %s\n", arg);
// 调用argp_usage函数,用于打印用法信息并退出程序
argp_usage(state);
}
env.pid = pid;
break;
case 'c':
cpu_id = strtol(arg, NULL, 10);
if(cpu_id < 0){
warn("Invalid CPUID: %s\n", arg);
argp_usage(state);
}
env.cpu_id = cpu_id;
break;
case 't':
env.time = strtol(arg, NULL, 10);
if(env.time) alarm(env.time);
break;
case 'r':
env.enable_resource = true;
break;
default:
return ARGP_ERR_UNKNOWN;
}

return 0;
}

static void sig_handler(int signo)
{
exiting = 1;
}

static int print_resource(struct bpf_map *map)
{
struct proc_id lookup_key = {-1}, next_key;
int err, fd = bpf_map__fd(map);
struct total_rsc event;
float pcpu,pmem;
double read_rate,write_rate;
unsigned long memtotal = sysconf(_SC_PHYS_PAGES);
time_t now = time(NULL);
struct tm *localTime = localtime(&now);
int hour = localTime->tm_hour;
int min = localTime->tm_min;
int sec = localTime->tm_sec;

if(prev_image != RESOURCE_IMAGE){
printf("RESOURCE----------------------------------------------------\n");
printf("%-8s %-6s %-6s %-6s %-12s %-12s\n","TIME","PID","CPU(%)","MEM(%)","read(kb/s)","write(kb/s)\n");
}

while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
err = bpf_map_lookup_elem(fd, &next_key, &event);
if (err < 0) {
fprintf(stderr, "failed to lookup infos: %d\n", err);
return -1;
}

pcpu = (1.0*event.time)/1000000000;
pmem = (1.0*event.memused)/memtotal;
read_rate = (1.0*event.readchar)/1024/((1.0*event.time)/1000000000); // kb/s
write_rate = (1.0*event.writechar)/1024/((1.0*event.time)/1000000000); // kb/s

printf("%02d:%02d:%02d %-6d %-6.4f %-6.4f %-12.2lf %-12.2lf\n",
hour,min,sec,event.pid,pcpu,pmem,read_rate,write_rate);

lookup_key = next_key;
}

prev_image = RESOURCE_IMAGE;

lookup_key.pid = -1;
lookup_key.cpu_id = -1;
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
err = bpf_map_delete_elem(fd, &next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup infos: %d\n", err);
return -1;
}
lookup_key = next_key;
}

return 0;
}

static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt)
{
fprintf(stderr, "Lost %llu events on CPU #%d!\n", lost_cnt, cpu);
}

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}

int main(int argc, char **argv)
{
struct resource_image_bpf *resource_skel;
int err;
static const struct argp argp = {
.options = opts,
.parser = parse_arg,
.doc = argp_program_doc,
};

err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
if (err)
return err;

libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
/* 设置libbpf错误和调试信息回调 */
libbpf_set_print(libbpf_print_fn);

/* 更干净地处理Ctrl-C
SIGINT:由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGTERM:请求中止进程,kill命令发送
*/
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGALRM,sig_handler);

if(env.enable_resource){
resource_skel = resource_image_bpf__open();
if(!resource_skel) {
fprintf(stderr, "Failed to open BPF resource skeleton\n");
return 1;
}

resource_skel->rodata->target_pid = env.pid;
resource_skel->rodata->target_cpu_id = env.cpu_id;

err = resource_image_bpf__load(resource_skel);
if (err) {
fprintf(stderr, "Failed to load and verify BPF resource skeleton\n");
goto cleanup;
}

err = resource_bpf__attach(resource_skel);
if (err) {
fprintf(stderr, "Failed to attach BPF resource skeleton\n");
goto cleanup;
}
}

/* 处理事件 */
/* 后期修改方案二:可以用锁进行实现;
后期修改方案一:每秒输出的事件改用定时器实现,先将数据写到用户空间缓冲区(字符串数组)中,
然后循环访问缓冲区中是否有数据,避免事件的数据交叉输出;*/
while (!exiting) {
sleep(1);

if(env.enable_resource){
err = print_resource(resource_skel->maps.total);
/* Ctrl-C will cause -EINTR */
if (err == -EINTR) {
err = 0;
break;
}
if (err < 0) {
break;
}
}
}

/* 卸载BPF程序 */
cleanup:
resource_image_bpf__destroy(resource_skel);

return err < 0 ? -err : 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2023 The LMP Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: [email protected]
//
// eBPF map for the process image

#ifndef __PROC_IMAGE_H
#define __PROC_IMAGE_H

// resource_image
struct proc_id{
long unsigned int pid;
long unsigned int cpu_id;
};

struct start_rsc{
long long unsigned int time;
long long unsigned int readchar;
long long unsigned int writechar;
};

struct total_rsc{
long unsigned int pid;
long long unsigned int time;
long unsigned int memused;
long long unsigned int readchar;
long long unsigned int writechar;
};

#endif /* __PROCESS_H */
Loading