如何从/proc/pid/stat 获得应用程序的总 CPU 使用量?

我想知道如何计算一个进程的总 CPU 使用量。

如果我做 cat /proc/pid/stat,我认为相关的字段是(摘自 lindevdoc.org) :

  1. 在用户代码中花费的 CPU 时间,以 jiffies 为单位
  2. CPU 在内核代码中花费的时间,以 jiffies 为单位
  3. CPU 时间花费在用户代码上,包括来自子代的时间
  4. 用于内核代码的 CPU 时间,包括来自子代的时间

所以总时间是14到17个字段之和吗?

114865 次浏览

是的,你可以这样说。你可以用公式把这些值转换成秒:

      sec = jiffies / HZ ; here - HZ = number of ticks per second

HZ 值是可配置的——在内核配置时完成。

准备工作

要计算特定进程的 CPU 使用量,您需要以下内容:

  1. /proc/uptime
    • 系统的 #1正常运行时间(秒)
  2. /proc/[PID]/stat
    • 在用户代码中花费的 CPU 时间,以 时钟滴答作响衡量
    • 在内核代码中花费的 CPU 时间,以 时钟滴答作响衡量
    • #16 cutime-等待-为儿童 CPU 在用户代码中花费的时间(在 时钟滴答作响中)
    • #17 cstime-等待-为儿童 CPU 在内核代码中花费的时间(在 时钟滴答作响中)
    • #22 starttime-进程开始的时间,以 时钟滴答作响测量
  3. 系统的赫兹(每秒钟的时钟滴答数)。

计算

首先,我们确定这个过程花费的总时间:

total_time = utime + stime

我们还必须决定是否要包含来自子进程的时间。如果我们这样做,那么我们将这些值添加到 total_time:

total_time = total_time + cutime + cstime

接下来,我们得到自进程开始以来在 几秒钟中运行的总时间:

seconds = uptime - (starttime / Hertz)

最后我们计算 CPU 使用率:

cpu_usage = 100 * ((total_time / Hertz) / seconds)

参见

Top 和 ps 不显示相同的 CPU 结果

如何在 Linux (c + +)中获得总的 CPU 使用量

计算 Linux 中进程的 CPU 使用率

如果需要计算过去10秒内进程使用了多少 CPU%

  1. 走开 Total _ time (13 + 14)(jiffies = > t1) 以 jiffies = > s1表示的起始时间(22)

延迟10秒

Total _ time (13 + 14)(jiffies = > t2) 以 jiffies = > s2表示的起始时间(22)

T2-t1 * 100/s2-s1 不会给% ? ?

这就是你要找的:

//USER_HZ detection, from openssl code
#ifndef HZ
# if defined(_SC_CLK_TCK) \
&& (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000)
#  define HZ ((double)sysconf(_SC_CLK_TCK))
# else
#  ifndef CLK_TCK
#   ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
#    define HZ  100.0
#   else /* _BSD_CLK_TCK_ */
#    define HZ ((double)_BSD_CLK_TCK_)
#   endif
#  else /* CLK_TCK */
#   define HZ ((double)CLK_TCK)
#  endif
# endif
#endif

这段代码实际上来自 心力衰竭,但是使用了 openssl 代码片段。

这是我得到我的应用程序的 CPU 使用量的另一种方法。我在 Android 中做了这个,它进行了一个内核 top 调用,并使用 top 返回的结果得到应用程序 PID 的 CPU 使用量。

public void myWonderfulApp()
{
// Some wonderfully written code here
Integer lMyProcessID = android.os.Process.myPid();
int lMyCPUUsage = getAppCPUUsage( lMyProcessID );
// More magic
}




// Alternate way that I switched to.  I found the first version was slower
// this version only returns a single line for the app, so far less parsing
// and processing.
public static float getTotalCPUUsage2()
{
try
{
// read global stats file for total CPU
BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
String[] sa = reader.readLine().split("[ ]+", 9);
long work = Long.parseLong(sa[1]) + Long.parseLong(sa[2]) + Long.parseLong(sa[3]);
long total = work + Long.parseLong(sa[4]) + Long.parseLong(sa[5]) + Long.parseLong(sa[6]) + Long.parseLong(sa[7]);
reader.close();


// calculate and convert to percentage
return restrictPercentage(work * 100 / (float) total);
}
catch (Exception ex)
{
Logger.e(Constants.TAG, "Unable to get Total CPU usage");
}


// if there was an issue, just return 0
return 0;
}


