【发布时间】:2013-04-15 09:21:35
【问题描述】:
我想在我的程序中专门设置一个线程来收集有关其性能的指标。内存使用情况、CPU 等。我一直在尝试使用 /proc/stat 和 /proc/pid/stat 文件来执行此操作。我目前一直在尝试测量 %CPU 使用率。我的程序报告的值与“顶部”报告的值完全不一致。我在几个不同的 linux 发行版上试过这个,每个都看到相同的结果。
这是我用来计算百分比的代码。任何人都可以在这里发现任何问题吗?
https://github.com/mmcilroy/cpu_usage
#include <stdlib.h>
#include <sys/types.h>
#include <sys/times.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
struct pstat {
long unsigned int utime_ticks;
long int cutime_ticks;
long unsigned int stime_ticks;
long int cstime_ticks;
long unsigned int vsize; // virtual memory size in bytes
long unsigned int rss; //Resident Set Size in bytes
long unsigned int cpu_total_time;
};
int get_usage(const pid_t pid, struct pstat* result) {
//convert pid to string
char pid_s[20];
snprintf(pid_s, sizeof(pid_s), "%d", pid);
char stat_filepath[30] = "/proc/"; strncat(stat_filepath, pid_s,
sizeof(stat_filepath) - strlen(stat_filepath) -1);
strncat(stat_filepath, "/stat", sizeof(stat_filepath) -
strlen(stat_filepath) -1);
FILE *fpstat = fopen(stat_filepath, "r");
if (fpstat == NULL) {
perror("FOPEN ERROR ");
return -1;
}
FILE *fstat = fopen("/proc/stat", "r");
if (fstat == NULL) {
perror("FOPEN ERROR ");
fclose(fstat);
return -1;
}
//read values from /proc/pid/stat
bzero(result, sizeof(struct pstat));
long int rss;
if (fscanf(fpstat, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu"
"%lu %ld %ld %*d %*d %*d %*d %*u %lu %ld",
&result->utime_ticks, &result->stime_ticks,
&result->cutime_ticks, &result->cstime_ticks, &result->vsize,
&rss) == EOF) {
fclose(fpstat);
return -1;
}
fclose(fpstat);
result->rss = rss * getpagesize();
//read+calc cpu total time from /proc/stat
long unsigned int cpu_time[10];
bzero(cpu_time, sizeof(cpu_time));
if (fscanf(fstat, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
&cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3],
&cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7],
&cpu_time[8], &cpu_time[9]) == EOF) {
fclose(fstat);
return -1;
}
fclose(fstat);
for(int i=0; i < 4;i++)
result->cpu_total_time += cpu_time[i];
printf( "usage: cpu %lu, utime %lu, stime %lu\n", result->cpu_total_time, result->utime_ticks, result->stime_ticks );
return 0;
}
void calc_cpu_usage_pct(const struct pstat* cur_usage,
const struct pstat* last_usage,
double* usage)
{
printf( "delta: cpu %lu, utime %lu, stime %lu\n",
cur_usage->cpu_total_time - last_usage->cpu_total_time,
cur_usage->utime_ticks - last_usage->utime_ticks,
cur_usage->stime_ticks - last_usage->stime_ticks );
const long unsigned int cpu_diff = cur_usage->cpu_total_time - last_usage->cpu_total_time;
const long unsigned int pid_diff =
( cur_usage->utime_ticks + cur_usage->utime_ticks + cur_usage->stime_ticks - cur_usage->stime_ticks ) -
( last_usage->utime_ticks + last_usage->utime_ticks + last_usage->stime_ticks - last_usage->stime_ticks );
*usage = 100.0 * ( (double)pid_diff / (double)cpu_diff );
}
int main( int argc, char* argv[] )
{
pstat prev, curr;
double pct;
struct tms t;
times( &t );
if( argc <= 1 ) {
printf( "please supply a pid\n" ); return 1;
}
while( 1 )
{
if( get_usage(atoi(argv[1]), &prev) == -1 ) {
printf( "error\n" );
}
sleep( 5 );
if( get_usage(atoi(argv[1]), &curr) == -1 ) {
printf( "error\n" );
}
calc_cpu_usage_pct(&curr, &prev, &pct);
printf("%%cpu: %.02f\n", pct);
}
}
如果您想自己尝试一下,程序需要 1 个参数 - 要监控的进程的 pid
【问题讨论】:
-
因此,请发布您的直接进行计算的代码,而不是作为链接。肯定不会超过 30-40 行吧?
-
将 cur_usage->utime_ticks 表示为“a”,cur_usage->stime_ticks 表示为“b”,last_usage->utime_ticks 表示为“c”,last_usage->stime_ticks 表示为“d”。然后计算 pid_diff 为“(a+a+b-b) - (c+c+d-d)”,即 2a-2c。不确定是否应该考虑“b”和“d”,但这里的因素2不是可疑的吗?
-
是的,你是对的。这是代码中的错误。即使在我修复它之后仍然无法正常工作:)
-
你知道
getrusage(2)和times(2)吗?更便携和更容易访问。