Add main.c
This commit is contained in:
commit
fc4b14bc28
1 changed files with 124 additions and 0 deletions
124
main.c
Normal file
124
main.c
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* cpu_governor_monitor - Simple CLI tool to sample the current CPU governor
|
||||
* and log it together with a caller-supplied C-state indicator.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
|
||||
|
||||
struct cpu_log_entry {
|
||||
char governor[30];
|
||||
int c_state;
|
||||
time_t timestamp;
|
||||
};
|
||||
|
||||
static void trim_newline(char *str)
|
||||
{
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
size_t len = strcspn(str, "\r\n");
|
||||
str[len] = '\0';
|
||||
}
|
||||
|
||||
const char *get_current_governor(void)
|
||||
{
|
||||
static char governor_buf[30] = "unknown";
|
||||
FILE *file = fopen(GOVERNOR_PATH, "r");
|
||||
|
||||
if (!file) {
|
||||
perror("fopen scaling_governor");
|
||||
return governor_buf;
|
||||
}
|
||||
|
||||
if (!fgets(governor_buf, sizeof(governor_buf), file)) {
|
||||
perror("fgets scaling_governor");
|
||||
snprintf(governor_buf, sizeof(governor_buf), "unknown");
|
||||
fclose(file);
|
||||
return governor_buf;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
trim_newline(governor_buf);
|
||||
return governor_buf;
|
||||
}
|
||||
|
||||
void log_cpu_state(const char *governor, int c_state)
|
||||
{
|
||||
struct cpu_log_entry entry;
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
|
||||
if (governor) {
|
||||
strncpy(entry.governor, governor, sizeof(entry.governor) - 1);
|
||||
} else {
|
||||
strncpy(entry.governor, "unknown", sizeof(entry.governor) - 1);
|
||||
}
|
||||
|
||||
entry.c_state = c_state;
|
||||
entry.timestamp = time(NULL);
|
||||
|
||||
char ts_buf[32];
|
||||
struct tm tm_info;
|
||||
|
||||
if (localtime_r(&entry.timestamp, &tm_info) != NULL) {
|
||||
strftime(ts_buf, sizeof(ts_buf), "%Y-%m-%d %H:%M:%S", &tm_info);
|
||||
} else {
|
||||
snprintf(ts_buf, sizeof(ts_buf), "unknown_time");
|
||||
}
|
||||
|
||||
printf("timestamp=%s (epoch=%ld) governor=%s c_state=%d\n",
|
||||
ts_buf,
|
||||
(long)entry.timestamp,
|
||||
entry.governor,
|
||||
entry.c_state);
|
||||
}
|
||||
|
||||
static void print_usage(const char *prog)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [c_state]\n", prog);
|
||||
fprintf(stderr, "If c_state is omitted, -1 is logged to indicate unknown.\n");
|
||||
}
|
||||
|
||||
static int parse_c_state(const char *arg, int *c_state)
|
||||
{
|
||||
char *endptr = NULL;
|
||||
long value = strtol(arg, &endptr, 10);
|
||||
|
||||
if (endptr == arg || *endptr != '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value < INT_MIN || value > INT_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*c_state = (int)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c_state = -1;
|
||||
|
||||
if (argc > 2) {
|
||||
print_usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
if (parse_c_state(argv[1], &c_state) != 0) {
|
||||
fprintf(stderr, "Invalid c_state value: %s\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
const char *governor = get_current_governor();
|
||||
log_cpu_state(governor, c_state);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
Reference in a new issue