【目录】

不考虑其他进程,cpu画正弦曲线

获取总体cpu利用率

获取多核处理器单个cpu利用率

考虑其他进程,cpu画正弦曲线


下面的程序针对多核处理器,可以设置让任何一个cpu显示相应的曲线(本文以正弦曲线为例)

代码编译环境:windows 7 64位 酷睿 i5 处理器,vs2010.

可以修改CpuSin函数的计算 busySpan 和 idleSpan的部分以显示不同的曲线。

下面的代码没有考虑cpu中其他进程的占用情况,这种情况详见第二部分

 #include <windows.h>
#include <stdio.h>
#include <math.h> //把一条正弦曲线0~2pi 之间的弧度等分200份抽样,计算每个点的振幅
//然后每隔300ms设置下一个抽样点,并让cpu工作对应振幅时间
const int samplingCount = ; //抽样点数目
const double pi = 3.1415926;
const int totalAmplitude = ; //每个抽样点对应时间片
const double delta = 2.0/samplingCount; //抽样弧度的增量 int busySpan[samplingCount];//每个抽样点对应的busy时间
int idleSpan[samplingCount];//每个抽样点对应的idle时间 //一个线程调用MakeUsageSin,并把该线程绑定到一个cpu,那么该cpu呈现正弦曲线
DWORD WINAPI MakeUsageSin(LPVOID lpParameter)
{
DWORD startTime = ;
for(int j = ; ; j = (j + ) % samplingCount)
{
startTime = GetTickCount();
while ((GetTickCount() - startTime) < busySpan[j]);
Sleep(idleSpan[j]);
}
} //如果cpuindex < 0 则所有cpu都显示正弦曲线
//否则只有第 cpuindex个cpu显示正弦曲线
//cpuindex 从 0 开始计数
void CpuSin(int cpuIndex)
{
//计算 busySpan 和 idleSpan
double radian = ;
int amplitude = totalAmplitude / ;
for (int i = ; i < samplingCount; i++)
{
busySpan[i] = (DWORD)(amplitude + sin(pi*radian)*amplitude);
idleSpan[i] = totalAmplitude - busySpan[i];
radian += delta;
} //获取系统cup数量
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
int num_processors = SysInfo.dwNumberOfProcessors;
if(cpuIndex + > num_processors)
{
printf("error: the index of cpu is out of boundary\n");
printf("cpu number: %d\n", num_processors);
printf("your index: %d\n", cpuIndex);
printf("** tip: the index of cpu start from 0 **\n");
return;
} if(cpuIndex < )
{
HANDLE* threads = new HANDLE[num_processors];
for (int i = ;i < num_processors;i++)
{
DWORD mask = <<i;
threads[i] = CreateThread(NULL, , MakeUsageSin, &mask, , NULL);
SetThreadAffinityMask(threads[i], <<i);//线程指定在某个cpu运行
}
WaitForMultipleObjects(num_processors, threads, TRUE, INFINITE);
}
else
{
HANDLE thread;
DWORD mask = ;
thread = CreateThread(NULL, , MakeUsageSin, &mask, , NULL);
SetThreadAffinityMask(thread, <<cpuIndex);
WaitForSingleObject(thread,INFINITE);
} }
int main()
{ CpuSin();
return ;
}

运行结果:


下面我们考虑其他进程对cpu的影响,即需要检测出某个cpu当前的使用率。

首先对于单核处理器获取cpu利用率,或者多核处理器获取总的cpu利用率,可以通过windows api “GetSystemTimes” 来实现

该函数声明如下:BOOL GetSystemTimes(LPFILETIME  IdleTime,LPFILETIME   KernelTime,LPFILETIME   UserTime),具体可以参考msdn接口介绍

cpu利用率计算公式为:CPURate=100.0-(NowIdleTime-LastIdleTime)/(NowKernelTime-LastKernelTime+NowUserTime-LastUserTime)*100.0

