author:辟邪马甲
介绍下在VC下获取CPU各项信息的方法,并附部分参考代码
MS的升级包屏蔽了很多底层的访问,真是黑手!
本节介绍下,CPU主频的获得方法,当然很多信息是可以从注册表读的,但是总感觉没那么安全,
这个安全也是相对的,不是还有背后的黑手在嘛....
其实SDK中也有些API跟CPU相关的
void GetSystemInfo( LPSYSTEM_INFO lpSystemInfo );
typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId;
struct {
WORD wProcessorArchitecture;
WORD wReserved;
};
};
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision; } SYSTEM_INFO;呵呵,我们看怎么获得CPU主频typedef struct
... {
unsigned long in_cycles; // Internal clock cycles during
// test
unsigned long ex_ticks; // Microseconds elapsed during
// test
unsigned long raw_freq; // Raw frequency of CPU in MHz
unsigned long norm_freq; // Normalized frequency of CPU
// in MHz.
![]()
} FREQ_INFO;
int _stdcall GetCPUSpeed()
... {
FREQ_INFO cpu_speed;
LARGE_INTEGER t0,t1; // Variables for High-
// Resolution Performance
// Counter reads
unsigned long freq =0; // Most current frequ. calculation
unsigned long freq2 =0; // 2nd most current frequ. calc.
unsigned long freq3 =0; // 3rd most current frequ. calc.
![]()
unsigned long total; // Sum of previous three frequency
// calculations
int tries=0; // Number of times a calculation has
// been made on this call to
// cpuspeed
unsigned long total_cycles=0, cycles; // Clock cycles elapsed
// during test
![]()
unsigned long stamp0, stamp1; // Time Stamp Variable
// for beginning and end
// of test
unsigned long total_ticks=0, ticks; // Microseconds elapsed
// during test
![]()
LARGE_INTEGER count_freq; // High Resolution
// Performance Counter
// frequency
#ifdef WIN32
int iPriority;
HANDLE hThread = GetCurrentThread();
#endif // WIN32;
memset(&cpu_speed, 0x00, sizeof(cpu_speed));
// return cpu_speed;
QueryPerformanceFrequency ( &count_freq );
// On processors supporting the Read
// Time Stamp opcode, compare elapsed
// time on the High-Resolution Counter
// with elapsed cycles on the Time
// Stamp Register.
![]()
do ...{ // This do loop runs up to 20 times or
// until the average of the previous
// three calculated frequencies is
// within 1 MHz of each of the
// individual calculated frequencies.
// This resampling increases the
// accuracy of the results since
// outside factors could affect this
// calculation
![]()
tries++; // Increment number of times sampled
// on this call to cpuspeed
![]()
freq3 = freq2; // Shift frequencies back to make
freq2 = freq; // room for new frequency
// measurement
QueryPerformanceCounter(&t0);
// Get high-resolution performance
// counter time
![]()
t1.LowPart = t0.LowPart; // Set Initial time
t1.HighPart = t0.HighPart;
#ifdef WIN32
iPriority = GetThreadPriority(hThread);
if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
...{
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
}
#endif // WIN32
while ( (unsigned long)t1.LowPart - (unsigned long)t0.LowPart<50) ...{
// Loop until 50 ticks have
// passed since last read of hi-
// res counter. This accounts for
// overhead later.
QueryPerformanceCounter(&t1);
_asm ...{
RDTSC // Read Time Stamp
MOV stamp0, EAX
}
}
t0.LowPart = t1.LowPart; // Reset Initial
t0.HighPart = t1.HighPart; // Time
while ((unsigned long)t1.LowPart-(unsigned long)t0.LowPart<1000 ) ...{
// Loop until 1000 ticks have
// passed since last read of hi-
// res counter. This allows for
// elapsed time for sampling.
QueryPerformanceCounter(&t1);
__asm ...{
RDTSC // Read Time Stamp
MOV stamp1, EAX
}
}
#ifdef WIN32
// Reset priority
if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
...{
SetThreadPriority(hThread, iPriority);
}
#endif // WIN32
cycles = stamp1 - stamp0; // Number of internal
// clock cycles is
// difference between
// two time stamp
// readings.
ticks = (unsigned long) t1.LowPart - (unsigned long) t0.LowPart;
// Number of external ticks is
// difference between two
// hi-res counter reads.
// Note that some seemingly arbitrary mulitplies and
// divides are done below. This is to maintain a
// high level of precision without truncating the
// most significant data. According to what value
// ITERATIIONS is set to, these multiplies and
// divides might need to be shifted for optimal
// precision.
ticks = ticks * 100000;
// Convert ticks to hundred
// thousandths of a tick
![]()
ticks = ticks / ( count_freq.LowPart/10 );
// Hundred Thousandths of a
// Ticks / ( 10 ticks/second )
// = microseconds (us)
total_ticks += ticks;
total_cycles += cycles;
if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
ticks++; // Round up if necessary
![]()
freq = cycles/ticks; // Cycles / us = MHz
![]()
if ( cycles%ticks > ticks/2 )
freq++; // Round up if necessary
![]()
total = ( freq + freq2 + freq3 );
// Total last three frequency
// calculations
}while ( (tries < 3 ) ||
(tries < 20)&&
((abs(3 * freq -total) > 3*TOLERANCE )||
(abs(3 * freq2-total) > 3*TOLERANCE )||
(abs(3 * freq3-total) > 3*TOLERANCE )));
// Compare last three calculations to
// average of last three calculations.
// Try one more significant digit.
freq3 = ( total_cycles * 10 ) / total_ticks;
freq2 = ( total_cycles * 100 ) / total_ticks;
if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
freq3++;
cpu_speed.raw_freq = total_cycles / total_ticks;
cpu_speed.norm_freq = cpu_speed.raw_freq;
freq = cpu_speed.raw_freq * 10;
if( (freq3 - freq) >= ROUND_THRESHOLD )
cpu_speed.norm_freq++;
cpu_speed.ex_ticks = total_ticks;
cpu_speed.in_cycles = total_cycles;
![]()
return (int)cpu_speed.norm_freq;
}
http://blog.youkuaiyun.com/Pregunta/从注册表获得这些信息的方法就不介绍了.下节探讨CPU的技术参数规格.