Как рассчитать загрузку процессора процесса PID в Linux из C?
Я хочу программно [в C] вычислить использование ЦП % для данного идентификатора процесса в Linux.
Как мы можем получить использование процессора в реальном времени % для данного процесса?
чтобы было еще яснее:
- Я должен быть в состоянии определить использование ЦП для предоставленного processid или процесса.
- процесс не обязательно должен быть дочерним процессом.
- Я хочу решение на языке' C'.
11 ответов:
вам нужно разобрать данные из
/proc/<PID>/stat. Это первые несколько полей (отDocumentation/filesystems/proc.txtв исходном коде ядра):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вы, наверное, после
utimeи/илиstime. Вам также нужно будет прочитатьcpuстроку с/proc/stat, который выглядит так:cpu 192369 7119 480152 122044337 14142 9937 26747 0 0это говорит вам совокупное время процессора, которое было использовано в различных категориях, в единицах jiffies. Вам нужно взять сумму значений в этой строке, чтобы получить
time_totalмера.читать как
utimeиstimeдля процесса, который вас интересует, и читатьtime_totalС/proc/stat. Затем поспите секунду или около того и прочитайте их все снова. Теперь вы можете рассчитать использование ЦП процесса за время выборки, с помощью: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);смысл?
getrusage () может помочь вам в определении использования текущего процесса или его дочернего
обновление: Я не могу вспомнить API. Но все подробности будут в /proc/PID / stat, так что если бы мы могли разобрать его, мы можем получить процент.
EDIT: Поскольку CPU % не является прямым для вычисления, вы можете использовать выборку здесь. Прочитайте ctime и utime для PID в определенный момент времени и снова прочитайте те же значения после 1 сек. Найти разницу и разделить на сто. Вы получите использование для этого процесса в течение одной секунды.
(может стать более сложным, если есть много процессоров)
легкий шаг к шагу для nubs, как я :)
прочитайте первую строку /proc / stat, чтобы получить 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 где pid-это pid процесса, который вы хотите узнать об использовании ЦП, например:
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 ....)Теперь суммируйте время пользователя и системное время и получите proc_times1
Теперь подождите 1 секунду или больше
сделайте это снова, и получите total_cpu_usage2 и proc_times2
формула это:
(number of processors) * (proc_times2 - proc_times1) * 100 / (float) (total_cpu_usage2 - total_cpu_usage1)вы можете получить число процессоров из /proc / cpuinfo
Я написал две маленькие функции C, основанные на ответе cafs, чтобы вычислить пользователя+использование процессора ядра процесса: https://github.com/fho/code_snippets/blob/master/c/getusage.c
вы можете прочитать на странице справочника прок для более подробной информации, но в целом вы можете прочитать /proc/[number]/stat, чтобы получить информацию о процессе. Это также используется командой "ps".
все поля и их спецификаторы формата scanf задокументированы в proc manpage.
вот некоторые сведения из manpage скопировано (довольно долго):
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.
Это мое решение...
/* 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
когда вы хотите контролировать указанный процесс, как правило, это делается с помощью скриптов. Вот пример perl. Это ставит проценты так же, как и top, scalling его на один процессор. Затем, когда какой-то процесс активен, работая с 2 потоками, загрузка ЦП может быть более 100%. Специально посмотрите, как подсчитываются ядра процессора :D тогда позвольте мне показать мой пример:
#!/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=+; 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; }Я надеюсь, что это поможет вам в любом мониторинге. Конечно, вы должны использовать scanf или другие функции C для преобразования любых регулярных выражений perl, которые у меня есть используется с источником. Конечно, 1 секунда для сна не является обязательным. вы можете использовать любое время. эффект заключается в том, что вы получите среднюю нагрузку на заданный период времени. Когда вы будете использовать его для мониторинга, конечно, последние значения вы должны поставить снаружи. Это необходимо, потому что мониторинг обычно вызывает скрипты периодически, и скрипт должен закончить свою работу как можно скорее.
установить
psacctилиacctпакета. Тогда используйтеsaкоманда для отображения процессорного времени, используемого для различных команд. SA man pageхороший howto С сайта nixCraft.
Я думаю, что стоит посмотреть на исходный код команды GNU "time". времени Он выводит время процессора пользователя / системы вместе с реальным истекшим временем. Он вызывает системный вызов wait3/wait4 (если он доступен), а в противном случае он вызывает системный вызов times. подождите * системный вызов возвращает структурную переменную" rusage", а системный вызов times возвращает"tms". Кроме того, вы можете взглянуть на системный вызов getrusage, который также возвращает очень интересную информацию о времени. времени
вместо того, чтобы анализировать это из proc, можно использовать такие функции, как getrusage() или clock_gettime() и вычислять использование ЦП как отношение или время wallclock и время процесса/потока, используемого на ЦП.
Comments