计算总的cpu利用率或者单核处理器cpu利用率的类实现如下:

 class CCPUUseRate
{
public:
BOOL Initialize()
{
FILETIME ftIdle, ftKernel, ftUser;
BOOL flag = FALSE;
if (flag = GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
{
m_fOldCPUIdleTime = FileTimeToDouble(ftIdle);
m_fOldCPUKernelTime = FileTimeToDouble(ftKernel);
m_fOldCPUUserTime = FileTimeToDouble(ftUser); }
return flag;
}
//调用Initialize后要等待1左右秒再调用此函数
int GetCPUUseRate()
{
int nCPUUseRate = -;
FILETIME ftIdle, ftKernel, ftUser;
if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
{
double fCPUIdleTime = FileTimeToDouble(ftIdle);
double fCPUKernelTime = FileTimeToDouble(ftKernel);
double fCPUUserTime = FileTimeToDouble(ftUser);
nCPUUseRate= (int)(100.0 - (fCPUIdleTime - m_fOldCPUIdleTime)
/ (fCPUKernelTime - m_fOldCPUKernelTime + fCPUUserTime - m_fOldCPUUserTime)
*100.0);
m_fOldCPUIdleTime = fCPUIdleTime;
m_fOldCPUKernelTime = fCPUKernelTime;
m_fOldCPUUserTime = fCPUUserTime;
}
return nCPUUseRate;
}
private:
double FileTimeToDouble(FILETIME &filetime)
{
return (double)(filetime.dwHighDateTime * 4.294967296E9) + (double)filetime.dwLowDateTime;
}
private:
double m_fOldCPUIdleTime;
double m_fOldCPUKernelTime;
double m_fOldCPUUserTime;
};

注意:前后两次调用GetSystemTimes之间要间隔一定时间,使用方法如下:

 int main()
{
CCPUUseRate cpuUseRate;
if (!cpuUseRate.Initialize())
{
printf("Error! %d\n", GetLastError());
getch();
return -;
}
else
{
while (true)
{
Sleep();
printf("\r当前CPU使用率为:%4d%%", cpuUseRate.GetCPUUseRate());
}
}
return ;
}

对于计算多核处理器中单个cpu的使用率,可以使用pdh.h头文件中的接口,该头文件是visual studio自带的,包含该头文件时,还需要引入相关的lib库:

 #include <TCHAR.h>
#include <windows.h>
#include <pdh.h>
#include <cstdio>
#include <cmath>
#pragma comment(lib, "pdh.lib") //---------------------------------------------------comput the cpu usage rate
static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal; //cpuindex 为指定的cpu id ,从0开始
void init(int cpuIndex)
{
PDH_STATUS Status = PdhOpenQuery(NULL, NULL, &cpuQuery);
if (Status != ERROR_SUCCESS)
{
printf("\nPdhOpenQuery failed with status 0x%x.", Status);
exit(-);
}
char buf[];
sprintf(buf, "\\Processor(%d)\\%% Processor Time", cpuIndex);
PdhAddCounter(cpuQuery, LPCSTR(buf), NULL, &cpuTotal);
PdhCollectQueryData(cpuQuery);
} double getCpuUsageRate()
{
PDH_FMT_COUNTERVALUE counterVal;
PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
return counterVal.doubleValue;
}

注:该方法也可以计算总的cpu利用率,只要把PdhAddCounter的第二个字符串参数改为"\\Processor(_Total)\\%% Processor Time"

前后两次调用PdhCollectQueryData之间也需要间隔一定时间

使用方法如下:

 int main()
{
init();
while()
{
Sleep();
printf("\n%f\n", getCpuUsageRate());
}
}

利用上述方法获取cpu当前利用率后,再画正弦曲线,只需要改变进程的busy时间和idle时间,如果当前点曲线需要的cpu利用率是a%,cpu实际利用率是b%

若a>b, 那么进程的busy时间为该点时间片的(a-b)%

若a<=b,那么进程busy时间为0(实际情况中由于cpu使用率采集的不精确以及使用率的不断变化,busy时间设置为0效果不一定最好,本文中是设置为原来时间的3/4)

实际上除了当前进程外,如果cpu一直占用某个使用率,会影响曲线的形状,特别是曲线的下部分.

代码如下:

