web-dev-qa-db-fra.com

Comment calculer l'utilisation du processeur d'un processus par PID sous Linux à partir de C?

Je souhaite par programme [en C] calculer le pourcentage d'utilisation du processeur pour un ID de processus donné sous Linux.

Comment pouvons-nous obtenir le pourcentage d'utilisation du processeur en temps réel pour un processus donné?

Pour être plus clair:

  • Je devrais être capable de déterminer l'utilisation du processeur pour le processid ou le processus fourni.
  • Le processus ne doit pas nécessairement être le processus enfant.
  • Je veux la solution en langage 'C'.
93
codingfreak

Vous devez analyser les données de /proc/<PID>/stat. Ce sont les premiers champs (de Documentation/filesystems/proc.txt dans votre source du noyau):

Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
..............................................................................
 Field          Content
  pid           process id
  tcomm         filename of the executable
  state         state (R is running, S is sleeping, D is sleeping in an
                uninterruptible wait, Z is zombie, T is traced or stopped)
  ppid          process id of the parent process
  pgrp          pgrp of the process
  sid           session id
  tty_nr        tty the process uses
  tty_pgrp      pgrp of the tty
  flags         task flags
  min_flt       number of minor faults
  cmin_flt      number of minor faults with child's
  maj_flt       number of major faults
  cmaj_flt      number of major faults with child's
  utime         user mode jiffies
  stime         kernel mode jiffies
  cutime        user mode jiffies with child's
  cstime        kernel mode jiffies with child's

Vous êtes probablement après utime et/ou stime. Vous aurez également besoin de lire la ligne cpu de /proc/stat, qui ressemble à:

cpu  192369 7119 480152 122044337 14142 9937 26747 0 0

Cela vous indique le temps de calcul cumulé utilisé dans différentes catégories, en unités de jiffies. Vous devez prendre la somme des valeurs sur cette ligne pour obtenir un time_total mesure.

Lisez à la fois utime et stime pour connaître le processus qui vous intéresse et lisez time_total de /proc/stat. Ensuite, dormez une seconde ou deux et relisez-les tous. Vous pouvez maintenant calculer l'utilisation du processeur par le processus sur la période d'échantillonnage, avec:

user_util = 100 * (utime_after - utime_before) / (time_total_after - time_total_before);
sys_util = 100 * (stime_after - stime_before) / (time_total_after - time_total_before);

Avoir un sens?

145
caf

getrusage () peut vous aider à déterminer l'utilisation du processus en cours ou de son fils

Mise à jour: Je ne me souviens pas d'une API. Mais tous les détails seront dans/proc/ [~ # ~] pid [~ # ~] /stat, donc si nous pouvions l'analyser, nous pourrions obtenir le pourcentage.

EDIT: Étant donné que le pourcentage de CPU% n'est pas simple à calculer, vous pouvez utiliser un type d'échantillonnage ici. Lisez ctime et utime pour un PID à un moment donné et relisez les mêmes valeurs après 1 seconde. Trouvez la différence et divisez par cent. Vous obtiendrez une utilisation pour ce processus pendant une seconde.

