code clean

This commit is contained in:
zy
2023-12-12 02:59:48 -05:00
parent 462bdebad6
commit 96462422ce
9 changed files with 307 additions and 347 deletions

View File

@@ -76,13 +76,13 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num,
printk(KERN_INFO "variable_monitor IOCTL_DUMP_LOG\n");
ret = copy_from_user(&dump_param, (ioctl_dump_param *)ioctl_param,
sizeof(ioctl_dump_param));
printk(KERN_INFO "dump_param: %p %d %p\n", dump_param.user_ptr_len,
printk(KERN_INFO "dump_param: %p %lx %p\n", dump_param.user_ptr_len,
dump_param.user_buf_len, dump_param.user_buf);
if (!ret) {
ret = copy_to_user_variant_buffer(
&load_monitor_variant_buffer, dump_param.user_ptr_len,
dump_param.user_buf, dump_param.user_buf_len);
printk(KERN_INFO "ret %d, %d\n", ret, dump_param.user_buf_len);
printk(KERN_INFO "ret %d, %lx\n", ret, dump_param.user_buf_len);
}
// printk(KERN_INFO "copy_to_user_variant_buffer \n");
break;

View File

@@ -19,7 +19,7 @@ extern int dump_reset_sec;
extern mm_tree mm_tree_struct;
extern struct diag_variant_buffer load_monitor_variant_buffer; // global buffer
#define LOAD_MONITOR_BUFFER_SIZE 256 * 1024 * 1024 // 10MB
#define VARIABLE_MONITOR_BUFFER_SIZE 256 * 1024 * 1024 // 256MB
int monitor_init(void); // monitor init
void monitor_exit(void); // monitor exit

View File

@@ -270,7 +270,7 @@ int monitor_init(void) {
ret = init_orig_fun(); // init orig_X
if (ret)
return ret;
ret = init_buffer(LOAD_MONITOR_BUFFER_SIZE); // 256M
ret = init_buffer(VARIABLE_MONITOR_BUFFER_SIZE); // 256M
if (ret)
return -1;
return 0;

View File

@@ -66,5 +66,6 @@ void start_all_hrTimer(void);
void cancel_all_hrTimer(void);
// for work
void init_work_all_hrTimer(void);
void cancel_all_work(void);
void cancel_destory_all_work(void);

198
source/ucli/helpfun.cc Normal file
View File

@@ -0,0 +1,198 @@
#include "helpfun.h"
unsigned long run_in_host = 0;
enum { RUN_IN_HOST = 0, RUN_IN_CONTAINER };
int is_pid_1_has_environ(const char *field) {
bool done = false;
FILE *f = NULL;
int r = 0;
size_t l;
assert(field);
f = fopen("/proc/1/environ", "re");
if (!f)
return 0;
(void)__fsetlocking(f, FSETLOCKING_BYCALLER);
l = strlen(field);
do {
char line[BUF_LEN];
size_t i;
for (i = 0; i < sizeof(line) - 1; i++) {
int c;
c = getc(f);
if ((c == EOF)) {
done = true;
break;
} else if (c == 0)
break;
line[i] = c;
}
line[i] = 0;
if (strneq(line, field, l) && line[l] == '=') {
r = 1;
goto out;
}
} while (!done);
out:
fclose(f);
return r;
}
int get_proc_field(const char *filename, const char *pattern,
const char *terminator, char **field) {
char status[BUF_LEN] = {0};
char *t, *f;
size_t len;
int r;
assert(terminator);
assert(filename);
assert(pattern);
assert(field);
int fd = open(filename, O_RDONLY);
if (fd < 0)
return -errno;
r = read(fd, &status, BUF_LEN - 1);
if (r < 0)
return r;
t = status;
do {
bool pattern_ok;
do {
t = strstr(t, pattern);
if (!t)
return -ENOENT;
/* Check that pattern occurs in beginning of line. */
pattern_ok = (t == status || t[-1] == '\n');
t += strlen(pattern);
} while (!pattern_ok);
t += strspn(t, " \t");
if (!*t)
return -ENOENT;
} while (*t != ':');
t++;
if (*t) {
t += strspn(t, " \t");
/* Also skip zeros, because when this is used for
* capabilities, we don't want the zeros. This way the
* same capability set always maps to the same string,
* irrespective of the total capability set size. For
* other numbers it shouldn't matter. */
t += strspn(t, "0");
/* Back off one char if there's nothing but whitespace
and zeros */
if (!*t || isspace(*t))
t--;
}
len = strcspn(t, terminator);
f = strndup(t, len);
if (!f)
return -ENOMEM;
*field = f;
return 0;
}
static int detect_container_by_pid_2(void) {
char *s = NULL;
int r;
r = get_proc_field("/proc/2/status", "PPid", WHITESPACE, &s);
if (r >= 0) {
if (streq(s, "0"))
r = RUN_IN_HOST;
else
r = RUN_IN_CONTAINER;
} else if (r == -ENOENT)
r = RUN_IN_CONTAINER;
else {
printf("Failed to read /proc/2/status: %d\n", r);
r = RUN_IN_HOST;
}
free(s);
return r;
}
int check_in_host(void) {
int r;
if (is_pid_1_has_environ("container"))
r = RUN_IN_CONTAINER;
else
r = detect_container_by_pid_2();
return r == RUN_IN_HOST;
}
static const char *user_mode_str(int user_mode) {
switch (user_mode) {
case 1:
return "USER MODE";
case 0:
return "SYSTEM MODE";
default:
return "UNKNOWN MODE";
}
}
std::string state_str(int __state) {
std::vector<std::string> states;
if (__state == TASK_RUNNING)
states.push_back("TASK_RUNNING");
// if (__state & TASK_RUNNING) states.push_back("TASK_RUNNING");
if (__state & TASK_INTERRUPTIBLE)
states.push_back("TASK_INTERRUPTIBLE");
if (__state & TASK_UNINTERRUPTIBLE)
states.push_back("TASK_UNINTERRUPTIBLE");
if (__state & __TASK_STOPPED)
states.push_back("__TASK_STOPPED");
if (__state & __TASK_TRACED)
states.push_back("__TASK_TRACED");
if (__state & TASK_PARKED)
states.push_back("TASK_PARKED");
if (__state & TASK_DEAD)
states.push_back("TASK_DEAD");
if (__state == TASK_KILLABLE)
states.push_back("TASK_KILLABLE");
if (__state == TASK_STOPPED)
states.push_back("TASK_STOPPED");
if (__state == TASK_IDLE)
states.push_back("TASK_IDLE");
std::string result;
for (const auto &state : states) {
if (!result.empty())
result += " | ";
result += state;
}
return result;
}

37
source/ucli/helpfun.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef __HELP_FUN_H__
#define __HELP_FUN_H__
#include <assert.h>
#include <ctype.h> // for isspace
#include <errno.h>
#include <fcntl.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unistd.h> // for read
#include <vector>
#define BUF_LEN 4096
#define WHITESPACE " \t\n\r"
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
#define streq(a, b) (strcmp((a), (b)) == 0)
#define TASK_RUNNING 0x0000
#define TASK_INTERRUPTIBLE 0x0001
#define TASK_UNINTERRUPTIBLE 0x0002
#define __TASK_STOPPED 0x0004
#define __TASK_TRACED 0x0008
#define TASK_PARKED 0x0040
#define TASK_DEAD 0x0080
#define TASK_WAKEKILL 0x0100
#define TASK_NOLOAD 0x0200
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
extern unsigned long run_in_host; // 0: container, 1: host
int check_in_host(void); // for run_in_host
std::string state_str(int __state); // task state to string
#endif

View File

@@ -20,8 +20,6 @@
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
#define streq(a, b) (strcmp((a), (b)) == 0)
unsigned long run_in_host = 0;
using namespace std;
class pid_cmdline {
@@ -61,8 +59,22 @@ std::string &pid_cmdline::get_pid_cmdline(int pid) {
return cmdlines[pid];
}
// 根据 sys_task 取值返回对应的字符串
static const char *sys_task_str(int sys_task) {
switch (sys_task) {
case 0:
return "USER_TASK";
case 1:
return "SYSTEM_TASK";
case 2:
return "IDLE_TASK";
default:
return "UNKNOWN_TASK";
}
}
/**
* @brief 调用ioctl
* @brief call ioctl
*/
long diag_call_ioctl(unsigned long request, unsigned long arg) {
long ret = 0;
@@ -91,6 +103,13 @@ err:
return ret;
}
/**
* @brief unwind frame callback
*
* @param entry
* @param arg
* @return int
*/
static int unwind_frame_callback(struct unwind_entry *entry, void *arg) {
symbol sym;
std::string symbol; // Use std::string instead of string
@@ -120,6 +139,14 @@ static int unwind_frame_callback(struct unwind_entry *entry, void *arg) {
return 0;
}
/**
* @brief extract buffer with func
*
* @param buf
* @param len
* @param func
* @param arg
*/
void extract_variant_buffer(char *buf, unsigned int len,
int (*func)(void *, unsigned int, void *),
void *arg) {
@@ -153,6 +180,14 @@ void extract_variant_buffer(char *buf, unsigned int len,
}
}
/**
* @brief printf user stack
*
* @param pid
* @param ns_pid
* @param comm
* @param raw_stack
*/
void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
raw_stack_detail *raw_stack) {
struct perf_sample stack_sample;
@@ -173,97 +208,11 @@ void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
fflush(stdout);
}
// 根据 sys_task 取值返回对应的字符串
static const char *sys_task_str(int sys_task) {
switch (sys_task) {
case 0:
return "USER_TASK";
case 1:
return "SYSTEM_TASK";
case 2:
return "IDLE_TASK";
default:
return "UNKNOWN_TASK";
}
}
static const char *user_mode_str(int user_mode) {
switch (user_mode) {
case 1:
return "USER MODE";
case 0:
return "SYSTEM MODE";
default:
return "UNKNOWN MODE";
}
}
// 判断 __state 具体是下面哪种状态.输出: 单个状态 | 组合状态
// #define TASK_RUNNING 0x0000 // 正在运行
// #define TASK_INTERRUPTIBLE 0x0001 // 等待事件阻塞 可信号唤醒
// #define TASK_UNINTERRUPTIBLE 0x0002 // 等待事件阻塞 不可信号唤醒
// #define __TASK_STOPPED 0x0004 // 暂停执行
// #define __TASK_TRACED 0x0008 //调试状态
// #define TASK_PARKED 0x0040 // parked 状态,暂停执行 保留在 cpu
// 但不被调度 #define TASK_DEAD 0x0080 // dead #define
// TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
// #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
// #define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
// static const char *state_str(int __state){
// }
#include <string>
#include <vector>
#define TASK_RUNNING 0x0000
#define TASK_INTERRUPTIBLE 0x0001
#define TASK_UNINTERRUPTIBLE 0x0002
#define __TASK_STOPPED 0x0004
#define __TASK_TRACED 0x0008
#define TASK_PARKED 0x0040
#define TASK_DEAD 0x0080
#define TASK_WAKEKILL 0x0100
#define TASK_NOLOAD 0x0200
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
std::string state_str(int __state) {
std::vector<std::string> states;
if (__state == TASK_RUNNING)
states.push_back("TASK_RUNNING");
// if (__state & TASK_RUNNING) states.push_back("TASK_RUNNING");
if (__state & TASK_INTERRUPTIBLE)
states.push_back("TASK_INTERRUPTIBLE");
if (__state & TASK_UNINTERRUPTIBLE)
states.push_back("TASK_UNINTERRUPTIBLE");
if (__state & __TASK_STOPPED)
states.push_back("__TASK_STOPPED");
if (__state & __TASK_TRACED)
states.push_back("__TASK_TRACED");
if (__state & TASK_PARKED)
states.push_back("TASK_PARKED");
if (__state & TASK_DEAD)
states.push_back("TASK_DEAD");
if (__state == TASK_KILLABLE)
states.push_back("TASK_KILLABLE");
if (__state == TASK_STOPPED)
states.push_back("TASK_STOPPED");
if (__state == TASK_IDLE)
states.push_back("TASK_IDLE");
std::string result;
for (const auto &state : states) {
if (!result.empty())
result += " | ";
result += state;
}
return result;
}
/**
* @brief printf task brief
*
* @param detail
*/
void printk_task_brief(task_detail *detail) {
printf(" TASK INFO: %s [%s / %s], PID: %d / %d\n",
sys_task_str(detail->sys_task), detail->cgroup_buf, detail->comm,
@@ -273,6 +222,11 @@ void printk_task_brief(task_detail *detail) {
// detail->state);
}
/**
* @brief print kernel stack
*
* @param kern_stack
*/
void diag_printf_kern_stack(kern_stack_detail *kern_stack) {
int i;
symbol sym;
@@ -292,6 +246,11 @@ void diag_printf_kern_stack(kern_stack_detail *kern_stack) {
}
}
/**
* @brief print proc chains
*
* @param proc_chains
*/
void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
int detail = 1;
int i;
@@ -312,154 +271,4 @@ void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
proc_chains->chains[i]);
}
}
}
int is_pid_1_has_environ(const char *field) {
bool done = false;
FILE *f = NULL;
int r = 0;
size_t l;
assert(field);
f = fopen("/proc/1/environ", "re");
if (!f)
return 0;
(void)__fsetlocking(f, FSETLOCKING_BYCALLER);
l = strlen(field);
do {
char line[BUF_LEN];
size_t i;
for (i = 0; i < sizeof(line) - 1; i++) {
int c;
c = getc(f);
if ((c == EOF)) {
done = true;
break;
} else if (c == 0)
break;
line[i] = c;
}
line[i] = 0;
if (strneq(line, field, l) && line[l] == '=') {
r = 1;
goto out;
}
} while (!done);
out:
fclose(f);
return r;
}
enum { RUN_IN_HOST = 0, RUN_IN_CONTAINER };
int get_proc_field(const char *filename, const char *pattern,
const char *terminator, char **field) {
char status[BUF_LEN] = {0};
char *t, *f;
size_t len;
int r;
assert(terminator);
assert(filename);
assert(pattern);
assert(field);
int fd = open(filename, O_RDONLY);
if (fd < 0)
return -errno;
r = read(fd, &status, BUF_LEN - 1);
if (r < 0)
return r;
t = status;
do {
bool pattern_ok;
do {
t = strstr(t, pattern);
if (!t)
return -ENOENT;
/* Check that pattern occurs in beginning of line. */
pattern_ok = (t == status || t[-1] == '\n');
t += strlen(pattern);
} while (!pattern_ok);
t += strspn(t, " \t");
if (!*t)
return -ENOENT;
} while (*t != ':');
t++;
if (*t) {
t += strspn(t, " \t");
/* Also skip zeros, because when this is used for
* capabilities, we don't want the zeros. This way the
* same capability set always maps to the same string,
* irrespective of the total capability set size. For
* other numbers it shouldn't matter. */
t += strspn(t, "0");
/* Back off one char if there's nothing but whitespace
and zeros */
if (!*t || isspace(*t))
t--;
}
len = strcspn(t, terminator);
f = strndup(t, len);
if (!f)
return -ENOMEM;
*field = f;
return 0;
}
static int detect_container_by_pid_2(void) {
char *s = NULL;
int r;
r = get_proc_field("/proc/2/status", "PPid", WHITESPACE, &s);
if (r >= 0) {
if (streq(s, "0"))
r = RUN_IN_HOST;
else
r = RUN_IN_CONTAINER;
} else if (r == -ENOENT)
r = RUN_IN_CONTAINER;
else {
printf("Failed to read /proc/2/status: %d\n", r);
r = RUN_IN_HOST;
}
free(s);
return r;
}
int check_in_host(void) {
int r;
if (is_pid_1_has_environ("container"))
r = RUN_IN_CONTAINER;
else
r = detect_container_by_pid_2();
return r == RUN_IN_HOST;
}
}

