当我在终端上使用cat /proc/stat
命令时,得到以下输出:
cpu 9268738 47123 3940054 3851366876 911347 0 164981 0 0 0
cpu0 558436 2170 208965 240825151 54221 0 30439 0 0 0
cpu1 699380 1976 382320 240476662 50707 0 7260 0 0 0
cpu2 547485 2685 204733 240867376 56441 0 4410 0 0 0
cpu3 541016 3581 202538 240872692 57657 0 3051 0 0 0
cpu4 552305 2716 286470 240322626 70098 0 60308 0 0 0
cpu5 490248 3598 211000 240891224 59970 0 2596 0 0 0
cpu6 510708 1987 215605 240879645 57692 0 2546 0 0 0
cpu7 528486 3053 220346 240866189 54916 0 2273 0 0 0
cpu8 540615 2563 216076 240857715 53633 0 2161 0 0 0
cpu9 862775 1794 413426 240049704 49504 0 1755 0 0 0
cpu10 576740 5166 230907 240805093 51594 0 2084 0 0 0
cpu11 611709 2192 268375 240408228 62183 0 37502 0 0 0
cpu12 589948 3351 227945 240734505 59752 0 1992 0 0 0
cpu13 552315 3205 217448 240834143 58786 0 2137 0 0 0
cpu14 554752 3387 218348 240835453 56078 0 2222 0 0 0
cpu15 551815 3693 215547 240840464 58106 0 2240 0 0 0
...
从上述输出中,我可以注意到我的计算机有16个不同的CPU。我正在尝试编写一个C程序来获取所有可用CPU内核的CPU利用率。但是问题在于我有以下代码,该代码仅使我能够获取总体CPU使用率,而仅读取/proc/stat
文件的第一行:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
long double cpu0_a[4], cpu0_b[4], loadavg;
FILE *fp;
char dump[50];
while(1)
{
fp = fopen("/proc/stat","r");
fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&cpu0_a[0],&cpu0_a[1],&cpu0_a[2],&cpu0_a[3]);
fclose(fp);
sleep(1);
fp = fopen("/proc/stat","r");
fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&cpu0_b[0],&cpu0_b[1],&cpu0_b[2],&cpu0_b[3]);
fclose(fp);
loadavg = ((cpu0_b[0]+cpu0_b[1]+cpu0_b[2]) - (cpu0_a[0]+cpu0_a[1]+cpu0_a[2])) / ((cpu0_b[0]+cpu0_b[1]+cpu0_b[2]+cpu0_b[3]) - (cpu0_a[0]+cpu0_a[1]+cpu0_a[2]+cpu0_a[3]));
printf("The current CPU utilization is : %Lf\n",loadavg);
}
return(0);
}
如何读取/proc/stat
文件以打印出所有可用CPU的当前CPU利用率,而不是整体打印?
P.S。我是C语言编程的新手,并且来自C#背景,因此我可能缺少C语言中非常基本的内容。感谢您的帮助。
答案 0 :(得分:1)
以下代码完成了工作。尽管经过了适当的考虑,该代码对系统上可用的CPU数量进行了硬编码,因此必须根据所运行的系统手动进行更改。尽管EOF可以与正则表达式结合使用以检查/ proc / stat文件中的cpu利用率,但是正则表达式具有计算开销(对于我正在使用的系统,大约需要30毫秒)。 此代码更适合实时设备的使用,因此,由于上述原因,避免使用正则表达式。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_CPU 16
int main(void)
{
//This code only caters for first 8 CPUs available
long double cpu_a[NUM_CPU+1][4], cpu_b[NUM_CPU+1][4], loadavg[NUM_CPU];
FILE *fp;
char dump[50];
while(1)
{
int count = 0;
fp = fopen("/proc/stat","r");
while(count < NUM_CPU+2)
{
fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&cpu_a[count][0],&cpu_a[count][1],&cpu_a[count][2],&cpu_a[count][3]);
count++;
}
fclose(fp);
usleep(200*1000); // 200 msec sleep and read the /proc/stat file again
count = 0;
fp = fopen("/proc/stat","r");
while(count < NUM_CPU+2)
{
fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&cpu_b[count][0],&cpu_b[count][1],&cpu_b[count][2],&cpu_b[count][3]);
count++;
}
fclose(fp);
for(int i = 1; i < NUM_CPU+2; i++)
{
loadavg[i-1] = ((cpu_b[i][0]+cpu_b[i][1]+cpu_b[i][2]) - (cpu_a[i][0]+cpu_a[i][1]+cpu_a[i][2])) / ((cpu_b[i][0]+cpu_b[i][1]+cpu_b[i][2]+cpu_b[i][3]) - (cpu_a[i][0]+cpu_a[i][1]+cpu_a[i][2]+cpu_a[i][3]));
printf("The current CPU %d utilization is : %Lf\n", (i-1), loadavg[i-1]);
}
printf("\n\n");
}
return(0);
}
在此程序中,CPU使用率1.0 = 100%CPU使用率。
答案 1 :(得分:0)
正如您在后续回答中已经说明的那样,您需要迭代输出行。
但是,要遍历存在的所有CPU而又不知道总数,您可以简单地定义一个C结构,并使用任意(高)计数实例化它。
我已经对您的示例进行了类似的调整,因此输出有所不同,但是作为示例就足够了。
(测试得不好,可能会有一些明显的逻辑漏洞,但还是一个例子)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
outputs CPU utilization for up to MAX_CPU CPUs.
* To output only the individual CPUs and not the combined total, set SKIP_TOTAL to 1
* To output only the combined total, set SKIP_TOTAL to 0, and MAX_CPU to 0
*/
#define MAX_CPU 64 // arbitrary max; can be set to 0 to only output overall
#define SKIP_TOTAL 1 // skips first "cpu", set to 0 to include in output
struct CPUS {
char id[4];
long double user;
long double nice;
long double system;
long double idle;
long double idle_last; // store previous idle value
long double sum_last; // store previous sum value
};
struct CPUS cpus[MAX_CPU + 1];
void calculate(int output) {
long cpu_delta, cpu_idle, cpu_used, utilization;
FILE *fp;
int last_cpu = 0;
int cpu_num = 0;
int sum;
fp = fopen("/proc/stat", "r");
while (last_cpu == 0 && cpu_num <= MAX_CPU) {
fscanf(
fp, "%s %Lf %Lf %Lf %Lf%*[^\n]\n",
(char *)&cpus[cpu_num].id, &cpus[cpu_num].user, &cpus[cpu_num].nice,
&cpus[cpu_num].system, &cpus[cpu_num].idle
);
// check if the first colum (placed in the id field) contains "cpu", if
// not, we are no longer processing CPU related lines
if(strstr(cpus[cpu_num].id, "cpu") != NULL) {
if (cpu_num == 0) {
if (SKIP_TOTAL == 1) {
cpu_num += 1;
continue;
} else {
// overwrite "cpu" to "all"
strcpy(cpus[cpu_num].id, "all");
}
}
// sum all of the values
sum = cpus[cpu_num].user + cpus[cpu_num].nice + \
cpus[cpu_num].system + cpus[cpu_num].idle;
// collect the difference between sum and the last sum
cpu_delta = sum - cpus[cpu_num].sum_last;
// collect idle time
cpu_idle = cpus[cpu_num].idle - cpus[cpu_num].idle_last;
// delta minus ide time
cpu_used = cpu_delta - cpu_idle;
// percentage of utilization
utilization = (100 * cpu_used) / cpu_delta;
if (output == 1) {
printf("%s:\t%li%%\n", cpus[cpu_num].id, utilization);
}
// store the current sum and idle time for calculation on next iteration
cpus[cpu_num].sum_last = sum;
cpus[cpu_num].idle_last = cpus[cpu_num].idle;
} else {
// no more CPUs to enumarte; exit while loop
last_cpu = 1;
}
cpu_num += 1;
}
fclose(fp);
}
int main(void) {
calculate(0); // first pass to collect baseline (no output)
usleep(200*1000); // wait
calculate(1); // collect again and output
return 0;
}