(peut devenir plus complexe s'il y a beaucoup de processeurs)

11
vpram86

étape facile pour l'étape comme moi :)

lit la première ligne de/proc/stat pour obtenir total_cpu_usage1

sscanf(line,"%*s %llu %llu %llu %llu",&user,&Nice,&system,&idle);
total_cpu_usage1 = user + Nice + system + idle;

read/proc/pid/stat où pid est le pid du processus pour lequel vous souhaitez connaître l'utilisation du processeur, comme ceci:

sscanf(line,
"%*d %*s %*c %*d" //pid,command,state,ppid

"%*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu"

"%lu %lu" //usertime,systemtime

"%*ld %*ld %*ld %*ld %*ld %*ld %*llu"

"%*lu", //virtual memory size in bytes
....)

maintenant somme usertime et l'heure du système et obtenez proc_times1

maintenant, attendez 1 seconde ou plus

faites-le encore, et obtenez total_cpu_usage2 et proc_times2

la formule est:

(number of processors) * (proc_times2 - proc_times1) * 100 / (float) (total_cpu_usage2 - total_cpu_usage1)

vous pouvez obtenir le nombre de processeurs depuis/proc/cpuinfo

6
zizzu

J'ai écrit deux petites fonctions C basées sur cafs answer pour calculer l'utilisation d'un processeur par l'utilisateur + le noyau: https://github.com/fho/code_snippets/blob/master/c/getusage.c =

5
fho

Vous pouvez lire le page de manuel de proc pour plus de détails, mais en résumé, vous pouvez lire/proc/[numéro]/stat pour obtenir des informations sur un processus. Ceci est également utilisé par la commande 'ps'.

Tous les champs et leurs spécificateurs de format scanf sont documentés dans le proc manpag e.

Voici quelques informations provenant de la page de manuel copiée (elle est assez longue):

          pid %d The process ID.

          comm %s
                 The  filename of the executable, in parentheses.  This is
                 visible whether or not the executable is swapped out.

          state %c
                 One character from the string "RSDZTW" where  R  is  runâ
                 ning,  S is sleeping in an interruptible wait, D is waitâ
                 ing in uninterruptible disk sleep,  Z  is  zombie,  T  is
                 traced or stopped (on a signal), and W is paging.

          ppid %d
                 The PID of the parent.

          pgrp %d
                 The process group ID of the process.

          session %d
                 The session ID of the process.

          tty_nr %d
                 The tty the process uses.

          tpgid %d
                 The  process group ID of the process which currently owns
                 the tty that the process is connected to.
3
Andre Miller

Jetez un coup d’œil à la commande "pidstat", cela ressemble exactement à ce dont vous avez besoin.

2
James Anderson

Ceci est ma solution ...

/*
this program is looking for CPU,Memory,Procs also u can look glibtop header there was a lot of usefull function have fun..
systeminfo.c
*/
#include <stdio.h>
#include <glibtop.h>
#include <glibtop/cpu.h>
#include <glibtop/mem.h>
#include <glibtop/proclist.h>



int main(){

glibtop_init();

glibtop_cpu cpu;
glibtop_mem memory;
glibtop_proclist proclist;

glibtop_get_cpu (&cpu);
glibtop_get_mem(&memory);


printf("CPU TYPE INFORMATIONS \n\n"
"Cpu Total : %ld \n"
"Cpu User : %ld \n"
"Cpu Nice : %ld \n"
"Cpu Sys : %ld \n"
"Cpu Idle : %ld \n"
"Cpu Frequences : %ld \n",
(unsigned long)cpu.total,
(unsigned long)cpu.user,
(unsigned long)cpu.Nice,
(unsigned long)cpu.sys,
(unsigned long)cpu.idle,
(unsigned long)cpu.frequency);

printf("\nMEMORY USING\n\n"
"Memory Total : %ld MB\n"
"Memory Used : %ld MB\n"
"Memory Free : %ld MB\n"
"Memory Buffered : %ld MB\n"
"Memory Cached : %ld MB\n"
"Memory user : %ld MB\n"
"Memory Locked : %ld MB\n",
(unsigned long)memory.total/(1024*1024),
(unsigned long)memory.used/(1024*1024),
(unsigned long)memory.free/(1024*1024),
(unsigned long)memory.shared/(1024*1024),
(unsigned long)memory.buffer/(1024*1024),
(unsigned long)memory.cached/(1024*1024),
(unsigned long)memory.user/(1024*1024),
(unsigned long)memory.locked/(1024*1024));

int which,arg;
glibtop_get_proclist(&proclist,which,arg);
printf("%ld\n%ld\n%ld\n",
(unsigned long)proclist.number,
(unsigned long)proclist.total,
(unsigned long)proclist.size);
return 0;
}

makefile is
CC=gcc
CFLAGS=-Wall -g
CLIBS=-lgtop-2.0 -lgtop_sysdeps-2.0 -lgtop_common-2.0

cpuinfo:cpu.c
$(CC) $(CFLAGS) systeminfo.c -o systeminfo $(CLIBS)
clean:
rm -f systeminfo
2
Mohan Ram

Lorsque vous souhaitez surveiller un processus spécifié, cela se fait généralement par script. Voici l'exemple de Perl. Cela met les pourcentages de la même manière que le haut, en le réduisant à un processeur. Ensuite, lorsqu'un processus est actif et utilise 2 threads, l'utilisation du processeur peut être supérieure à 100%. Regardez spécialement comment les cœurs de processeur sont comptés: D alors laissez-moi montrer mon exemple:

#!/usr/bin/Perl

my $pid=1234; #insert here monitored process PID

#returns current process time counters or single undef if unavailable
#returns:  1. process counter  , 2. system counter , 3. total system cpu cores
sub GetCurrentLoads {
    my $pid=shift;
    my $fh;
    my $line;
    open $fh,'<',"/proc/$pid/stat" or return undef;
    $line=<$fh>;
    close $fh;
    return undef unless $line=~/^\d+ \([^)]+\) \S \d+ \d+ \d+ \d+ -?\d+ \d+ \d+ \d+ \d+ \d+ (\d+) (\d+)/;
    my $TimeApp=$1+$2;
    my $TimeSystem=0;
    my $CpuCount=0;
    open $fh,'<',"/proc/stat" or return undef;
    while (defined($line=<$fh>)) {
        if ($line=~/^cpu\s/) {
            foreach my $nr ($line=~/\d+/g) { $TimeSystem+=$nr; };
            next;
        };
        $CpuCount++ if $line=~/^cpu\d/;
    }
    close $fh;
    return undef if $TimeSystem==0;
    return $TimeApp,$TimeSystem,$CpuCount;
}