 #include <TCHAR.h>
#include <windows.h>
#include <pdh.h>
#include <cstdio>
#include <cmath>
#pragma comment(lib, "pdh.lib") //---------------------------------------------------comput the cpu usage rate
static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal; //cpuindex 为指定的cpu id ,从0开始
void init(int cpuIndex)
{
PDH_STATUS Status = PdhOpenQuery(NULL, NULL, &cpuQuery);
if (Status != ERROR_SUCCESS)
{
printf("\nPdhOpenQuery failed with status 0x%x.", Status);
exit(-);
}
char buf[];
sprintf(buf, "\\Processor(%d)\\%% Processor Time",cpuIndex);
PdhAddCounter(cpuQuery, LPCSTR(buf), NULL, &cpuTotal);
PdhCollectQueryData(cpuQuery);
} double getCpuUsageRate()
{
PDH_FMT_COUNTERVALUE counterVal;
PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
return counterVal.doubleValue;
} //--------------------------------------------------------------------cpu sin
//把一条正弦曲线0~2pi 之间的弧度等分200份抽样,计算每个点的振幅
//然后每隔300ms设置下一个抽样点,并让cpu工作对应振幅时间
const int samplingCount = ; //抽样点数目
const double pi = 3.1415926;
const int totalAmplitude = ; //每个抽样点对应时间片
const double delta = 2.0/samplingCount; //抽样弧度的增量 DWORD busySpan[samplingCount];//每个抽样点对应的busy时间
int idleSpan[samplingCount];//每个抽样点对应的idle时间 //一个线程调用MakeUsageSin,并把该线程绑定到一个cpu,那么该cpu呈现正弦曲线
DWORD WINAPI MakeUsageSin(LPVOID lpParameter)
{
DWORD startTime = ;
for(int j = ; ; j = (j + ) % samplingCount)
{
startTime = GetTickCount();
DWORD realBusy = busySpan[j]; double currentCpuUsageRate = getCpuUsageRate();
if(currentCpuUsageRate < busySpan[j]*1.0/totalAmplitude)
realBusy = (busySpan[j]*1.0/totalAmplitude - currentCpuUsageRate)*totalAmplitude;
else
realBusy *= 0.75; while ((GetTickCount() - startTime) < realBusy);
Sleep(idleSpan[j]);
}
} //如果cpuindex < 0 则所有cpu都显示正弦曲线
//否则只有第 cpuindex个cpu显示正弦曲线
//cpuindex 从 0 开始计数
void CpuSin(int cpuIndex)
{
//计算 busySpan 和 idleSpan
double radian = ;
int amplitude = totalAmplitude / ;
for (int i = ; i < samplingCount; i++)
{
busySpan[i] = (DWORD)(amplitude + sin(pi*radian)*amplitude);
idleSpan[i] = totalAmplitude - busySpan[i];
radian += delta;
} //获取系统cup数量
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
int num_processors = SysInfo.dwNumberOfProcessors;
if(cpuIndex + > num_processors)
{
printf("error: the index of cpu is out of boundary\n");
printf("cpu number: %d\n", num_processors);
printf("your index: %d\n", cpuIndex);
printf("** tip: the index of cpu start from 0 **\n");
return;
} if(cpuIndex < )
{
HANDLE* threads = new HANDLE[num_processors];
for (int i = ;i < num_processors;i++)
{
DWORD mask = <<i;
threads[i] = CreateThread(NULL, , MakeUsageSin, &mask, , NULL);
SetThreadAffinityMask(threads[i], <<i);//线程指定在某个cpu运行
}
WaitForMultipleObjects(num_processors, threads, TRUE, INFINITE);
}
else
{
init(cpuIndex);
HANDLE thread;
DWORD mask = ;
thread = CreateThread(NULL, , MakeUsageSin, &mask, , NULL);
SetThreadAffinityMask(thread, <<cpuIndex);
WaitForSingleObject(thread,INFINITE);
} }
//------------------------------------- int main()
{
CpuSin();
}

主要改动在MakeUsageSin函数,初始化在上面代码108行

结果如下:

【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3242910.html

编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器)的更多相关文章

  1. 编程之美_1.1 让CPU占用率曲线听你指挥

    听到有人说让要写一个程序,让用户来决定Windows任务管理器的CPU占用率. 觉得很好奇.但第一个想法就是写个死循环.哈哈.不知道具体的占用率是多少,但至少能保证在程序运行时,CPU的占用率终会稳定 ...

  2. 让cpu占用率曲线听你指挥(多核处理器)

    编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器) [版权声明]转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3242910.html  [目录] 不考 ...

  3. 第1章 游戏之乐——让CPU占用率曲线听你指挥

    让CPU占用率曲线听你指挥 写一个程序,让用于来决定Windows任务管理器(Task Manager)的CPU占用率.程序越精简越好,计算机语言不限.例如,可以实现下面三种情况: CPU的占用率固定 ...

  4. 1.1 让CPU占用率曲线听你指挥[cpu manager]

    [本文链接] http://www.cnblogs.com/hellogiser/p/cpu-manager.html [题目] 写一个程序,让用户来决定Windows任务管理器(Task Manag ...

  5. 让CPU占用率曲线听你指挥

    使用GetTickCount()和Sleep(): Code#include <stdio.h> #include <unistd.h> #include <time.h ...

  6. 编程之美读书笔记1.1——让CPU占用率曲线听你的指挥

    http://blog.csdn.net/pipisorry/article/details/36189155 <strong><span style="font-size ...

  7. 让CPU的占有率曲线听我指挥

    最近我要在公司的一个study group负责AWS的AutoScaling功能的介绍.AWS可以根据instance(虚拟机)的CPU使用量进行scaling. 为了做demo,于是就有这样一个需求 ...

  8. 控制CPU占用率曲线

    编程之美的第一个问题,我的机器是双核的,用文中的代码,得到的曲线波动比较大额,受其他进程的影响比较大.文中提到10ms接近windows的调度时间片,如果选得太小,会造成线程被频繁唤醒和挂起,造成内核 ...

  9. 编程之美 之 让CPU占用率听你指挥

    昨天在bbs上淘到了这本编程之美.顺手刷了第一章,很有意思.第一章的要求是要控制CPU曲线,绘制出对应的形状. 拿到这个问题,我的第一反应是, 是不是有这么一个API,能在任务管理器上的对应区域直接绘 ...

