免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4922 | 回复: 18
打印 上一主题 下一主题

[C] [求助]貌似得到的cpu使用率有问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-25 10:41 |只看该作者 |倒序浏览
最近在看《编程之美》这本书,是电子工业出版社broadview发行的,里面有msra的一道面试题:

1. 如何通过命令行参数,让cpu的使用率保持在任意位置,如90%?

2. 如何让cpu的使用率表现为一条正xuan曲线?

3. 如果你的电脑是双核的,那么你的程序会有什么样的结果?为什么?

我先做第1题,貌似得到的cpu(MacBook Intel Dule Core 2)使用率有问题,请大家看看哈

http://trac.lcuc.org.cn/public/t ... ul_code/cpu_usage.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <pthread.h>

#define PROC_STAT_FILE "/proc/stat"
#define DEFAULT_CPU_USAGE "50"

static int proc_stat_exists();
static double get_cpu_usage();
static void *get_cpu_usage_callback();
static void *set_cpu_usage_callback(void *usage);

static int
proc_stat_exists()
{
  struct stat buf;

  if (stat(PROC_STAT_FILE, &buf) < 0)
  {
    if (errno == ENOENT)
    {
      return 0;
    }
  }

  return 1;
}

static double
get_cpu_usage()
{
  double cur_usage = 0.00;
  double user1, nice1, system1, idle1;
  double user2, nice2, system2, idle2;
  FILE *stream = NULL;
  char *line = NULL;
  int line_counter;
  char *lineptr = NULL;
  size_t allocated_size = 0;
  size_t n = 0;
  char *token = NULL;
  const char *delim = " ";
  int token_counter;

  if (stream = fopen(PROC_STAT_FILE, "r"))
  {
    line_counter = 0;
    /* TODO: Get the first line of /proc/stat */
    while (getline(&lineptr, &n, stream) != -1 && !line_counter)
    {
      allocated_size = strlen(lineptr);
      if (line = (char *) malloc(allocated_size))
      {
        memset(line, 0, allocated_size);
        /* TODO: Get rid of '\0' at the end of line */
        if (index(line, '\0'))
        {
          strncpy(line, lineptr, allocated_size - 1);
        }
        else
        {
          line = lineptr;
        }
      }
      /* TODO: Get the user, nice, system and idle value */
      token = strtok(line, delim);
      token_counter = 0;
      while (token)
      {
        switch (token_counter)
        {
          case 1:
            user1 = (double) atoi(token);
            break;
          case 2:
            nice1 = (double) atoi(token);
            break;
          case 3:
            system1 = (double) atoi(token);
            break;
          case 4:
            idle1 = (double) atoi(token);
            break;
        }
        token = strtok(NULL, delim);
        token_counter++;
      }
      line_counter++;
      if (line)
      {
        free(line);
        line = NULL;
        lineptr = NULL;
      }
    }
  }
  if (stream)
  {
    fclose(stream);
    stream = NULL;
  }

  sleep(2);

  if (stream = fopen(PROC_STAT_FILE, "r"))
  {
    line_counter = 0;
    while (getline(&lineptr, &n, stream) != -1 && !line_counter)
    {
      allocated_size = strlen(lineptr);
      if (line = (char *) malloc(allocated_size))
      {
        memset(line, 0, allocated_size);
        if (index(line, '\0'))
        {
          strncpy(line, lineptr, allocated_size - 1);
        }
        else
        {
          line = lineptr;
        }
      }
      token = strtok(line, delim);
      token_counter = 0;
      while (token)
      {
        switch (token_counter)
        {
          case 1:
            user1 = (double) atoi(token);
            break;
          case 2:
            nice1 = (double) atoi(token);
            break;
          case 3:
            system1 = (double) atoi(token);
            break;
          case 4:
            idle1 = (double) atoi(token);
            break;
        }
        token = strtok(NULL, delim);
        token_counter++;
      }
      line_counter++;
      if (line)
      {
        free(line);
        line = NULL;
        lineptr = NULL;
      }
    }
  }
  if (stream)
  {
    fclose(stream);
    stream = NULL;
  }

  cur_usage = (user2 - user1) / (user2 + nice2 + system2 + idle2 - user1 - nice1 - system1 - idle1);

  return cur_usage;
}

static void *
get_cpu_usage_callback()
{
  printf("CPU usage is %.2f currently\n", get_cpu_usage());

  return NULL;
}

static void *
set_cpu_usage_callback(void *usage)
{
  double set_usage = (double) atoi(usage) / (double) 100;
  printf("try to restrict CPU usage to %.2f ...\n", set_usage);
  
  return NULL;
}

int
main(int argc, char **argv)
{
  extern char *optarg;
  int c;
  char *usage = DEFAULT_CPU_USAGE;
  pthread_t get_cpu_usage_thread;
  pthread_t set_cpu_usage_thread;
  
  if (!proc_stat_exists())
  {
    printf("proc/stat is not exists\n");

    return -1;
  }

  while ((c = getopt(argc, argv, "v:")) != -1)
  {
    switch (c)
    {
      case 'v':
        if (atoi(optarg) < 100 && atoi(optarg) > 0)
        {
          usage = optarg;
        }
        break;
    }
  }

  pthread_create(&get_cpu_usage_thread, NULL, get_cpu_usage_callback, NULL);
  pthread_create(&set_cpu_usage_thread, NULL, set_cpu_usage_callback, (void *) usage);
  pthread_join(get_cpu_usage_thread, NULL);
  pthread_join(set_cpu_usage_thread, NULL);

  return 0;
}