// This is an alternate way, but it takes the entire output of
// top, so there is a fair bit of parsing.
public static int getAppCPUUsage( Integer aAppPID)
{
int lReturn = 0;
// make sure a valid pid was passed
if ( null == aAppPID && aAppPID > 0)
{
return lReturn;
}


try
{
// Make a call to top so we have all the processes CPU
Process lTopProcess = Runtime.getRuntime().exec("top");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(lTopProcess.getInputStream()));


String lLine;


// While we have stuff to read and we have not found our PID, process the lines
while ( (lLine = bufferedReader.readLine()) != null )
{
// Split on 4, the CPU % is the 3rd field .
// NOTE: We trim because sometimes we had the first field in the split be a "".
String[] lSplit = lLine.trim().split("[ ]+", 4);


// Don't even bother if we don't have at least the 4
if ( lSplit.length > 3 )
{
// Make sure we can handle if we can't parse the int
try
{
// On the line that is our process, field 0 is a PID
Integer lCurrentPID = Integer.parseInt(lSplit[0]);


// Did we find our process?
if (aAppPID.equals(lCurrentPID))
{
// This is us, strip off the % and return it
String lCPU = lSplit[2].replace("%", "");


lReturn = Integer.parseInt(lCPU);
break;
}
}
catch( NumberFormatException e )
{
// No op.  We expect this when it's not a PID line
}
}
}


bufferedReader.close();
lTopProcess.destroy();      // Cleanup the process, otherwise you make a nice hand warmer out of your device


}
catch( IOException ex )
{
// Log bad stuff happened
}
catch (Exception ex)
{
// Log bad stuff happened
}


// if there was an issue, just return 0
return lReturn;
}

以下是我用 BASH编写的简单解决方案。它是一个通过 procfs 的 linux/unix 系统监视器和进程管理器,如“ 头儿”或“ 注意”。有两个版本的简单单色(快速)和彩色版本(有点慢,但特别有用的进程的统计监视)。我根据 CPU 使用量进行了排序。

Https://github.com/arakhachatryan/top

  • Utime Stime很好犯罪现场调查开始用于获取 CPU 使用情况,从 /proc/[ pid ]/stat文件中获取。

  • 状态 Pid优先权不错编号线程参数也是从 /proc/[ pid ]/stat文件中获得的。

  • 驻留 Data _ and _ stack参数,用于获取 内存使用情况并从 /proc/[ pid ]/statm文件获取。


function my_ps
{
pid_array=`ls /proc | grep -E '^[0-9]+$'`
clock_ticks=$(getconf CLK_TCK)
total_memory=$( grep -Po '(?<=MemTotal:\s{8})(\d+)' /proc/meminfo )


cat /dev/null > .data.ps


for pid in $pid_array
do
if [ -r /proc/$pid/stat ]
then
stat_array=( `sed -E 's/(\([^\s)]+)\s([^)]+\))/\1_\2/g' /proc/$pid/stat` )
uptime_array=( `cat /proc/uptime` )
statm_array=( `cat /proc/$pid/statm` )
comm=( `grep -Po '^[^\s\/]+' /proc/$pid/comm` )
user_id=$( grep -Po '(?<=Uid:\s)(\d+)' /proc/$pid/status )


user=$( id -nu $user_id )
uptime=${uptime_array[0]}


state=${stat_array[2]}
ppid=${stat_array[3]}
priority=${stat_array[17]}
nice=${stat_array[18]}


utime=${stat_array[13]}
stime=${stat_array[14]}
cutime=${stat_array[15]}
cstime=${stat_array[16]}
num_threads=${stat_array[19]}
starttime=${stat_array[21]}


total_time=$(( $utime + $stime ))
#add $cstime - CPU time spent in user and kernel code ( can olso add $cutime - CPU time spent in user code )
total_time=$(( $total_time + $cstime ))
seconds=$( awk 'BEGIN {print ( '$uptime' - ('$starttime' / '$clock_ticks') )}' )
cpu_usage=$( awk 'BEGIN {print ( 100 * (('$total_time' / '$clock_ticks') / '$seconds') )}' )


resident=${statm_array[1]}
data_and_stack=${statm_array[5]}
memory_usage=$( awk 'BEGIN {print( (('$resident' + '$data_and_stack' ) * 100) / '$total_memory'  )}' )


printf "%-6d %-6d %-10s %-4d %-5d %-4s %-4u %-7.2f %-7.2f %-18s\n" $pid $ppid $user $priority $nice $state $num_threads $memory_usage $cpu_usage $comm >> .data.ps


fi
done


clear
printf "\e[30;107m%-6s %-6s %-10s %-4s %-3s %-6s %-4s %-7s %-7s %-18s\e[0m\n" "PID" "PPID" "USER" "PR" "NI" "STATE" "THR" "%MEM" "%CPU" "COMMAND"
sort -nr -k9 .data.ps | head -$1
read_options
}


screenshot of working script