Linux 如何从 /proc/pid/stat 获取应用程序的总 CPU 使用率?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16726779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I get the total CPU usage of an application from /proc/pid/stat?
提问by
I was wondering how to calculate the total CPU usage of a process.
我想知道如何计算进程的总 CPU 使用率。
If I do cat /proc/pid/stat
, I think the relevant fields are (taken from lindevdoc.org):
如果我这样做,我认为相关领域是(取自 lindevdoc.org):cat /proc/pid/stat
- CPU time spent in user code, measured in jiffies
- CPU time spent in kernel code, measured in jiffies
- CPU time spent in user code, including time from children
- CPU time spent in kernel code, including time from children
- 在用户代码中花费的 CPU 时间,以 jiffies 为单位
- 在内核代码中花费的 CPU 时间,以 jiffies 为单位
- 在用户代码中花费的 CPU 时间,包括来自孩子的时间
- 在内核代码中花费的 CPU 时间,包括来自子进程的时间
So is the total time spend the sum of fields 14 to 17?
那么总时间是第 14 到 17 字段的总和吗?
采纳答案by Vilhelm Gray
Preparation
准备
To calculate CPU usage for a specific process you'll need the following:
要计算特定进程的 CPU 使用率,您需要以下内容:
/proc/uptime
#1
uptime of the system (seconds)
/proc/[PID]/stat
#14
utime
- CPU time spent in user code, measured in clock ticks#15
stime
- CPU time spent in kernel code, measured in clock ticks#16
cutime
- Waited-for children'sCPU time spent in user code (in clock ticks)#17
cstime
- Waited-for children'sCPU time spent in kernel code (in clock ticks)#22
starttime
- Time when the process started, measured in clock ticks
- Hertz (number of clock ticks per second) of your system.
- In most cases,
getconf CLK_TCK
can be used to return the number of clock ticks. - The
sysconf(_SC_CLK_TCK)
C function call may also be used to return the hertz value.
- In most cases,
/proc/uptime
#1
系统正常运行时间(秒)
/proc/[PID]/stat
#14
utime
- 在用户代码中花费的 CPU 时间,以时钟滴答为单位#15
stime
- 在内核代码中花费的 CPU 时间,以时钟滴答来衡量#16
cutime
-等待孩子在用户代码中花费的CPU 时间(以时钟滴答计)#17
cstime
-等待孩子在内核代码中花费的CPU 时间(以时钟滴答计)#22
starttime
- 进程开始的时间,以时钟滴答为单位
- 系统的赫兹(每秒时钟滴答数)。
- 大多数情况下,
getconf CLK_TCK
可用于返回时钟滴答数。 - 在
sysconf(_SC_CLK_TCK)
C函数调用也可以用来返回赫兹值。
- 大多数情况下,
Calculation
计算
First we determine the total time spent for the process:
首先我们确定流程花费的总时间:
total_time = utime + stime
We also have to decide whether we want to include the time from children processes. If we do, then we add those values to total_time
:
我们还必须决定是否要包括子进程的时间。如果我们这样做,那么我们将这些值添加到total_time
:
total_time = total_time + cutime + cstime
Next we get the total elapsed time in secondssince the process started:
接下来我们得到自进程开始以来经过的总时间(以秒为单位):
seconds = uptime - (starttime / Hertz)
Finally we calculate the CPU usage percentage:
最后我们计算CPU使用率:
cpu_usage = 100 * ((total_time / Hertz) / seconds)
See also
也可以看看
Top and ps not showing the same cpu result
回答by rakib_
Yes, you can say so. You can convert those values into seconds using formula:
是的,你可以这么说。您可以使用公式将这些值转换为秒:
sec = jiffies / HZ ; here - HZ = number of ticks per second
HZ value is configurable - done at kernel configuration time.
HZ 值是可配置的 - 在内核配置时完成。
回答by Vilhelm Gray
If need to calculate how much cpu% used by a process in last 10 secs
如果需要计算一个进程在过去 10 秒内使用了多少 cpu%
- get total_time (13+14) in jiffies => t1 starttime(22) in jiffies => s1
- 在 jiffies 中获得 total_time (13+14) => t1 starttime(22) 在 jiffies => s1
--delay of 10 secs
--延迟10秒
total_time (13+14) in jiffies => t2 starttime(22) in jiffies => s2
jiffies 中的 total_time (13+14) => jiffies 中的 t2 starttime(22) => s2
t2-t1 *100 / s2 - s1 wouldnt give the % ??
t2-t1 *100 / s2 - s1 不会给出 % ??
回答by Savio Sena
Here's what you're looking for:
这就是你要找的:
//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
This code is actually from cpulimit, but uses openssl snippets.
这段代码实际上来自cpulimit,但使用了 openssl 片段。
回答by GR Envoy
Here is another way that I got my App's CPU usage. I did this in Android, and it makes a kernel top call and gets the CPU usage for your apps PID using what top returns.
这是我获取应用程序 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;
}
回答by Ara
Here is my simple solution written in BASH. It is a linux/unix system monitor and process manager through procfs, like "top" or "ps". There is two versions simple monochrome(fast) and colored version(little bit slow, but useful especially for monitoring the statе of processes). I made sorting by CPU usage.
这是我用BASH编写的简单解决方案。它是一个通过 procfs 的 linux/unix 系统监视器和进程管理器,如“ top”或“ ps”。有两个版本,简单的单色(快速)和彩色版本(有点慢,但对于监控进程状态特别有用)。我按 CPU 使用率排序。
https://github.com/AraKhachatryan/top
https://github.com/AraKhachatryan/top
utime, stime, cutime, cstime, starttimeused for getting cpu usageand obtained from /proc/[pid]/statfile.
state, ppid, priority, nice, num_threadsparameters obtained also from /proc/[pid]/statfile.
residentand data_and_stackparameters used for getting memory usageand obtained from /proc/[pid]/statmfile.
utime、stime、cutime、cstime、starttime用于获取CPU 使用率并从/proc/[pid]/stat文件中获取。
state, ppid, priority, nice, num_threads参数也从/proc/[pid]/stat文件中获得。
resident和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([^)]+\))/_/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 -
read_options
}