提交 058455aa 编写于 作者: N nocjj

display: add CPU usage item to display

Calculation formula of CPU usage:
cpu_time = (utime_now + stime_now) - (utime_pre + stime_pre);
CPU usage = cpu_time / time_interval;

Get utime and stime from /proc/qemupid/stat, then we can get cpu_time
by calculate variation of these value over time.
And time_interval represent cpu time interval between two data acquisition.
Signed-off-by: NJiajun Chen <1250062498@qq.com>
上级 e4c1027d
......@@ -48,11 +48,38 @@ static struct domain *add_domains(struct domain_list *list)
return &(list->domains[list->num - 1]);
}
static void copy_domains(struct domain_list *now, struct domain_list *pre)
{
if (pre->domains) {
free(pre->domains);
}
pre->num = now->num;
pre->domains = malloc(sizeof(struct domain) * pre->num);
if (pre->domains == NULL) {
pre->num = 0;
return;
}
memcpy(pre->domains, now->domains, sizeof(struct domain) * pre->num);
}
static void pop_domains(struct domain_list *list)
{
list->num--;
}
/*
* get domain from domain list
*/
static struct domain *get_domain_from_id(int id, struct domain_list *list)
{
for (int i = 0; i < list->num; i++) {
if (list->domains[i].domain_id == id) {
return &(list->domains[i]);
}
}
return NULL;
}
static int get_id_from_cgroup(pid_t pid)
{
char path[CGROUP_PATH_SIZE];
......@@ -92,7 +119,7 @@ static int set_domain(struct domain *dom, const char *name)
char path[PATH_MAX];
char pid[PID_STRING_MAX];
char *end = NULL;
if (len >= DOMAIN_NAME_MAX - 1) {
return -1;
}
......@@ -160,12 +187,23 @@ static int get_qemu_id(struct domain_list *list)
return list->num;
}
int refresh_domains(struct domain_list *list)
int refresh_domains(struct domain_list *now, struct domain_list *pre)
{
int num;
init_domains(list);
num = get_qemu_id(list);
copy_domains(now, pre); /* save last data int pre */
init_domains(now);
num = get_qemu_id(now);
for (int i = 0; i < now->num; i++) {
int id = now->domains[i].domain_id;
struct domain *old_domain = get_domain_from_id(id, pre);
if (old_domain == NULL) {
continue;
}
refresh_delta_stat(&(now->domains[i]), old_domain);
}
return num;
}
......@@ -21,5 +21,5 @@ struct domain_list {
int num;
};
int refresh_domains(struct domain_list *list);
int refresh_domains(struct domain_list *now, struct domain_list *pre);
#endif
......@@ -26,6 +26,7 @@ FID fields[] = {
{"VMname", FIELDS_DISPLAY, 14 },
{"DID", FIELDS_DISPLAY, 5 },
{"PID", FIELDS_DISPLAY, 8 },
{"%CPU", FIELDS_DISPLAY, 5 },
{"S", FIELDS_DISPLAY, 5 },
{"P", FIELDS_DISPLAY, 5 }
};
......@@ -20,6 +20,7 @@ enum fields_type {
FD_VMNAME,
FD_DID,
FD_PID,
FD_CPU,
FD_STATE,
FD_P,
FD_END
......
......@@ -19,7 +19,8 @@
#define STAT_PATH_SIZE 40
struct file_item proc_stab[] = {
#define GF(f) (DFUN_T)GET_NAME(f)
#define GDF(f) (void *)GET_NAME(f), (void *)DELTA_NAME(f)
#define GF(f) (void *)GET_NAME(f), NULL
{"%c", GF(state)},
{"%d", GF(ppid)},
{"%d", GF(pgrd)},
......@@ -31,8 +32,8 @@ struct file_item proc_stab[] = {
{"%lu", GF(cmin_flt)},
{"%lu", GF(maj_flt)},
{"%lu", GF(cmaj_flt)},
{"%llu", GF(utime)},
{"%llu", GF(stime)},
{"%llu", GDF(utime)},
{"%llu", GDF(stime)},
{"%llu", GF(cutime)},
{"%llu", GF(cstime)},
{"%ld", GF(priority)},
......@@ -48,18 +49,19 @@ struct file_item proc_stab[] = {
{"%lu", GF(start_stack)},
{"%lu", GF(kstk_esp)},
{"%lu", GF(kstk_eip)},
{"%*s", NULL}, /* discard signal */
{"%*s", NULL}, /* discard blocked */
{"%*s", NULL}, /* discard sigignore */
{"%*s", NULL}, /* discard sigcatch */
{"%*s", NULL, NULL}, /* discard signal */
{"%*s", NULL, NULL}, /* discard blocked */
{"%*s", NULL, NULL}, /* discard sigignore */
{"%*s", NULL, NULL}, /* discard sigcatch */
{"%lu", GF(wchan)},
{"%*u", NULL}, /* dsicard nswap */
{"%*u", NULL}, /* discard cnswap */
{"%*u", NULL, NULL}, /* dsicard nswap */
{"%*u", NULL, NULL}, /* discard cnswap */
{"%d", GF(exit_signal)},
{"%d", GF(processor)},
{"%lu", GF(rtprio)},
{"%lu", GF(sched)}
#undef GF
#undef GDF
};
const int stat_size = sizeof(proc_stab) / sizeof(struct file_item);
......@@ -93,3 +95,12 @@ int get_proc_stat(struct domain *dom)
}
return 1;
}
void refresh_delta_stat(struct domain *new, struct domain *old)
{
for (int i = 0; i < stat_size; i++) {
if (proc_stab[i].delta_fun) {
(*proc_stab[i].delta_fun)(new, old);
}
}
}
......@@ -13,39 +13,40 @@
#ifndef SRC_PROC_H
#define SRC_PROC_H
GET_FUN(state)
GET_FUN(ppid)
GET_FUN(pgrd)
GET_FUN(session)
GET_FUN(tty)
GET_FUN(tpgid)
GET_FUN(flags)
GET_FUN(min_flt)
GET_FUN(cmin_flt)
GET_FUN(maj_flt)
GET_FUN(cmaj_flt)
GET_FUN(utime)
GET_FUN(stime)
GET_FUN(cutime)
GET_FUN(cstime)
GET_FUN(priority)
GET_FUN(nice)
GET_FUN(nlwp)
GET_FUN(alarm)
GET_FUN(start_time)
GET_FUN(vsize)
GET_FUN(rss)
GET_FUN(rss_rlim)
GET_FUN(start_code)
GET_FUN(end_code)
GET_FUN(start_stack)
GET_FUN(kstk_esp)
GET_FUN(kstk_eip)
GET_FUN(wchan)
GET_FUN(exit_signal)
GET_FUN(processor)
GET_FUN(rtprio)
GET_FUN(sched)
GET_VALUE(state)
GET_VALUE(ppid)
GET_VALUE(pgrd)
GET_VALUE(session)
GET_VALUE(tty)
GET_VALUE(tpgid)
GET_VALUE(flags)
GET_VALUE(min_flt)
GET_VALUE(cmin_flt)
GET_VALUE(maj_flt)
GET_VALUE(cmaj_flt)
GET_DELTA_FUN(utime)
GET_DELTA_FUN(stime)
GET_VALUE(cutime)
GET_VALUE(cstime)
GET_VALUE(priority)
GET_VALUE(nice)
GET_VALUE(nlwp)
GET_VALUE(alarm)
GET_VALUE(start_time)
GET_VALUE(vsize)
GET_VALUE(rss)
GET_VALUE(rss_rlim)
GET_VALUE(start_code)
GET_VALUE(end_code)
GET_VALUE(start_stack)
GET_VALUE(kstk_esp)
GET_VALUE(kstk_eip)
GET_VALUE(wchan)
GET_VALUE(exit_signal)
GET_VALUE(processor)
GET_VALUE(rtprio)
GET_VALUE(sched)
int get_proc_stat(struct domain *dom);
void refresh_delta_stat(struct domain *new, struct domain *old);
#endif
......@@ -15,9 +15,6 @@
#include <unistd.h>
typedef void *(*DFUN_T)(const void *);
typedef void *(DFUN_VOID_T)(void *, void *);
typedef unsigned long long u64;
#define DOMAIN_NAME_MAX 256
......@@ -27,23 +24,35 @@ typedef unsigned long long u64;
#define DFX_VALUE(v) v, DELTA_VALUE(v)
#define GET_NAME(v) domain_get_ ## v
#define GET_FUN(v) \
#define GET_VALUE(v) \
static inline void *GET_NAME(v)(struct domain *dom) \
{ \
return (void *)(&(dom->v)); \
}
#define GET_DELTA_NAME(v) domain_get_delta_ ## v
#define GET_DELTA_FUN(v) \
#define GET_DELTA_VALUE(v) \
static inline void *GET_DELTA_NAME(v)(struct domain *dom) \
{ \
return (void *)(&(dom->DELTA_VALUE(v))); \
}
#define DELTA_NAME(v) domain_delta_ ## v
#define DELTA_FUN(v) \
static inline void DELTA_NAME(v)(struct domain *new, \
struct domain *old) \
{ \
new->DELTA_VALUE(v) = new->v - old->v; \
}
#define GET_DELTA_FUN(v) \
GET_VALUE(v) \
DELTA_FUN(v)
struct file_item {
const char *format;
DFUN_T get_fun;
DFUN_T delta_fun;
void *(*get_fun)(void *);
void (*delta_fun)(void *, void *);
};
struct domain {
......@@ -83,11 +92,10 @@ struct domain {
sched,
wchan;
u64
utime,
stime,
DFX_VALUE(utime),
DFX_VALUE(stime),
cutime,
cstime,
start_time;
};
#endif
......@@ -26,6 +26,7 @@
int delay_time;
int quit_flag;
struct domain_list scr_cur;
struct domain_list scr_pre;
static void init_screen(void)
{
......@@ -101,6 +102,13 @@ static void print_domain_field(struct domain *dom, int field)
printw("%*lu", fields[i].align, dom->pid);
break;
}
case FD_CPU: {
u64 cpu_jeffies = dom->DELTA_VALUE(utime) + dom->DELTA_VALUE(stime);
double usage = (double)cpu_jeffies * 100 /
sysconf(_SC_CLK_TCK) / delay_time;
printw("%*.1f", fields[i].align, usage);
break;
}
case FD_STATE: {
printw("%*c", fields[i].align, dom->state);
break;
......@@ -228,7 +236,7 @@ int main(int argc, char *argv[])
delay_time = 1; /* default delay 1s between display*/
do {
refresh_domains(&scr_cur);
refresh_domains(&scr_cur, &scr_pre);
/* display frame make */
move(0, 0);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册