Chcę programowo [w C] obliczyć% użycia procesora dla danego identyfikatora procesu w systemie Linux.
Jak możemy uzyskać procentowe użycie procesora w czasie rzeczywistym dla danego procesu?
Aby było to bardziej jasne:
- Powinienem być w stanie określić użycie procesora przez podany identyfikator procesu lub proces.
- Proces nie musi być procesem potomnym.
- Chcę rozwiązania w języku „C”.
Odpowiedzi:
Musisz przeanalizować dane z
/proc/<PID>/stat
. Oto kilka pierwszych pól (zDocumentation/filesystems/proc.txt
twojego źródła jądra):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
Prawdopodobnie szukasz
utime
i / lubstime
. Musisz także przeczytaćcpu
wiersz z/proc/stat
, który wygląda następująco:cpu 192369 7119 480152 122044337 14142 9937 26747 0 0
To pokazuje skumulowany czas procesora, który był używany w różnych kategoriach, w jednostkach migotania. Aby uzyskać
time_total
miarę, musisz wziąć sumę wartości w tej linii .Czytaj zarówno
utime
istime
dla procesu jesteś zainteresowany i czytaćtime_total
z/proc/stat
. Następnie prześpij się na sekundę i przeczytaj je ponownie. Możesz teraz obliczyć użycie procesora przez proces w czasie próbkowania za pomocą: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);
Ma sens?
źródło
/proc/stat
powiedzieć, ile migotów wykonał w sumie procesor i/proc/<PID>/stat
ile migów zostało wykonanych przez pojedynczy proces.man proc
czy twój przyjaciel (szukaj/proc/[pid]/stat
)/proc
pseudo-systemu plików: nauczanie standardowych funkcji dostępu do systemu plików C, takich jakfopen()
iscanf()
jest poza tematem.getrusage () może pomóc w określeniu użycia bieżącego procesu lub jego elementu podrzędnego
Aktualizacja: nie pamiętam API. Ale wszystkie szczegóły będą w / proc / PID / stat, więc gdybyśmy mogli to przeanalizować, moglibyśmy uzyskać procent.
EDYCJA: Ponieważ CPU% nie jest łatwe do obliczenia, możesz użyć tutaj próbkowania. Odczytaj ctime i utime dla PID w danym momencie i przeczytaj te same wartości ponownie po 1 sek. Znajdź różnicę i podziel przez sto. Będziesz korzystać z tego procesu przez ostatnią sekundę.
(może się skomplikować, jeśli jest wiele procesorów)
źródło
Łatwy krok dla początkujących takich jak ja:
/proc/stat
aby uzyskaćtotal_cpu_usage1
.sscanf(line,"%*s %llu %llu %llu %llu",&user,&nice,&system,&idle); total_cpu_usage1 = user + nice + system + idle;
/proc/pid/stat
gdziepid
jest PID procesu, o którym chcesz wiedzieć, użycie procesora, na przykład: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 ....)
usertime
asystemtime
i dostaćproc_times1
total_cpu_usage2
iproc_times2
Formuła to:
(number of processors) * (proc_times2 - proc_times1) * 100 / (float) (total_cpu_usage2 - total_cpu_usage1)
Możesz uzyskać ilość procesorów z
/proc/cpuinfo
.źródło
#include <unistd.h>
i nazwij tę metodęint nb = sysconf(_SC_NPROCESSORS_ONLN);
Napisałem dwie małe funkcje C oparte na odpowiedzi cafs, aby obliczyć użycie procesora przez użytkownika + jądro procesora: https://github.com/fho/code_snippets/blob/master/c/getusage.c
źródło
Możesz przeczytać stronę podręcznika dla proc, aby uzyskać więcej szczegółów, ale podsumowując, możesz przeczytać / proc / [numer] / stat, aby uzyskać informacje o procesie. Jest to również używane przez polecenie „ps”.
Wszystkie pola i ich specyfikatory formatu scanf są udokumentowane na stronie podręcznika proc .
Oto niektóre informacje ze skopiowanej strony podręcznika (jest dość długa):
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.
źródło
ps aux
is better :)Spójrz na polecenie „pidstat”, brzmi dokładnie tak, jak potrzebujesz.
źródło
To jest moje rozwiązanie ...
/* 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
źródło
Kiedy chcesz monitorować określony proces, zwykle odbywa się to za pomocą skryptów. Oto przykład Perla. W ten sposób procenty są takie same jak w przypadku góry, sprowadzając je do jednego procesora. Następnie, gdy jakiś proces jest aktywny, pracując z 2 wątkami, użycie procesora może przekraczać 100%. Specjalnie spójrz, jak liczone są rdzenie procesora: D, a następnie pokażę mój przykład:
#!/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; }
Mam nadzieję, że pomoże ci to w każdym monitorowaniu. Oczywiście powinieneś użyć scanf lub innych funkcji C do konwersji wszelkich wyrażeń regularnych Perla, których używałem, na źródła C. Oczywiście 1 sekunda na spanie nie jest obowiązkowa. możesz użyć w dowolnym momencie. Efekt jest taki, że otrzymasz średnie obciążenie w określonym okresie czasu. Kiedy użyjesz go do monitorowania, oczywiście ostatnie wartości powinieneś umieścić na zewnątrz. Jest to potrzebne, ponieważ monitorowanie zwykle wywołuje skrypty okresowo, a skrypt powinien jak najszybciej zakończyć swoją pracę.
źródło
Zainstaluj
psacct
lubacct
spakuj. Następnie użyjsa
polecenia, aby wyświetlić czas procesora używany dla różnych poleceń. jest stroną podręcznikaMiłym howto ze strony nixCraft.
źródło
Myślę, że warto przyjrzeć się kodowi źródłowemu komend GNU „time”. time Wyświetla czas procesora użytkownika / systemu wraz z rzeczywistym czasem, który upłynął. Wywołuje wywołanie systemowe wait3 / wait4 (jeśli jest dostępne), w przeciwnym razie wywołuje wywołanie systemowe times. wait * wywołanie systemowe zwraca zmienną strukturalną "rusage" i razy, gdy wywołanie systemowe zwróci "tms". Możesz także rzucić okiem na wywołanie systemowe getrusage, które również zwraca bardzo interesujące informacje o czasie. czas
źródło
Zamiast analizować to z proc, można użyć funkcji takich jak getrusage () lub clock_gettime () i obliczyć użycie procesora jako stosunek lub czas wallclock i czas procesu / wątku używany na procesorze.
źródło
Use strace stwierdził, że użycie procesora musi być obliczone według przedziału czasu:
# top -b -n 1 -p 3889 top - 16:46:37 up 1:04, 3 users, load average: 0.00, 0.01, 0.02 Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 5594496 total, 5158284 free, 232132 used, 204080 buff/cache KiB Swap: 3309564 total, 3309564 free, 0 used. 5113756 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3889 root 20 0 162016 2220 1544 S 0.0 0.0 0:05.77 top
# strace top -b -n 1 -p 3889
. . . stat("/proc/3889", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0 open("/proc/3889/stat", O_RDONLY) = 7 read(7, "3889 (top) S 3854 3889 3854 3481"..., 1024) = 342 . . . nanosleep({0, 150000000}, NULL) = 0 . . . stat("/proc/3889", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0 open("/proc/3889/stat", O_RDONLY) = 7 read(7, "3889 (top) S 3854 3889 3854 3481"..., 1024) = 342 . . .
źródło