my ($currApp,$currSys,$lastApp,$lastSys,$cores);
while () {
    ($currApp,$currSys,$cores)=GetCurrentLoads($pid);
    printf "Load is: %5.1f\%\n",($currApp-$lastApp)/($currSys-$lastSys)*$cores*100 if defined $currApp and defined $lastApp and defined $currSys and defined $lastSys;
    ($lastApp,$lastSys)=($currApp,$currSys);
    sleep 1;
}

J'espère que cela vous aidera dans n'importe quelle surveillance. Bien sûr, vous devez utiliser scanf ou d’autres fonctions C pour convertir les expressions rationnelles Perl que j’ai utilisées en source C. Bien sûr, 1 seconde pour dormir n'est pas obligatoire. vous pouvez utiliser à tout moment. L’effet est que vous obtiendrez une charge moyenne sur une période spécifiée. Lorsque vous l'utiliserez pour la surveillance, vous devrez bien sûr placer les dernières valeurs à l'extérieur. Il est nécessaire, car la surveillance appelle généralement les scripts périodiquement, et ce dernier doit terminer son travail le plus rapidement possible.

1
Znik

Installez le package psacct ou acct. Utilisez ensuite la commande sa pour afficher le temps CPU utilisé pour les différentes commandes. sa page de manuel

Un Nice howto du site nixCraft.

0
Lifeguard

Au lieu d'analyser cela à partir de proc, vous pouvez utiliser des fonctions telles que getrusage () ou clock_gettime () et calculer l'utilisation du processeur en tant que ratio ou heure/heure/heure/heure/heure du processus/thread utilisé sur le processeur.

0
ensonic

Je pense que cela vaut la peine de regarder GNU le code source de la commande "time". time Il affiche le temps de traitement de l'utilisateur/système avec le temps écoulé réel. Il appelle le système wait3/wait4 call (si disponible) et sinon il appelle fois l'appel système. wait * appel système renvoie une variable struct "rusage" et fois l'appel système renvoie "tms". Vous pouvez également consulter l'appel système getrusage, qui renvoie également un minutage très intéressant. informations. heure

0
user3288728