View File

@@ -2,6 +2,7 @@
* various_monitor cli 命令行工具
*/
#include "ucli.h"
#include "helpfun.h"
#include <cstdio>
#include <getopt.h>
#include <string.h>
@@ -9,84 +10,6 @@
#include <sys/ioctl.h> // for ioctl
#include <unistd.h>
// #include <fcntl.h>
// #include <sched.h>
// // #include <unistd.h>
// #include <stdio.h>
// #include <stdlib.h>
// ioctl
// !todo move to a header file
#define IOCTL_MAGIC_NUMBER 'k'
#define IOCTL_PID _IOWR(IOCTL_MAGIC_NUMBER, 2, int)
#define IOCTL_TGID _IOWR(IOCTL_MAGIC_NUMBER, 3, int)
// int switch_namespace(pid_t pid, const char *ns) {
// char ns_path[256];
// snprintf(ns_path, sizeof(ns_path), "/proc/%d/ns/%s", pid, ns);
// int fd = open(ns_path, O_RDONLY);
// if (fd == -1) {
// perror("open");
// return -1;
// }
// if (setns(fd, 0) == -1) {
// perror("setns");
// close(fd);
// return -1;
// }
// close(fd);
// return 0;
// }
// int switch_to_pid_namespace(pid_t pid) {
// return switch_namespace(pid, "pid");
// }
// int switch_to_user_namespace(pid_t pid) {
// return switch_namespace(pid, "user");
// }
// void test(variable_monitor_task *tsk_info) {
// // host
// if (tsk_info->task.pid == tsk_info->task.container_pid){
// printf("host\n");
// diag_printf_raw_stack(tsk_info->task.tgid, tsk_info->task.container_tgid,
// tsk_info->task.comm, &tsk_info->raw_stack);
// }
// printf("container\n");
// // Save the current namespace.
// int fd = open("/proc/self/ns/pid", O_RDONLY);
// if (fd == -1) {
// perror("open");
// return;
// }
// // Switch to the namespace of the target process.
// if (switch_to_pid_namespace(tsk_info->task.pid) != 0) {
// close(fd);
// return;
// }
// if (switch_to_user_namespace(tsk_info->task.pid) != 0) {
// close(fd);
// return;
// }
// // Do something with tgid...
// diag_printf_raw_stack(tsk_info->task.container_tgid,
// tsk_info->task.container_tgid, tsk_info->task.comm,
// &tsk_info->raw_stack);
// // Switch back to the original namespace.
// if (!run_in_host && setns(fd, 0) == -1) {
// perror("setns");
// }
// close(fd);
// }
static int task_info_extract(void *buf, unsigned int len, void *) {
int *et_type;
variable_monitor_record *vm_record;
@@ -128,18 +51,8 @@ static int task_info_extract(void *buf, unsigned int len, void *) {
state_str(tsk_info->task.state).c_str(), tsk_info->task.state);
printk_task_brief(&tsk_info->task);
// diag_printf_raw_stack(tsk_info->task.tgid, tsk_info->task.container_tgid,
// tsk_info->task.comm, &tsk_info->raw_stack);
// printf("run_in_host: %d\n", run_in_host);
// diag_printf_raw_stack(run_in_host ? tsk_info->task.tgid
// : tsk_info->task.container_tgid,
// tsk_info->task.container_tgid, tsk_info->task.comm,
// &tsk_info->raw_stack);
// test(tsk_info);
// diag_printf_kern_stack(&tsk_info->kern_stack);
// system task no need print raw_stack
// system task no need print user stack | just in case
if (tsk_info->task.sys_task == 1) {
diag_printf_kern_stack(&tsk_info->kern_stack);
} else {
@@ -170,7 +83,6 @@ static int task_info_extract(void *buf, unsigned int len, void *) {
diag_printf_kern_stack(&tsk_info_system->kern_stack);
printf("#* 0xffffffffffffff %s (UNKNOWN)\n",
tsk_info_system->task.comm);
// diag_printf_proc_chains(&tsk_info_system->proc_chains);
printf("##\n");
break;
@@ -187,8 +99,7 @@ static void do_extract(char *buf, int len) {
}
static void do_dump(const char *arg) {
//! todo
static char variant_buf[256 * 1024 * 1024];
static char variant_buf[VARIABLE_MONITOR_BUFFER_SIZE];
int len;
int ret = 0;
@@ -198,12 +109,11 @@ static void do_dump(const char *arg) {
struct diag_ioctl_dump_param dump_param = {
.user_ptr_len = &len,
.user_buf_len = 256 * 1024 * 1024,
.user_buf_len = VARIABLE_MONITOR_BUFFER_SIZE,
.user_buf = variant_buf,
};
ret = diag_call_ioctl(IOCTL_DUMP_LOG,
(long)&dump_param); // !todo arg -> #define
ret = diag_call_ioctl(IOCTL_DUMP_LOG, (long)&dump_param);
if (ret == 0) {
do_extract(variant_buf, len);
}
@@ -223,7 +133,7 @@ static void do_pid(char *arg) {
if (ret) {
printf("Get pid info err: %d\n", ret);
}
sleep(3);
sleep(3); // after 3sec
do_dump("");
}

View File

@@ -11,6 +11,9 @@
// ioctl
#define IOCTL_WATCH_VARIABLE 0
#define IOCTL_DUMP_LOG 1
#define IOCTL_MAGIC_NUMBER 'k'
#define IOCTL_PID _IOWR(IOCTL_MAGIC_NUMBER, 2, int)
#define IOCTL_TGID _IOWR(IOCTL_MAGIC_NUMBER, 3, int)
// dump type
#define VARIABLE_MONITOR_RECORD_TYPE 0x0
@@ -31,8 +34,12 @@
#define MAX_NAME_LEN (127) // max name length
#define TIMER_MAX_WATCH_NUM (32) // A timer max watch number at once time
#define VARIABLE_MONITOR_BUFFER_SIZE 256 * 1024 * 1024 // 256MB
#define DIAG_USER_STACK_SIZE (16 * 1024)
extern unsigned long run_in_host;
typedef struct {
pid_t task_id; // current process id
char name[MAX_NAME_LEN + 1]; // name
@@ -146,6 +153,4 @@ void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
void diag_printf_kern_stack(kern_stack_detail *kern_stack);
void diag_printf_proc_chains(proc_chains_detail *proc_chains);
std::string state_str(int __state);
#endif /* UAPI_H */