【目錄】html
不考慮其餘進程,cpu畫正弦曲線windows
獲取整體cpu利用率api
下面的程序針對多核處理器,能夠設置讓任何一個cpu顯示相應的曲線(本文以正弦曲線爲例)spa
代碼編譯環境:windows 7 64位 酷睿 i5 處理器,vs2010.線程
能夠修改CpuSin函數的計算 busySpan 和 idleSpan的部分以顯示不一樣的曲線。code
下面的代碼沒有考慮cpu中其餘進程的佔用狀況,這種狀況詳見第二部分orm
1 #include <windows.h> 2 #include <stdio.h> 3 #include <math.h> 4 5 //把一條正弦曲線0~2pi 之間的弧度等分200份抽樣,計算每一個點的振幅 6 //而後每隔300ms設置下一個抽樣點,並讓cpu工做對應振幅時間 7 const int samplingCount = 200; //抽樣點數目 8 const double pi = 3.1415926; 9 const int totalAmplitude = 300; //每一個抽樣點對應時間片 10 const double delta = 2.0/samplingCount; //抽樣弧度的增量 11 12 int busySpan[samplingCount];//每一個抽樣點對應的busy時間 13 int idleSpan[samplingCount];//每一個抽樣點對應的idle時間 14 15 //一個線程調用MakeUsageSin,並把該線程綁定到一個cpu,那麼該cpu呈現正弦曲線 16 DWORD WINAPI MakeUsageSin(LPVOID lpParameter) 17 { 18 DWORD startTime = 0; 19 for(int j = 0; ; j = (j + 1) % samplingCount) 20 { 21 startTime = GetTickCount(); 22 while ((GetTickCount() - startTime) < busySpan[j]); 23 Sleep(idleSpan[j]); 24 } 25 } 26 27 //若是cpuindex < 0 則全部cpu都顯示正弦曲線 28 //不然只有第 cpuindex個cpu顯示正弦曲線 29 //cpuindex 從 0 開始計數 30 void CpuSin(int cpuIndex) 31 { 32 //計算 busySpan 和 idleSpan 33 double radian = 0; 34 int amplitude = totalAmplitude / 2; 35 for (int i = 0; i < samplingCount; i++) 36 { 37 busySpan[i] = (DWORD)(amplitude + sin(pi*radian)*amplitude); 38 idleSpan[i] = totalAmplitude - busySpan[i]; 39 radian += delta; 40 } 41 42 //獲取系統cup數量 43 SYSTEM_INFO SysInfo; 44 GetSystemInfo(&SysInfo); 45 int num_processors = SysInfo.dwNumberOfProcessors; 46 if(cpuIndex + 1 > num_processors) 47 { 48 printf("error: the index of cpu is out of boundary\n"); 49 printf("cpu number: %d\n", num_processors); 50 printf("your index: %d\n", cpuIndex); 51 printf("** tip: the index of cpu start from 0 **\n"); 52 return; 53 } 54 55 if(cpuIndex < 0) 56 { 57 HANDLE* threads = new HANDLE[num_processors]; 58 for (int i = 0;i < num_processors;i++) 59 { 60 DWORD mask = 1<<i; 61 threads[i] = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL); 62 SetThreadAffinityMask(threads[i], 1<<i);//線程指定在某個cpu運行 63 } 64 WaitForMultipleObjects(num_processors, threads, TRUE, INFINITE); 65 } 66 else 67 { 68 HANDLE thread; 69 DWORD mask = 1; 70 thread = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL); 71 SetThreadAffinityMask(thread, 1<<cpuIndex); 72 WaitForSingleObject(thread,INFINITE); 73 } 74 75 } 76 int main() 77 { 78 79 CpuSin(0); 80 return 0; 81 }
運行結果:htm
下面咱們考慮其餘進程對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利用率的類實現以下:
1 class CCPUUseRate 2 { 3 public: 4 BOOL Initialize() 5 { 6 FILETIME ftIdle, ftKernel, ftUser; 7 BOOL flag = FALSE; 8 if (flag = GetSystemTimes(&ftIdle, &ftKernel, &ftUser)) 9 { 10 m_fOldCPUIdleTime = FileTimeToDouble(ftIdle); 11 m_fOldCPUKernelTime = FileTimeToDouble(ftKernel); 12 m_fOldCPUUserTime = FileTimeToDouble(ftUser); 13 14 } 15 return flag; 16 } 17 //調用Initialize後要等待1左右秒再調用此函數 18 int GetCPUUseRate() 19 { 20 int nCPUUseRate = -1; 21 FILETIME ftIdle, ftKernel, ftUser; 22 if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser)) 23 { 24 double fCPUIdleTime = FileTimeToDouble(ftIdle); 25 double fCPUKernelTime = FileTimeToDouble(ftKernel); 26 double fCPUUserTime = FileTimeToDouble(ftUser); 27 nCPUUseRate= (int)(100.0 - (fCPUIdleTime - m_fOldCPUIdleTime) 28 / (fCPUKernelTime - m_fOldCPUKernelTime + fCPUUserTime - m_fOldCPUUserTime) 29 *100.0); 30 m_fOldCPUIdleTime = fCPUIdleTime; 31 m_fOldCPUKernelTime = fCPUKernelTime; 32 m_fOldCPUUserTime = fCPUUserTime; 33 } 34 return nCPUUseRate; 35 } 36 private: 37 double FileTimeToDouble(FILETIME &filetime) 38 { 39 return (double)(filetime.dwHighDateTime * 4.294967296E9) + (double)filetime.dwLowDateTime; 40 } 41 private: 42 double m_fOldCPUIdleTime; 43 double m_fOldCPUKernelTime; 44 double m_fOldCPUUserTime; 45 };
注意:先後兩次調用GetSystemTimes之間要間隔必定時間,使用方法以下:
1 int main() 2 { 3 CCPUUseRate cpuUseRate; 4 if (!cpuUseRate.Initialize()) 5 { 6 printf("Error! %d\n", GetLastError()); 7 getch(); 8 return -1; 9 } 10 else 11 { 12 while (true) 13 { 14 Sleep(1000); 15 printf("\r當前CPU使用率爲:%4d%%", cpuUseRate.GetCPUUseRate()); 16 } 17 } 18 return 0; 19 }
對於計算多核處理器中單個cpu的使用率,可使用pdh.h頭文件中的接口,該頭文件是visual studio自帶的,包含該頭文件時,還須要引入相關的lib庫:
1 #include <TCHAR.h> 2 #include <windows.h> 3 #include <pdh.h> 4 #include <cstdio> 5 #include <cmath> 6 #pragma comment(lib, "pdh.lib") 7 8 //---------------------------------------------------comput the cpu usage rate 9 static PDH_HQUERY cpuQuery; 10 static PDH_HCOUNTER cpuTotal; 11 12 //cpuindex 爲指定的cpu id ,從0開始 13 void init(int cpuIndex) 14 { 15 PDH_STATUS Status = PdhOpenQuery(NULL, NULL, &cpuQuery); 16 if (Status != ERROR_SUCCESS) 17 { 18 printf("\nPdhOpenQuery failed with status 0x%x.", Status); 19 exit(-1); 20 } 21 char buf[50]; 22 sprintf(buf, "\\Processor(%d)\\%% Processor Time", cpuIndex); 23 PdhAddCounter(cpuQuery, LPCSTR(buf), NULL, &cpuTotal); 24 PdhCollectQueryData(cpuQuery); 25 } 26 27 28 double getCpuUsageRate() 29 { 30 PDH_FMT_COUNTERVALUE counterVal; 31 PdhCollectQueryData(cpuQuery); 32 PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal); 33 return counterVal.doubleValue; 34 }
注:該方法也能夠計算總的cpu利用率,只要把PdhAddCounter的第二個字符串參數改成"\\Processor(_Total)\\%% Processor Time"
先後兩次調用PdhCollectQueryData之間也須要間隔必定時間
使用方法以下:
1 int main() 2 { 3 init(0); 4 while(1) 5 { 6 Sleep(800); 7 printf("\n%f\n", getCpuUsageRate()); 8 } 9 }
利用上述方法獲取cpu當前利用率後,再畫正弦曲線,只須要改變進程的busy時間和idle時間,若是當前點曲線須要的cpu利用率是a%,cpu實際利用率是b%
若a>b, 那麼進程的busy時間爲該點時間片的(a-b)%
若a<=b,那麼進程busy時間爲0(實際狀況中因爲cpu使用率採集的不精確以及使用率的不斷變化,busy時間設置爲0效果不必定最好,本文中是設置爲原來時間的3/4)
實際上除了當前進程外,若是cpu一直佔用某個使用率,會影響曲線的形狀,特別是曲線的下部分.
代碼以下:
1 #include <TCHAR.h> 2 #include <windows.h> 3 #include <pdh.h> 4 #include <cstdio> 5 #include <cmath> 6 #pragma comment(lib, "pdh.lib") 7 8 //---------------------------------------------------comput the cpu usage rate 9 static PDH_HQUERY cpuQuery; 10 static PDH_HCOUNTER cpuTotal; 11 12 //cpuindex 爲指定的cpu id ,從0開始 13 void init(int cpuIndex) 14 { 15 PDH_STATUS Status = PdhOpenQuery(NULL, NULL, &cpuQuery); 16 if (Status != ERROR_SUCCESS) 17 { 18 printf("\nPdhOpenQuery failed with status 0x%x.", Status); 19 exit(-1); 20 } 21 char buf[50]; 22 sprintf(buf, "\\Processor(%d)\\%% Processor Time",cpuIndex); 23 PdhAddCounter(cpuQuery, LPCSTR(buf), NULL, &cpuTotal); 24 PdhCollectQueryData(cpuQuery); 25 } 26 27 28 double getCpuUsageRate() 29 { 30 PDH_FMT_COUNTERVALUE counterVal; 31 PdhCollectQueryData(cpuQuery); 32 PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal); 33 return counterVal.doubleValue; 34 } 35 36 //--------------------------------------------------------------------cpu sin 37 //把一條正弦曲線0~2pi 之間的弧度等分200份抽樣,計算每一個點的振幅 38 //而後每隔300ms設置下一個抽樣點,並讓cpu工做對應振幅時間 39 const int samplingCount = 200; //抽樣點數目 40 const double pi = 3.1415926; 41 const int totalAmplitude = 300; //每一個抽樣點對應時間片 42 const double delta = 2.0/samplingCount; //抽樣弧度的增量 43 44 DWORD busySpan[samplingCount];//每一個抽樣點對應的busy時間 45 int idleSpan[samplingCount];//每一個抽樣點對應的idle時間 46 47 //一個線程調用MakeUsageSin,並把該線程綁定到一個cpu,那麼該cpu呈現正弦曲線 48 DWORD WINAPI MakeUsageSin(LPVOID lpParameter) 49 { 50 DWORD startTime = 0; 51 for(int j = 0; ; j = (j + 1) % samplingCount) 52 { 53 startTime = GetTickCount(); 54 DWORD realBusy = busySpan[j]; 55 56 double currentCpuUsageRate = getCpuUsageRate(); 57 if(currentCpuUsageRate < busySpan[j]*1.0/totalAmplitude) 58 realBusy = (busySpan[j]*1.0/totalAmplitude - currentCpuUsageRate)*totalAmplitude; 59 else 60 realBusy *= 0.75; 61 62 while ((GetTickCount() - startTime) < realBusy); 63 Sleep(idleSpan[j]); 64 } 65 } 66 67 //若是cpuindex < 0 則全部cpu都顯示正弦曲線 68 //不然只有第 cpuindex個cpu顯示正弦曲線 69 //cpuindex 從 0 開始計數 70 void CpuSin(int cpuIndex) 71 { 72 //計算 busySpan 和 idleSpan 73 double radian = 0; 74 int amplitude = totalAmplitude / 2; 75 for (int i = 0; i < samplingCount; i++) 76 { 77 busySpan[i] = (DWORD)(amplitude + sin(pi*radian)*amplitude); 78 idleSpan[i] = totalAmplitude - busySpan[i]; 79 radian += delta; 80 } 81 82 //獲取系統cup數量 83 SYSTEM_INFO SysInfo; 84 GetSystemInfo(&SysInfo); 85 int num_processors = SysInfo.dwNumberOfProcessors; 86 if(cpuIndex + 1 > num_processors) 87 { 88 printf("error: the index of cpu is out of boundary\n"); 89 printf("cpu number: %d\n", num_processors); 90 printf("your index: %d\n", cpuIndex); 91 printf("** tip: the index of cpu start from 0 **\n"); 92 return; 93 } 94 95 if(cpuIndex < 0) 96 { 97 HANDLE* threads = new HANDLE[num_processors]; 98 for (int i = 0;i < num_processors;i++) 99 { 100 DWORD mask = 1<<i; 101 threads[i] = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL); 102 SetThreadAffinityMask(threads[i], 1<<i);//線程指定在某個cpu運行 103 } 104 WaitForMultipleObjects(num_processors, threads, TRUE, INFINITE); 105 } 106 else 107 { 108 init(cpuIndex); 109 HANDLE thread; 110 DWORD mask = 1; 111 thread = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL); 112 SetThreadAffinityMask(thread, 1<<cpuIndex); 113 WaitForSingleObject(thread,INFINITE); 114 } 115 116 } 117 //------------------------------------- 118 119 int main() 120 { 121 CpuSin(0); 122 }
主要改動在MakeUsageSin函數,初始化在上面代碼108行
結果以下:
【版權聲明】轉載請註明出處 http://www.cnblogs.com/TenosDoIt/p/3242910.html