Jak na Linuxu v programu v jazyce C sledovat aktuální frekvenci procesoru
27.7.2020
Aktuální frekvenci jednotlivých procesorů/jader zjistíme načtením souboru /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq, kde * je číslo toho kterého procesoru/jádra v kilohertzech. Můžeme tedy za * postupně dosazovat čísla od nuly a po testu zda takový soubor existuje, jej načíst a hodnotu převést na číslo a podle potřeby nějak formátově vypsat (nejlépe v MHz nebo GHz)
Následující zdrojový kód můžeme po přeložení využít jako výstup na nějaký panel (tint2, xfce4-panel, ...), kde nastavíme jeho spuštění třeba každou sekundu. Jako parametry můžeme zadat nadpis (label) jako parametr -l a pokud chceme výpis v MHz, zadáme parametr jednotky jako -um. Výchozí jednotkou jsou GHz.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <getopt.h>
#define MAX_LABEL_LENGTH 15
#define MAX_CPU_COUNT 16
long _frequency[MAX_CPU_COUNT];
unsigned int _cpu_found = 0;
int _units = 6; // Ghz
int is_regular_file(const char* file_path)
{
struct stat ss;
if (stat(file_path, &ss) != 0)
return 0;
else
return (ss.st_mode & S_IFMT) == S_IFREG;
}
long get_value_from_file(const char* file_path)
{
FILE* pfile = fopen(file_path, "r");
if (NULL == pfile)
return -1;
char buffer[255];
long lret;
if (fgets(buffer, sizeof(buffer), pfile))
{
lret = strtol(buffer, NULL, 10);
if (0 == lret)
{
lret = -1;
}
else if (LONG_MAX == lret || LONG_MIN == lret)
{
lret = -1;
}
}
else
{
lret = -1;
}
fclose(pfile);
return lret;
}
int main(int argc, char** argv)
{
char label[MAX_LABEL_LENGTH+1];
int opt;
strcpy(label, "cpu: ");
if (argc > 1)
{
while ((opt = getopt(argc, argv, "l:u:")) != -1)
{
switch (opt)
{
case 'l':
if (strlen(optarg) <= MAX_LABEL_LENGTH)
{
if (0 == strcmp(optarg, "0"))
*label = 0;
else
strcpy(label, optarg);
}
break;
case 'u':
if (*optarg == 'm' || *optarg == 'M')
_units = 3;
break;
}
}
}
char file_path[255];
for (;;)
{
sprintf(file_path,
"/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq",
_cpu_found);
if (is_regular_file(file_path))
{
_frequency[_cpu_found] = get_value_from_file(file_path);
_cpu_found++;
}
else
break;
}
printf("%s", label);
for (size_t i = 0; i < _cpu_found; i++)
{
if (6 ==_units)
printf("%.2f ", (float)_frequency[i]/1000000);
else
printf("%ld ", _frequency[i]/1000);
}
if (6 ==_units)
printf("(GHz)");
else
printf("(MHz)");
return EXIT_SUCCESS;
}
Zdrojový kód přeložíme překladačem GCC:
gcc -O3 show-cpu-freq.c -o show-cpu-freq
Zdojový kód na github: https://github.com/radekchalupa/cpu-tools/blob/master/show-cpu-freq.c