#include "myMonitoringTool.h" #include #include #include #include #include #define MAIN 0 #define MEM 1 #define CPU 2 #define CORE 3 bool isint(char *str) { ///_|> descry: checks if a string is an integer ///_|> str: string to check ///_|> returning: true iff is an integer int i = 0; while (str[i] != '\0') { if (!isdigit(str[i])) { return false; } i += 1; } return true; } void sigint_handler(int sig) { ///_|> descry: Handles SIGINT, exiting if pressed twice ///_|> sig: signal number ///_|> returning: void static int count = 0; if (count == 0) { printf("\nPress Ctrl+C again to quit"); count++; char buf[LINE_BUF]; fgets(buf, sizeof buf, stdin); count = 0; if (signal(SIGINT, sigint_handler) != 0) { perror("signal"); exit(1); } } else { exit(0); } } // Parse input, read values, display requested output int main(int argc, char **argv) { ///_|> Parse CLAs, implement children to read data, prints childrens data ///_|> argc: number of arguments including function name ///_|> argv: list of string arguments ///_|> retuning: integer success code if (signal(SIGTSTP, SIG_IGN) != 0) { perror("signal"); exit(1); } bool show_mem = false; bool show_cpu = false; bool show_cores = false; int samples = 20; int tdelay = 5e5; int nums_given = 0; // Parse input for (int i = 1; i < argc; i++) { char first9[10]; strncpy(first9, argv[i], 9); first9[9] = '\0'; char first10[11]; strncpy(first10, argv[i], 10); first10[10] = '\0'; if (strcmp(argv[i], "--memory") == 0) { show_mem = true; } else if (strcmp(argv[i], "--cpu") == 0) { show_cpu = true; } else if (strcmp(argv[i], "--cores") == 0) { show_cores = true; } else if (isint(argv[i])) { if (nums_given == 0) { samples = atoi(argv[i]); } else if (nums_given == 1) { tdelay = atoi(argv[i]); } else { printf("Unknown flag %s\nUsage: myMonitoringTool [samples [tdelay]] " "[--memory] [--cpu] [--cores] [--samples=N] [--tdelay=T]\n", argv[i]); exit(1); } nums_given += 1; } else if (strcmp(first9, "--tdelay=") == 0) { char value[LINE_BUF]; strncpy(value, argv[i] + 9, 20); tdelay = atoi(value); } else if (strcmp(first10, "--samples=") == 0) { char value[LINE_BUF]; strncpy(value, argv[i] + 10, 20); samples = atoi(value); } else { printf("Unknown flag %s\nUsage: myMonitoringTool [samples [tdelay]] " "[--memory] [--cpu] [--cores] [--samples=N] [--tdelay=T]\n", argv[i]); exit(1); } } bool show_all = !(show_mem || show_cpu || show_cores); if (show_cores && !(show_mem || show_cpu || show_all)) { samples = 1; } int cpu_cores = get_file_line_value("/proc/cpuinfo", 11); int p[2]; // Mem pipe int q[2]; // Cpu pipe int r[2]; // Core pipe if (pipe(p) == -1 || pipe(q) == -1) { perror("pipe"); exit(1); } int cpu_proc = fork(); int mem_proc = -2; if (cpu_proc != 0) { mem_proc = fork(); } if (cpu_proc == -1 || mem_proc == -1) { perror("fork"); exit(1); } int id = -1; if (cpu_proc != 0 && mem_proc > 0) { close(p[1]); close(q[1]); id = MAIN; if (signal(SIGINT, sigint_handler) != 0) { perror("signal"); exit(1); } } else if (cpu_proc == 0 && mem_proc <= 0) { close(p[0]); close(p[1]); close(q[0]); id = CPU; if (signal(SIGINT, SIG_IGN) != 0) { perror("signal"); exit(1); } } else { assert(cpu_proc != 0 && mem_proc == 0); close(p[0]); close(q[0]); close(q[1]); id = MEM; if (signal(SIGINT, SIG_IGN) != 0) { perror("signal"); exit(1); } } // Prepare the core info char coreinfo[PANE_BUF]; if (id == MAIN && (show_cores || show_all)) { if (pipe(r) == -1) { perror("pipe"); exit(1); } int pid = fork(); if (pid == -1) { perror("fork"); exit(1); } if (pid == 0) { close(r[0]); int cpu_max_freq = get_file_line_value( "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", 0); draw_cores(cpu_cores, cpu_max_freq, r[1]); exit(0); } else { close(r[1]); } } // Draw the frames int mem_total = get_file_line_value("/proc/meminfo", 0); // Initialize arrays for values that change, scaled from 0 to 10. For use // in children int mem_usages[samples]; int cpu_utils[samples]; // Values that will be printed, for use in parent char meminfo[PANE_BUF]; char cpuinfo[PANE_BUF]; // Draw, compute, and display output for (int i = 0; i < samples; i++) { if (id == MEM && (show_mem || show_all)) { assert(mem_proc == 0 && cpu_proc != 0); get_mem_usage(mem_total, meminfo, mem_usages, i); write(p[1], meminfo, PANE_BUF); raise(SIGSTOP); } if (id == CPU && (show_cpu || show_all)) { assert(mem_proc != 0 && cpu_proc == 0); get_cpu_usage(cpu_cores, cpuinfo, cpu_utils, i, tdelay / 2); write(q[1], cpuinfo, PANE_BUF); raise(SIGSTOP); } // Display cores info if (id == MAIN) { if (show_mem || show_cpu || show_all) { usleep(tdelay); } draw_reset(samples, tdelay); if (show_mem || show_all) { // printf("main wait to read mem\n"); read(p[0], meminfo, PANE_BUF); printf("%s", meminfo); if (kill(mem_proc, SIGCONT) != 0) { perror("kill"); exit(1); }; } if (show_cpu || show_all) { read(q[0], cpuinfo, PANE_BUF); printf("%s", cpuinfo); if (kill(cpu_proc, SIGCONT) != 0) { perror("kill"); exit(1); }; } if (show_cores || show_all) { // The core info had time to generate, now it should read without // generation time if (i == 0) { read(r[0], coreinfo, PANE_BUF); } printf("%s", coreinfo); } } } return 0; }