请教:获得多任务实时操作系统的CPU使用率的原理是什么?

xueyingyt2008 2005-11-14 05:04:56
如以下程序,IDLE时间是怎样计算的?

//C++:实时获取CPU使用率的类(源码) 出处:www.csdn.net

//=========================================================
//
// Copyright (c) 2000-2004 iWise Technologies,Co. Ltd.
// All Rights Reserved.
//
// Product: iW988
// File: CpuUsage.h
// Created: 天衣有缝
//
// Description:
// ValueAdded main program for iW988.
// Contact:
// waterpub@mail.csdn.net
//
//=========================================================

#pragma once

#define SystemBasicInformation 0
#define SystemPerformanceInformation 2
#define SystemTimeInformation 3

#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))

class CCpuUsage
{
public:
CCpuUsage();
~CCpuUsage();

public:
int GetCpuUsage(); //得到系统cpu利用率
int SetRefreshInterval(int milli_sec); //定时刷新间隔

private:
//类型定义
typedef LONG (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG);

typedef struct
{
DWORD dwUnknown1;
ULONG uKeMaximumIncrement;
ULONG uPageSize;
ULONG uMmNumberOfPhysicalPages;
ULONG uMmLowestPhysicalPage;
ULONG uMmHighestPhysicalPage;
ULONG uAllocationGranularity;
PVOID pLowestUserAddress;
PVOID pMmHighestUserAddress;
ULONG uKeActiveProcessors;
BYTE bKeNumberProcessors;
BYTE bUnknown2;
WORD wUnknown3;
} SYSTEM_BASIC_INFORMATION;

typedef struct
{
LARGE_INTEGER liIdleTime;
DWORD dwSpare[76];
} SYSTEM_PERFORMANCE_INFORMATION;

typedef struct
{
LARGE_INTEGER liKeBootTime;
LARGE_INTEGER liKeSystemTime;
LARGE_INTEGER liExpTimeZoneBias;
ULONG uCurrentTimeZoneId;
DWORD dwReserved;
} SYSTEM_TIME_INFORMATION;

//变量定义
SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
SYSTEM_TIME_INFORMATION SysTimeInfo;
SYSTEM_BASIC_INFORMATION SysBaseInfo;

double dbIdleTime;
double dbSystemTime;

LONG status;

LARGE_INTEGER liOldIdleTime;
LARGE_INTEGER liOldSystemTime;

PROCNTQSI NtQuerySystemInformation;

int m_nCpuUsage;

//定时
HWND m_hWnd;
int m_nRefreshInterval;//默认为1000毫秒
int m_nTimerID;

private:
static void CalcCpuUsage(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
int OnTimer();
};

inline CCpuUsage::CCpuUsage()
{
//
m_hWnd = NULL;
m_nRefreshInterval = 1000;
m_nTimerID = 1000;
m_nCpuUsage = 0;

//
memset(&liOldIdleTime , 0, sizeof(LARGE_INTEGER));
memset(&liOldSystemTime, 0, sizeof(LARGE_INTEGER));

//
NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
GetModuleHandle("ntdll") , "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
return;

// get number of processors in the system
status = NtQuerySystemInformation(SystemBasicInformation,&SysBaseInfo,sizeof(SysBaseInfo),NULL);
if (status != NO_ERROR)
return;

// create control for timer
m_hWnd = ::CreateWindow("static", "", 0, 0, 0, 0, 0, NULL, NULL, 0, NULL);
::SetWindowLong(m_hWnd , GWL_USERDATA , (long)(this) );

TIMERPROC tp = (TIMERPROC)CalcCpuUsage;
SetTimer(m_hWnd , m_nTimerID, m_nRefreshInterval, tp);

}

inline CCpuUsage::~CCpuUsage()
{
KillTimer(m_hWnd , m_nTimerID);
DestroyWindow(m_hWnd);
}

inline void CCpuUsage::CalcCpuUsage(
HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
)
{
CCpuUsage* pCpu = (CCpuUsage*)::GetWindowLong(hwnd , GWL_USERDATA);

if ( pCpu )
{
pCpu->OnTimer();
}

}

inline int CCpuUsage::OnTimer()
{
status = NtQuerySystemInformation(SystemTimeInformation,&SysTimeInfo,sizeof(SysTimeInfo),0);

if (status!=NO_ERROR)
return 0;

// get new CPU's idle time
status = NtQuerySystemInformation(SystemPerformanceInformation,&SysPerfInfo,sizeof(SysPerfInfo),NULL);
if (status != NO_ERROR)
return 0;

// if it's a first call - skip it
if (liOldIdleTime.QuadPart != 0)
{
// CurrentValue = NewValue - OldValue
dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);

// CurrentCpuIdle = IdleTime / SystemTime
dbIdleTime = dbIdleTime / dbSystemTime;

// CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;

m_nCpuUsage = (UINT)dbIdleTime;
}

// store new CPU's idle and system time
liOldIdleTime = SysPerfInfo.liIdleTime;
liOldSystemTime = SysTimeInfo.liKeSystemTime;

// wait one second

return 0;
}

