-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
149 lines (129 loc) · 5.22 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <argp.h>
#include <time.h>
const char *argp_program_version = "system_info 0.1.0";
const char *argp_program_bug_address = "[email protected]";
static char doc[] = "system_info -- measure your system CPU load";
static struct argp_option options[] = {
{"file", 'f', "FILE", 0, "Save results to a file"},
{"interval", 'i', "INTERVAL", 0, "Frequency of measurements in seconds. Default to 1 second."},
{"time", 't', "TIME", 0, "Time of measurement in seconds. Default to 60 seconds."},
{0}
};
struct arguments {
char *file;
unsigned int interval;
unsigned int time;
};
struct cpu_info {
char name[10];
long long user;
long long nice;
long long system;
long long idle;
long long iowait;
long long irq;
long long softirq;
long long steal;
long long guest;
long long guest_nice;
};
void save_to_csv(char *file_name, float *cpu_loads, unsigned int size);
void print_args(struct arguments arguments);
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
int interval, time;
struct arguments *arguments = state->input;
switch (key) {
case 'f':
arguments->file = arg;
break;
case 'i':
interval = atoi(arg);
if (interval < 1) {
printf("Interval cannot be lower than 1\n");
argp_usage(state);
}
arguments->interval = (unsigned int) interval;
break;
case 't':
time = atoi(arg);
if (time < 1) {
printf("Time cannot be lower than 1\n");
argp_usage(state);
}
arguments->time = (unsigned int) time;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = {options, parse_opt, 0, doc};
int main(int argc, char **argv) {
unsigned long timestamp = (unsigned long)time(NULL);
int timestamp_len = snprintf(NULL, 0, "%lu", timestamp);
char *file_name = (char *)malloc(timestamp_len + 1 + 4); // +1 for NULL byte and +4 for .csv extenstion
snprintf(file_name, timestamp_len + 1 + 4, "%lu.csv", timestamp);
struct arguments arguments;
arguments.file = file_name;
arguments.interval = 1;
arguments.time = 60;
argp_parse(&argp, argc, argv, 0, 0, &arguments);
print_args(arguments);
unsigned int iterations = arguments.time / arguments.interval;
fprintf(stdout, "Iterations: %d\n", iterations);
struct cpu_info last_cpu_info;
struct cpu_info current_cpu_info;
FILE *stat;
float *cpu_loads = calloc(iterations, sizeof(float));;
stat = fopen("/proc/stat", "r");
fscanf(stat, "%s %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", last_cpu_info.name, &last_cpu_info.user,
&last_cpu_info.nice, &last_cpu_info.system, &last_cpu_info.idle,
&last_cpu_info.iowait, &last_cpu_info.irq, &last_cpu_info.softirq,
&last_cpu_info.steal, &last_cpu_info.guest, &last_cpu_info.guest_nice);
fclose(stat);
for (int i = 0; i < iterations; i++) {
sleep(arguments.interval);
stat = fopen("/proc/stat", "r");
fscanf(stat, "%s %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", current_cpu_info.name, ¤t_cpu_info.user,
¤t_cpu_info.nice, ¤t_cpu_info.system, ¤t_cpu_info.idle,
¤t_cpu_info.iowait, ¤t_cpu_info.irq, ¤t_cpu_info.softirq,
¤t_cpu_info.steal, ¤t_cpu_info.guest, ¤t_cpu_info.guest_nice);
fclose(stat);
long current_busy_time = current_cpu_info.user + current_cpu_info.nice +
current_cpu_info.system + current_cpu_info.irq +
current_cpu_info.softirq + current_cpu_info.steal;
long current_total_time =
current_busy_time + current_cpu_info.idle + current_cpu_info.iowait;
long last_busy_time = last_cpu_info.user + last_cpu_info.nice +
last_cpu_info.system + last_cpu_info.irq +
last_cpu_info.softirq + last_cpu_info.steal;
long last_total_time = last_busy_time + last_cpu_info.idle + last_cpu_info.iowait;
float totald = current_total_time - last_total_time;
float busyd = current_busy_time - last_busy_time;
float cpu_load = busyd / totald * 100.0f;
fprintf(stdout, "totald: %f, busyd: %f, load: %f%%\n", totald, busyd, cpu_load);
cpu_loads[i] = cpu_load;
last_cpu_info = current_cpu_info;
}
save_to_csv(arguments.file, cpu_loads, iterations);
free(cpu_loads);
free(file_name);
return 0;
}
void print_args(struct arguments arguments) {
fprintf(stdout, "Output: %s\n"
"Interval: %d\n"
"Time: %d\n", arguments.file, arguments.interval, arguments.time);
}
void save_to_csv(char *file_name, float *cpu_loads, unsigned int size) {
FILE *file = fopen(file_name, "w");
for (int i = 0; i < size; i++) {
// print to two decimal places
fprintf(file, "%.2f\n", cpu_loads[i]);
}
fclose(file);
}