CからLinuxでPIDを使用してプロセスのCPU使用率を計算する方法


94

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

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

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

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

topの出力を取得(grep-ing)するのはどうですか?
dusoft 2009

本当に厥ない効率的に行うための最善の方法であり、y
codingfreak

'top'を開始するには、おそらく「高価な」システムコールが必要です。
Liran Orevi 09/09/14

@Liran:正しく言った:)
vpram86

物事のこの方法を忘れて.... in C
コーディングフリーク

回答:


148

からのデータを解析する必要があり/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

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

両方を読むutimeと、stimeプロセスのためにあなたが興味を持っている、と読んで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);

理にかなっていますか?


11
「jiffy」はCPU時間の単位です。実時間で正確に何が対応するかは、アーキテクチャとカーネルの構成方法によって異なりますが、重要なことは/proc/stat、CPUが合計で実行したjiffyの数と、CPUが実行した/proc/<PID>/statjiffyの数を示します。単一のプロセス。
ca 09/09/15

1
@advocate:カーネルからプロセス実行統計を取得するためのインターフェースを実装する疑似ファイルです。
カフェ

4
フィールドに関する詳細情報を求める人へ:man procあなたの友達(で検索/proc/[pid]/stat
redShadow 2013年

1
cafのソリューションとzizzu(以下)が提供するソリューションを比較すると、cafのソリューションはシステム時間とユーザー時間を別々に提供しますが、これらの値のいずれかとCPUの数を乗算しません。それはそれをすべきではないのですか?
linuxfan 2016年

2
どうやらOPは同意しなかった。ここで重要な洞察は使用することがある/proc擬似ファイルシステム:のような標準のCファイルシステムへのアクセス機能の指導をfopen()し、scanf()ポイントの横にあります。
caf

11

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

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

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

(プロセッサが多い場合はさらに複雑になる可能性があります)


2
getrusage()システムコールは、プロセスのCPU使用率を計算するのにどのように役立ちますか?
コーディングフリーク

@codingfreak。私は質問を誤解しました。更新した後、クリアします。
vpram86 2009

1
@Aviator CPU%=(processusertime + processkerneltime)/(CPUusertime + CPUkerneltime)「processusertime」などの値を取得するにはどうすればよいですか。??? 「/ proc / PID / stat」ファイルにさまざまな値が表示されます。それで、どれがどの値に対応しますか?
codeingfreak 2009

@codingfreak:CPU時間の計算は困難です。UはすべてのPID統計をループする必要があります(確かではありません)
vpram86

@Aviatorいくつかの方法があるだろうか、トップのようにもアプリケーションが出力に表示するCPU使用率を計算する必要がありますので、...それを行うために、他の
codingfreak

6

私のような初心者のための簡単なステップ:

  1. 最初の行読んで/proc/stat取得するがtotal_cpu_usage1
    sscanf(line,"%*s %llu %llu %llu %llu",&user,&nice,&system,&idle);
    total_cpu_usage1 = user + nice + system + idle;
  1. 次のように、CPU使用率を知りたいプロセスのPIDが/proc/pid/statどこに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
    ....)
  1. 合計usertimesystemtimeて取得するproc_times1
  2. 1秒以上待つ
  3. もう一度やって、入手total_cpu_usage2してproc_times2

式は次のとおりです。

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

CPUの量はから取得できます/proc/cpuinfo


2
あなたのソリューションは良いですが、CPUの数を取得するには、それをより単純にします。この人#include <unistd.h>を含めてこのメソッドを呼び出しますint nb = sysconf(_SC_NPROCESSORS_ONLN);
David Guyon

1
delta(proc_times)がそれが実行されたコアのものであると仮定して、なぜ(プロセッサ数)を掛けるのかわかりません。係数またはCPUを掛けないで、それは正しいはずです。
JayabalanAaron 2017年

5

プロセスのuser + kernel cpu使用量を計算するために、cafsの回答に基づいて2つの小さなC関数を記述しました:https : //github.com/fho/code_snippets/blob/master/c/getusage.c


コンパイル中にエラーが発生するため、コンパイルされたバージョンがありますか?また、どのように使用できますか?
メドハット2014年

私にはmain()関数がないので、コンパイルして実行できるのは「スタンドアロン」プログラムではありません。getusage.cの関数でいくつかのことを行うmain()関数を作成する必要があります
fho

実際にはC関数を使用していません。コマンド出力を解析するために任意の言語を使用するだけです。
グラハム、

4

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

すべてのフィールドとそのscanf形式指定子は、proc manpag eに記載されています。

コピーされたマンページからの情報の一部を次に示します(非常に長い):

          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.

「CPU使用率」と「現在の状態」は、位置と速度のようなものです。片方を知っているともう片方を知ることができません。CPU使用率は継続時間に依存するため、プロセスが「R」状態にある頻度を自分で確認する必要があります。
ボンベ

うーん、良い質問です。いつもそこにあると思っていました。おそらく、これらの変数から計算できるはずです
Andre Miller

あなたはtopコマンドの出力をチェックする場合は、CPU使用率を見ることができます....私は計算CPUの使用率を最出力を通じてgrepingにintrestedていないです.....
codingfreak

@codingfreak:ps aux優れています:)
vpram86

@Aviator-CPU使用率%を決定するためにシェルコマンドの出力をgrepすることを忘れるように私はすでにuに言っています
codeingfreak


2

これが私の解決策です...

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

1
libgtopライブラリのヘルプを使用しているようです。
codingfreak

1
私はこれが好きです-ライブラリは簡単です。総容量の何パーセントが総使用量であるかを確認する方法はあるのでしょうか。
Cera

1

特定のプロセスを監視する場合、通常はスクリプトによって行われます。これは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;
}

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


0

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

nixCraftサイトからの素晴らしいハウツー


0

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


GNU "time"は "time"の子プロセスのみを対象としています
Graham

0

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


getrusage clock_gettimeは制限されており、すべてのプロセスが対象ではありません
Graham

0

straceを使用して、CPU使用率を期間ごとに計算する必要があることがわかりました。

# 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
.
.
.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.