254 lines
6.0 KiB
C
254 lines
6.0 KiB
C
#include "myMonitoringTool.h"
|
|
#include <assert.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#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;
|
|
} |