随机推荐

  1. 多个按钮触发同一个Bootstrap自适应模态窗口

    在项目中可能会面对这样的一个场景: 界面上有多个按钮,我们希望点击这些按钮弹出同一个模态窗口,但希望模态窗口的内容是动态生成的,即,点击每个按钮弹出的模态窗口内容不同. 通常情况下,一个按钮对应一个模 ...

  2. AutoMapper在MVC中的运用06-一次性定义映射、复杂类型属性映射

    本篇AutoMapper使用场景: ※ 当源和目标具有同名的复杂类型属性.集合类型属性,这2种属性对应的类间也需建立映射 ※ 一次性定义好源和目标的所有映射 ※ 一次性定义好源和目标的所有映射,目标中 ...

  3. Delphi XE5 android 获取网络状态《转》

    unit Androidapi.JNI.Network; interface function IsConnected: Boolean; function IsWiFiConnected: Bool ...

  4. rTorrent + ruTorrent 安装和配置

    原文地址:http://wangyan.org/blog/rtorrent-and-rutorrent-tutorial.html rTorrent 是一款非常简洁优秀的BT客户端,它完全基于文本并可 ...

  5. eval json ajax

    在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 使用eval函数来解析,并且使用jquery的ea ...

  6. Android按返回键退出程序但不销毁,程序后台运行,同QQ退出处理方式

    @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BA ...

  7. 云服务器 ECS Linux 系统安装图形化桌面 (centos7 ubuntu14)

    基于性能及通用性等因素,默认情况下,阿里云官方公共 Linux 系统镜像不会安装图形化桌面组件.本文简述了常用操作系统图形化桌面安装说明,您可以根据需求进行配置系统. 注意:图形化桌面可能会 显著降低 ...

  8. Adapter数据变化改变现有View的实现原理及案例

    首先说说Adapter详细的类的继承关系.例如以下图 Adapte为接口它的实现类的对象作为AdapterView和View的桥梁,Adapter是装载了View(比方ListView和girdVie ...

  9. whl文件(python)安装方法

    https://blog.csdn.net/fhl812432059/article/details/51745226 windows7 python2.7 1.用管理员方式打开cmd 2.首先通过p ...

  10. 从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" ...")中检测到有潜在危险的 Request.Form 值。

    ylbtech-Error-WebForm:从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" . ...