程序显示cpu user usage一直是3%,连我故意提高cpu负荷,它依旧3%

论坛徽章:
0
2 [报告]
发表于 2008-03-25 11:18 |只看该作者
Linux sirtoozee 2.6.22-gentoo-r5-mactel #18 SMP PREEMPT Sun Mar 9 21:05:42 CST 2008 i686 Intel(R) Core(TM)2 CPU T7200  @ 2.00GHz GenuineIntel GNU/Linux

大家不要光看,不在自己的机器上测试一下,帮我找找原因吧

论坛徽章:
0
3 [报告]
发表于 2008-03-25 11:24 |只看该作者
看不懂

论坛徽章:
0
4 [报告]
发表于 2008-03-25 11:28 |只看该作者
我是这么做的:
        jiff cpu_use[2] = {0}, cpu_nic[2], cpu_sys[2], cpu_idl[2], cpu_iow[2], cpu_xxx[2], cpu_yyy[2];
        jiff duse, dsys, didl, diow, Div, divo2;
        getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,cpu_iow+tog,cpu_xxx+tog,cpu_yyy+tog,
                        pgpgin+tog,pgpgout+tog,pswpin+tog,pswpout+tog,
                        intr+tog,ctxt+tog,
                        &running,&blocked,
                        &dummy_1,&dummy_2);

                duse= cpu_use[tog]-cpu_use[!tog] + cpu_nic[tog]-cpu_nic[!tog];
                dsys= cpu_sys[tog]-cpu_sys[!tog] + cpu_xxx[tog]-cpu_xxx[!tog] + cpu_yyy[tog]-cpu_yyy[!tog];
                didl= cpu_idl[tog]-cpu_idl[!tog];
                diow= cpu_iow[tog]-cpu_iow[!tog];

(unsigned)((100 * (dsys + duse + diow)) / Div) 这个算出来的就是百分比了。

论坛徽章:
0
5 [报告]
发表于 2008-03-25 13:57 |只看该作者
是不是我的公式有问题,我是参考的 http://bbs.chinaunix.net/archiver/?tid-629524.html

其中,oyjcq兄给出的公式user% = (user2 - user1)/(totle2 - totle1)

我本地cat /proc/stat的内容如下:
cpu  3873 0 1156 127623 8317 8 46 0
cpu0 2107 0 707 60816 6860 8 46 0
cpu1 1766 0 448 66806 1457 0 0 0
intr 166068 115348 0 0 0 0 0 0 0 57 4951 0 0 0 0 5927 0 18344 38 41 20014 1087 261 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 574895
btime 1206423754
processes 6463
procs_running 2
procs_blocked 0

那么,我实际上就是通过sleep(2)得到不同时间下,通过第1行cpu  3873 0 1156 127623 8317 8 46 0(user nice system idle iowait irq softirq)套用oyjcq兄给出的公式,大家帮忙看卡哈

论坛徽章:
0
6 [报告]
发表于 2008-03-25 14:02 |只看该作者
原帖由 cugb_cat 于 2008-3-25 11:28 发表
(unsigned)((100 * (dsys + duse + diow)) / Div) 这个算出来的就是百分比了。


版主的公式就和http://bbs.chinaunix.net/archiver/?tid-629524.html 讨论的不同,有可能是公式的问题?

还有Div的数值是多少呢?

论坛徽章:
0
7 [报告]
发表于 2008-03-25 14:06 |只看该作者
原帖由 涩兔子 于 2008-3-25 14:02 发表


版主的公式就和http://bbs.chinaunix.net/archiver/?tid-629524.html 讨论的不同,有可能是公式的问题?

还有Div的数值是多少呢?

Div= duse+dsys+didl+diow;

论坛徽章:
0
8 [报告]
发表于 2008-03-25 14:11 |只看该作者
dsys= cpu_sys[tog]-cpu_sys[!tog] + cpu_xxx[tog]-cpu_xxx[!tog] + cpu_yyy[tog]-cpu_yyy[!tog];


xxx 和 yyy是指的/proc/stat中第1行的哪2个数值呢?

我参考的是 http://www.linuxhowtos.org/System/procstat.htm

论坛徽章:
0
9 [报告]
发表于 2008-03-25 14:13 |只看该作者
原帖由 涩兔子 于 2008-3-25 14:11 发表


xxx 和 yyy是指的/proc/stat中第1行的哪2个数值呢?

我参考的是 http://www.linuxhowtos.org/System/procstat.htm

你看一下getstat函数。

论坛徽章:
0
10 [报告]
发表于 2008-03-25 16:18 |只看该作者
恩,谢谢版主,我去LOU LOU getstat的函数;

我心里想:是不是http://bbs.chinaunix.net/archiver/?tid-629524.html 讨论的是Linux kernel 2.4之前的,而2.6之后,/proc/stat的参数有变化的;

盼望有人给一个支持2.6 kernel的公式
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP