#include "stat.h" #include #include #include #include #include #include #include "display.h" #include "err.h" #include "log.h" #include "mem.h" stat *stat_init() { stat *s = xmalloc(sizeof(stat)); *s = (stat){ .sysver = "", .meminfo = {.mem_available = 0, .mem_total = 0}, .diskinfo = {.disk_available = 0, .disk_total = 0}, }; s->cpu_occ = xmalloc(sizeof(cpu_occupy)); if (s->cpu_occ) *s->cpu_occ = (cpu_occupy){0}; return s; } void stat_get_sysver(stat *s) { FILE *fp = fopen(PROC_PATH_VERSION, "r"); if (!fp) die("Cannot open %s", PROC_PATH_VERSION); if (fgets(s->sysver, sizeof(s->sysver), fp) != NULL) { s->sysver[strcspn(s->sysver, "\n")] = '\0'; } fclose(fp); } void stat_print_cpu_info(WINDOW *w, int y, int maxx, stat *s) { mvwprintw(w, y, maxx - STAT_INFO_WIDTH, " %.2f %%", s->cpu_occ->smooth_cpu); } void stat_print_info(WINDOW *w, int y, int maxx, const char *label, unsigned long total, unsigned long ava) { unsigned long long t_bytes = total; unsigned long long a_bytes = ava; if (strcmp(label, "Mem") == 0 || strcmp(label, "Mem ") == 0) { t_bytes *= 1024; a_bytes *= 1024; } const char *units[] = {"B", "K", "M", "G", "T"}; int t_idx = 0; int a_idx = 0; double d_total = (double)t_bytes; double d_ava = (double)a_bytes; while (d_total >= 1024.0 && t_idx < 4) { d_total /= 1024.0; t_idx++; } while (d_ava >= 1024.0 && a_idx < 4) { d_ava /= 1024.0; a_idx++; } int startx = maxx - STAT_INFO_WIDTH; mvwprintw(w, y, startx, " %.2f%s/%.2f%s", d_ava, units[t_idx], d_total, units[t_idx]); /* wrefresh(w); */ } int stat_get_bar_ticks(int maxx, unsigned long long total, unsigned long long ava) { if (total == 0) return 0; if (ava >= total) return 0; unsigned long long used = total - ava; unsigned long long slots = (unsigned long long)(maxx); return (int)((slots * used) / total); } void stat_draw_cpu_bar(WINDOW *w, int maxx, int y, int x, stat *s) { int ava_to_draw_x = maxx - STAT_INFO_WIDTH - BAR_LABEL_WIDTH; int total_hashes = ava_to_draw_x * (s->cpu_occ->smooth_cpu * 0.1); char hashes[2048] = {0}; if (total_hashes > ava_to_draw_x) total_hashes = ava_to_draw_x; memset(hashes, '#', total_hashes); hashes[total_hashes] = '\0'; mvwprintw(w, y, x, "%-*s [", 4, "CPU"); wprintw_colorful(w, COLOR_PAIR_PROGRESS, "%.*s", total_hashes, hashes); int remaining_spaces = ava_to_draw_x - total_hashes; if (remaining_spaces > 0) { wprintw(w, "%*s", remaining_spaces, ""); } waddch(w, ']'); } void stat_draw_bar(WINDOW *w, const char *label, int maxx, int y, int x, unsigned long total, unsigned long ava) { int ava_to_draw_x = maxx - STAT_INFO_WIDTH - BAR_LABEL_WIDTH; int total_hashes = stat_get_bar_ticks(ava_to_draw_x, total, ava); char hashes[2048] = {0}; init_pair(COLOR_PAIR_PROGRESS, COLOR_GREEN, COLOR_BLACK); if (total_hashes > ava_to_draw_x) total_hashes = ava_to_draw_x; memset(hashes, '#', total_hashes); hashes[total_hashes] = '\0'; mvwprintw(w, y, x, "%-*s [", 4, label); wprintw_colorful(w, COLOR_PAIR_PROGRESS, "%.*s", total_hashes, hashes); int remaining_spaces = ava_to_draw_x - total_hashes; if (remaining_spaces > 0) { wprintw(w, "%*s", remaining_spaces, ""); } waddch(w, ']'); /* wrefresh(w); */ } void stat_get_meminfo(stat *s) { static char buf[128]; char key[32] = ""; unsigned long long val = 0; FILE *fp = fopen(PROC_PATH_MEMINFO, "r"); if (!fp) die("Cannot open %s", PROC_PATH_MEMINFO); while (fgets(buf, sizeof(buf), fp)) { if (sscanf(buf, "%31[^:]: %llu", key, &val) == 2) { if (strcmp(key, "MemTotal") == 0) { s->meminfo.mem_total = val; } else if (strcmp(key, "MemAvailable") == 0) { s->meminfo.mem_available = val; break; } } } fclose(fp); } void stat_get_diskinfo(stat *s) { struct statvfs vfs; if (statvfs("/", &vfs) != 0) { s->diskinfo.disk_total = 0; s->diskinfo.disk_available = 0; log_write(LOG_WARN, "Cannot get disk info"); } s->diskinfo.disk_total = (unsigned long long)vfs.f_blocks * vfs.f_frsize; s->diskinfo.disk_available = (unsigned long long)vfs.f_bavail * vfs.f_frsize; } void stat_get_cpuinfo(stat *s) { char buf[256]; FILE *fp = fopen(PROC_PATH_STAT, "r"); if (!fp) { log_write(LOG_WARN, "Cannot open %s", PROC_PATH_STAT); return; } if (!fgets(buf, sizeof(buf), fp)) { fclose(fp); return; } fclose(fp); unsigned long long user = 0, nice = 0, system = 0, idle = 0; unsigned long long iowait = 0, irq = 0, softirq = 0; sscanf(buf, "%*s %llu %llu %llu %llu %llu %llu %llu", &user, &nice, &system, &idle, &iowait, &irq, &softirq); s->cpu_occ->user = user; s->cpu_occ->nice = nice; s->cpu_occ->system = system; s->cpu_occ->idle = idle; s->cpu_occ->iowait = iowait; s->cpu_occ->irq = irq; s->cpu_occ->softirq = softirq; unsigned long long curr_idle = idle + iowait; unsigned long long curr_total = user + nice + system + idle + iowait + irq + softirq; unsigned long long total_diff = curr_total - s->cpu_occ->prev_total; unsigned long long idle_diff = curr_idle - s->cpu_occ->prev_idle; if (total_diff > 0) { s->cpu_occ->cpu = (double)(total_diff - idle_diff) / (double)total_diff * 100.0; } else { s->cpu_occ->cpu = 0.0; // 防零除 } s->cpu_occ->prev_total = curr_total; s->cpu_occ->prev_idle = curr_idle; /* EMA - Exponential Moving Average */ /* DisplayCPU = alpha * raw_cpu + (1 - alpha) * pre_cpu */ double alpha = 0.1; if (total_diff > 0) { double raw_cpu = (double)(total_diff - idle_diff) / (double)total_diff * 100.0; if (s->cpu_occ->smooth_cpu == 0.0) { s->cpu_occ->smooth_cpu = raw_cpu; } else { s->cpu_occ->smooth_cpu = alpha * raw_cpu + (1 - alpha) * s->cpu_occ->smooth_cpu; } s->cpu_occ->cpu = raw_cpu; } }