inline int CCpuUsage::GetCpuUsage()
{
return m_nCpuUsage;
}

inline int CCpuUsage::SetRefreshInterval(int milli_sec)
{
m_nRefreshInterval = milli_sec;

if ( m_hWnd )
{
TIMERPROC tp = (TIMERPROC)CalcCpuUsage;
SetTimer(m_hWnd, m_nTimerID, m_nRefreshInterval ,tp);
}

return 0;

}

...全文
612 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
big_chen 2005-12-06
  • 打赏
  • 举报
回复
LINUX系统的调度和WINDOWS一样么?
嵌入式的呢?
要走嵌入式特色的路线,必须符合嵌入式的情况,要避免一刀切!
xueyingyt2008 2005-11-22
  • 打赏
  • 举报
回复
看来只有我自己努力了
jixingzhong 2005-11-17
  • 打赏
  • 举报
回复
MARK ~

没有研究过这方面的东东 ~
555 ...
只有帮顶了 ~
x86 2005-11-16
  • 打赏
  • 举报
回复
psos没用过,如果是类似UNIX的系统,你可以考虑读proc文件,一般在/proc目录下每个进程有个以进程号为名字的目录,之下有个stat文件,可以得到一些进程信息。
如果是专用的OS,跟unix一点关系也没有,那只能研究它的文档了。
xueyingyt2008 2005-11-16
  • 打赏
  • 举报
回复
是psos
x86 2005-11-15
  • 打赏
  • 举报
回复
嵌入式?
linux的话, 可以用ps -eo "%p %C"得到所有进程的进程号和cpu使用率, 可以看看ps的源码了解它是怎么得到cpu使用率的.
xueyingyt2008 2005-11-15
  • 打赏
  • 举报
回复
我不是在windows下写,而是在嵌入式操作系统中
Cantonese00 2005-11-14
  • 打赏
  • 举报
回复
mark
帮LZ顶上去...
没学得这么多,只能这样帮忙了
=_='
x86 2005-11-14
  • 打赏
  • 举报
回复
你摘得代码调用的是windows的系统调用, 看不出实际干了些什么.
可以参考一下linux的CPU load average, 假设某一时刻load average是
load average: 8.13, 5.90, 4.94
表示在过去的1、5、15分钟内运行队列中的平均进程数量(注意, 不是CPU活动百分比).
cpu的真实使用率可以通过运行在其上的进程数及进程的活跃程度来判定, 单位时间内活跃的进程越多表示CPU越繁忙. 因为活跃的进程肯定是要被系统调度的, 也就是会在CPU上运行的.

对于windows, 可以简单理解为某个进程在单位时间内占用CPU时间片的比例, 这个值是系统的进程调度可以知道的.
code8238 2005-11-14
  • 打赏
  • 举报
回复
NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
GetModuleHandle("ntdll") , "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
return;

ntdll.dll文件中有个NtQuerySystemInformation函数,应该是没公开的api,网上有用法!

19,503

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