Получить использование CPU всех доступных процессоров по отдельности в C - PullRequest
0 голосов
/ 28 февраля 2019

Когда я использую команду 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 различных процессоров.И я пытаюсь написать программу на C для извлечения загрузки ЦП из всех доступных ядер ЦП.Но проблема в том, что у меня есть следующий код, который позволяет мне только получить общее использование ЦП, но только чтение первой строки файла /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 файл для распечатки информации о текущей загрузке ЦП всеми доступными ЦП по отдельности вместо общего?

PS Я новичок в программировании на C и пришел из C #, поэтому мне может не хватать чего-то очень базового в C. СпасибоВы за вашу помощь в этом.

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Как вы уже продемонстрировали в своем последующем ответе, вам нужно перебрать строки вывода.

Но, чтобы перебрать все имеющиеся процессоры, не зная общего количества, вы можете просто определить структуру 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;
}

0 голосов
/ 28 февраля 2019

Следующий код работает.Хотя с должным уважением, код имеет жестко запрограммированное количество процессоров, доступных в системе, и, следовательно, должен быть изменен вручную в зависимости от системы, которую вы используете.Хотя EOF можно было бы использовать в сочетании с регулярным выражением для проверки загрузки ЦП из файла / proc / stat, но регулярные выражения требуют вычислительных затрат (почти 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);
}

NB. Здесь, в программе, загрузка процессора 1.0 = 100% загрузки процессора.

...