web-dev-qa-db-ja.com

LinuxのCからPIDによってプロセスのCPU使用率を計算する方法は?

Linuxで特定のプロセスIDのCPU使用率をプログラムで[Cで]計算したい。

特定のプロセスのリアルタイムCPU使用率を取得するにはどうすればよいですか?

さらに明確にするために:

  • 提供されたプロセスIDまたはプロセスのCPU使用率を判断できるはずです。
  • プロセスは子プロセスである必要はありません。
  • 「C」言語のソリューションが必要です。
93
codingfreak

/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の後です。また、次のような/proc/statからcpu行を読み取る必要があります。

cpu  192369 7119 480152 122044337 14142 9937 26747 0 0

これは、さまざまなカテゴリで使用された累積CPU時間をjiffie単位で示します。 time_totalメジャーを取得するには、この行の値の合計を取る必要があります。

関心のあるプロセスのutimestimeの両方を読み取り、time_totalから/proc/statを読み取ります。その後、1秒間ほど眠り、それらすべてをもう一度読みます。これで、サンプリング時間でのプロセスのCPU使用率を計算できます。

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

理にかなっていますか?

145
caf

getrusage() は、現在のプロセスまたはその子プロセスの使用状況を判断するのに役立ちます

更新:APIを思い出せません。ただし、すべての詳細は/ proc /PID/ statにあるため、解析できる場合はパーセンテージを取得できます。

EDIT:CPU%の計算は単純ではないため、ここではサンプリングのようなものを使用できます。ある時点でPIDのctimeとutimeを読み取り、1秒後に同じ値を再度読み取ります。違いを見つけて、100で割ります。過去1秒間、そのプロセスの使用率が得られます。

(プロセッサが多数ある場合、より複雑になる可能性があります)

11
vpram86

私のようなnubの簡単なステップ:)

/ proc/statの最初の行を読んで、total_cpu_usage1を取得します

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

/ proc/pid/statを読み取ります。ここで、pidは、次のようにcpuの使用状況を知りたいプロセスの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からcpusの数を取得できます

6
zizzu

プロセスのユーザー+カーネルCPU使用量を計算するために、cafsの回答に基づいて2つの小さなC関数を作成しました。 https://github.com/fho/code_snippets/blob/master/c/getusage.c =

5
fho

詳細については procのマンページ を読むことができますが、要約すると/ proc/[number]/statを読んでプロセスに関する情報を取得できます。これは「ps」コマンドでも使用されます。

すべてのフィールドとそのscanf形式指定子は、 proc manpag eで文書化されています。

以下は 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.
3
Andre Miller

「pidstat」コマンドを見てください。まさに必要なもののように聞こえます。

2
James Anderson

これは私のソリューションです...

/*
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

指定されたプロセスを監視する場合、通常はスクリプトによって実行されます。 Perlの例を次に示します。これはtopと同じようにパーセントを入れて、1つのCPUにスケーリングします。その後、2つのスレッドを処理するプロセスがアクティブになると、CPU使用率が100%を超える場合があります。 CPUコアがどのようにカウントされるかを特別に見てください: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=$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;
}

モニタリングに役立つことを願っています。もちろん、scanfまたは他のC関数を使用して、私が使用したPerl正規表現をCソースに変換する必要があります。もちろん、睡眠のための1秒は必須ではありません。いつでも使用できます。効果は、指定された期間に平均負荷を取得することです。監視に使用する場合、もちろん最後の値を外部に配置する必要があります。通常、監視はスクリプトを定期的に呼び出し、スクリプトはできるだけ早く作業を終了する必要があるため、これが必要です。

1
Znik

psacctまたはacctパッケージをインストールします。次に、saコマンドを使用して、さまざまなコマンドに使用されるCPU時間を表示します。 マニュアルページ

ニース howto nixCraftサイトから。

0
Lifeguard

これをprocから解析する代わりに、getrusage()やclock_gettime()などの関数を使用して、CPU使用率をCPUで使用されるプロセスまたはスレッドの比率またはウォールクロック時間と時間として計算できます。

0
ensonic

GNU "time"コマンドのソースコードを見る価値があると思います。 time 実際の経過時間とともにユーザー/システムCPU時間を出力します。 wait3/wait4システムコール(利用可能な場合)を呼び出し、それ以外の場合はtimesシステムコールを呼び出します。 wait *システムコールは「rusage」構造体変数を返し、システムコールが「tms」を返す回数を返します。また、非常に興味深いタイミング情報を返すgetrusageシステムコールを見ることができます。 時間

0
user3288728