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

Quiero calcular programáticamente [en C] el% de uso de CPU para una ID de proceso dada en Linux.

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

Para hacerlo más claro:

  • Debería poder determinar el uso de la CPU para el proceso o proceso proporcionado.
  • El proceso no necesita ser el proceso secundario.
  • Quiero la solución en lenguaje ‘C’.

Necesita analizar los datos de /proc//stat . Estos son los primeros campos (de Documentation/filesystems/proc.txt en la fuente de su kernel):

 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 

Probablemente estés después de utime y / o stime . También necesitará leer la línea de la cpu de /proc/stat , que se ve así:

 cpu 192369 7119 480152 122044337 14142 9937 26747 0 0 

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

Lea tanto utime como stime para el proceso que le interesa, y lea time_total de /proc/stat . Luego duerma por un segundo más o menos, y léelos nuevamente. Ahora puede calcular el uso de la 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); 

¿Tener sentido?

getrusage () puede ayudarlo a determinar el uso del proceso actual o su hijo

Actualización: no recuerdo una API. Pero todos los detalles estarán en / proc / PID / stat, por lo que si pudiéramos analizarlo, podemos obtener el porcentaje.

EDITAR: Dado que el% de CPU no es sencillo de calcular, puede usar el tipo de material de muestra 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. Encuentra la diferencia y divide por cien. Obtendrá la utilización de ese proceso durante el último segundo.

(puede ser más complejo si hay muchos procesadores)

fácil paso a paso para 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; 

read / proc / pid / stat donde pid es el pid del proceso que desea conocer el uso de la CPU, como este:

 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 sum el tiempo de uso y del sistema y obtén proc_times1

ahora espera 1 segundo o más

hacerlo de nuevo, y obtener total_cpu_usage2 y proc_times2

la formula es:

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

puedes obtener el número de cpus de / proc / cpuinfo

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

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

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

A continuación, se incluye 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. 

Eche un vistazo al comando “pidstat”, suena exactamente como lo requiere.

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  #include  #include  #include  #include  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 

Cuando desee supervisar el proceso especificado, generalmente se realiza mediante scripts. Aquí está el ejemplo perl. Esto pone los porcentajes de la misma manera que los superiores y los convierte en una sola CPU. Luego, cuando algún proceso está activo trabajando con 2 hilos, el uso de la CPU puede ser más del 100%. Mire especialmente cómo se cuentan los núcleos de CPU: D déjenme 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 te ayude en cualquier monitoreo. Por supuesto, debe usar scanf u otras funciones de C para convertir cualquier expresión regular de perl que haya utilizado en la fuente C. Por supuesto, 1 segundo para dormir no es obligatorio. puedes usar cualquier momento El efecto es que obtendrá carga de averrage en el período de tiempo especificado. Cuando lo usará para monitorear, por supuesto, los últimos valores debe colocar afuera. Es necesario, porque el monitoreo usualmente llama a los scripts periódicamente, y el script debe terminar su trabajo lo antes posible.

Instale el paquete psacct o acct . Luego use el comando sa para mostrar el tiempo de CPU utilizado para varios comandos. sa man page

Un buen howto del sitio nixCraft.

Creo que vale la pena mirar el código fuente del comando “tiempo” de GNU. time Muestra el tiempo de CPU del usuario / sistema junto con el tiempo real transcurrido. Llama a la llamada al sistema wait3 / wait4 (si está disponible) y, de lo contrario, llama por llamada al sistema. wait * system call devuelve una variable struct “rusage” y las veces que la llamada al sistema devuelve “tms”. Además, puedes echarle un vistazo a la llamada al sistema getrusage que también devuelve información de sincronización muy interesante. hora

En lugar de analizar esto desde el proceso, se pueden usar funciones como getrusage () o clock_gettime () y calcular el uso de la CPU como una relación o tiempo y hora de reloj de pared en el proceso / subproceso utilizado en la CPU.