¿Cómo calcular el uso de CPU de un proceso por PID en Linux desde C?


Quiero calcular mediante programación [en C] el % de uso de CPU para un ID de proceso dado en Linux.

¿Cómo podemos obtener el % de uso de CPU en tiempo real para un proceso determinado?

Para dejarlo más claro:

  • Debería ser capaz de determinar el uso de CPU para el proceso o proceso proporcionado.
  • El proceso no necesita ser el proceso hijo.
  • Quiero la solución en lenguaje 'C'.
Author: Mateusz Piotrowski, 2009-09-14

11 answers

Necesita analizar los datos de /proc/<PID>/stat. Estos son los primeros campos (de Documentation/filesystems/proc.txt en el código fuente del núcleo):

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

Usted está probablemente después de utime y/o stime. También tendrá que leer la línea cpu de /proc/stat, que se parece a:

cpu  192369 7119 480152 122044337 14142 9937 26747 0 0

Esto le indica el tiempo de CPU acumulado que se ha utilizado en varias categorías, en unidades de jiffies. Necesita tomar la suma de los valores en esta línea para obtener una medida time_total.

Leer tanto utime y stime para el proceso que le interesa, y lea time_total de /proc/stat. Luego duerme un segundo más o menos, y léelas todas de nuevo. Ahora puede calcular el uso de CPU del proceso durante el tiempo de muestreo, con:

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);

¿Tiene sentido?

 136
Author: caf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-15 00:31:06

Getrusage () puede ayudarle a determinar el uso del proceso actual o su hijo

Actualización: No puedo recordar una API. Pero todos los detalles estarán en / proc / PID /stat, así que si podemos analizarlo, podemos obtener el porcentaje.

EDITAR: Dado que el % de CPU no es fácil de calcular, podría usar el tipo de muestreo aquí. Lea ctime y utime para un PID en un punto en el tiempo y lea los mismos valores nuevamente después de 1 segundo. divida por cien. Obtendrá la utilización de ese proceso durante más de un segundo.

(podría volverse más complejo si hay muchos procesadores)

 11
Author: vpram86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-14 09:52:14

Paso a paso fácil para los nubs como yo :)

Lea la primera línea de/proc / stat para obtener total_cpu_usage1

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

Lee /proc / pid / stat donde pid es el pid del proceso que quieres conocer el uso de la cpu, así:

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
....)

Ahora sume el tiempo de usuario y el tiempo del sistema y obtenga proc_times1

Ahora espera 1 segundo o más

Hágalo de nuevo, y obtenga total_cpu_usage2 y proc_times2

La fórmula es:

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

Puede obtener el número de cpu de / proc / cpuinfo

 6
Author: zizzu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-26 14:29:56

Escribí dos pequeñas funciones C basadas en la respuesta de cafs para calcular el uso de cpu del usuario + kernel de un proceso: https://github.com/fho/code_snippets/blob/master/c/getusage.c

 5
Author: fho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-25 14:18:33

Puede leer la página de manual para proc para más detalles, pero en resumen puede leer /proc/[number]/stat para obtener la información sobre un proceso. Esto también es usado por el comando' ps'.

Todos los campos y sus especificadores de formato scanf están documentados en el proc manpage.

He aquí parte de la información de la página de manual copiada (es bastante larga):

          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
Author: Andre Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-14 09:33:29

Eche un vistazo al comando "pidstat", suena exactamente lo que necesita.

 2
Author: James Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-14 09:55:32

Esta es mi solución...

/*
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
Author: Mohan Ram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-21 09:23:08

Cuando desea supervisar el proceso especificado, generalmente se realiza mediante scripts. Aquí está el ejemplo de perl. Esto pone los porcentajes de la misma manera que top, escalándolo a una CPU. Luego, cuando algún proceso está activo trabajando con 2 subprocesos, el uso de la cpu puede ser más del 100%. Mira especialmente cómo se cuentan los núcleos de cpu: D entonces permítanme mostrar mi ejemplo:

#!/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;
}

Espero que le ayude en cualquier monitoreo. Por supuesto, debe usar scanf u otras funciones de C para convertir cualquier regexpes de perl que haya utilizado en C fuente. Por supuesto 1 segundo para dormir no es obligatorio. puedes usar cualquier momento. el efecto es que obtendrá una carga de aversión en el período de tiempo especificado. Cuando se va a utilizar para el monitoreo, por supuesto, los últimos valores que debe poner fuera. Es necesario, porque el monitoreo por lo general llama scripts periódicamente, y script debe terminar su trabajo lo antes posible.

 1
Author: Znik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-27 13:23:14

Instale el paquete psacct o acct. A continuación, utilice el comando sa para mostrar el tiempo de CPU utilizado para varios comandos. sa man page

Un bonito howto del sitio de nixCraft.

 0
Author: Lifeguard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-17 08:20:47

Creo que vale la pena mirar el código fuente del comando GNU "time". tiempo Genera el tiempo de cpu del usuario / sistema junto con el tiempo transcurrido real. Llama a la llamada del sistema wait3/wait4 (si está disponible) y de lo contrario llama a la llamada del sistema times. wait * system call devuelve una variable de estructura " rusage "y times system call devuelve"tms". Además, puede echar un vistazo a la llamada al sistema getrusage que también devuelve información de tiempo muy interesante. tiempo

 0
Author: user3288728,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-13 22:12:00

En lugar de analizar esto desde proc, se pueden usar funciones como getrusage() o clock_gettime() y calcular el uso de la cpu como una relación o tiempo de wallclock y el tiempo del proceso/hilo utilizado en la cpu.

 0
Author: ensonic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-11 06:58:21