⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpuinfo.cpp

📁 一个用vc获取系统硬件信息的例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
// CpuInfo.cpp
//    
//   This file contains the class CpuInfo. It basically determines all 
//   pertinent information for the CPU. It currently gets in-depth 
//   information for both Intel and AMD CPUs. 
//
//   Parts of this code were submitted by and should be credited to:
//   Alexandre Cesari [acesari@aclogic.com] -- CPU Speed detection
// 
//   Copyright (c) 2001 Paul Wendt [p-wendt@wideopenwest.com]
// 
//   Updates J. Michael McGarrah [mcgarrah@mcgarware.com]
// 
#include "CpuInfo.h"
#include <tchar.h>  // for _T [registry searches]
#include <sstream>
using namespace std;

//---------------------------------------------------------------------------
// CPU information defines -- VERY x86-dependent stuff going on here
//
#define CPU_ID __asm _emit 0xf __asm _emit 0xa2

const int CpuInfo::BRANDTABLESIZE = 4;

CpuInfo::CpuInfo(const bool fCpuSpeed/* = true*/, const bool fDebug /* = false */)
{
   m_fDebug = fDebug;
   m_strCpuSpeed = "0";
   determineCpuInfo();
   if (fCpuSpeed)
   {
      determineCpuSpeed();
   }
   m_osDebugResults << ends;
   std::string d = m_osDebugResults.str();
}

CpuInfo::CpuInfo(const CpuInfo& source)
{
   assign(source);
}

CpuInfo& CpuInfo::operator=(const CpuInfo& right)
{
   if (this != &right)
   {
      assign(right);
   }

   return (*this);
}

CpuInfo::~CpuInfo()
{
   // nothing to do yet
}

void CpuInfo::determineCpuInfo(void)
{
   SYSTEM_INFO stCpuInfo;

   GetSystemInfo(&stCpuInfo);

   ostringstream os;
   os << stCpuInfo.dwNumberOfProcessors << ends;
   m_strNumProcessors = os.str();

   if (m_fDebug) m_osDebugResults << "# CPUs detected: " << stCpuInfo.dwNumberOfProcessors << endl;

   determineCpuStats(stCpuInfo.wProcessorArchitecture);
}

// this is pretty straight forward. as long as it's a fairly-recent processor, we'll
// try to get the speed. first, though, we set the priority to high ... so that
// we'll get a greater chance of getting the correct speed.
// the primary algorithm is very accurate, but not supported across all x86 processors.
// the second approach is to get the speed from the registry; this isn't supported
// on all platforms, so ...
// the third approach just does a crude and slow benchmark.
void CpuInfo::determineCpuSpeed(void)
{
   if ( ((m_cpuStats.getVendor() == CpuStats::VENDOR_INTEL) && (m_cpuStats.getFamily() > 4)) ||
        ((m_cpuStats.getVendor() == CpuStats::VENDOR_AMD)   && (m_cpuStats.getFamily() > 5)) )
   {
      DWORD dwStartingPriority = GetPriorityClass(GetCurrentProcess());
      SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

      DWORD dwSpeed = calculateCpuSpeed();
      if (m_fDebug) m_osDebugResults << "CPU Speed from QueryPerformanceFrequency: " << dwSpeed << endl;
      if (dwSpeed == 0)
      {
         dwSpeed = getCpuSpeedFromRegistry();
         if (m_fDebug) m_osDebugResults << "CPU Speed from Registry [NT only]" << dwSpeed << endl;
         if (dwSpeed == 0)
         {
            dwSpeed = calculateCpuSpeedMethod2();
            if (m_fDebug) m_osDebugResults << "CPU Speed -- old, slow method: " << dwSpeed << endl;
         }
      }

      SetPriorityClass(GetCurrentProcess(), dwStartingPriority);

      // if it's still 0 at this point, god help us all
      if (dwSpeed == 0)
      {
         m_strCpuSpeed = "Unknown";
      }
      else
      {
         ostringstream os;
         os << dwSpeed << " MHz" << ends;
         m_strCpuSpeed = os.str();
      }
   }
      
   if (m_fDebug) m_osDebugResults << "Final determined speed: " << m_strCpuSpeed << endl;
}

void CpuInfo::assign(const CpuInfo& source)
{
   m_cpuStats = source.m_cpuStats;
   m_strCpuSpeed = source.m_strCpuSpeed;
   m_strNumProcessors = source.m_strNumProcessors;
   m_fDebug = source.m_fDebug;
   m_osDebugResults << source.m_osDebugResults.str();
}

void CpuInfo::determineCpuStats(WORD wProcessorArchitecture)
{
   // make sure the cpu knows CPUID
   if (!determineCpuId())
   {
      return;
   }

   m_cpuStats.setKnowsCpuId(true);

   DWORD dwHighestCpuId = determineHighestCpuId();
   switch (dwHighestCpuId)
   {
   default:
   case 2:     // intel cpu's find cache information here
      determineIntelCacheInfo();
      // no break;
   case 1:     // x86 cpu's do processor identification here
      determineCpuIdentification();
      break;

   case 0:     // don't do anything funky; return
      return;
   }

   if (m_cpuStats.getVendor() == CpuStats::VENDOR_INTEL)
   {
      determineOldIntelName();
   }
 
   DWORD dwLargestExtendedFeature = determineLargestExtendedFeature(); 
   if (dwLargestExtendedFeature >= AMD_L2CACHE_FEATURE)
   { 
      determineAmdL2CacheInfo(); 
   } 

   if (dwLargestExtendedFeature >= AMD_L1CACHE_FEATURE)
   { 
      determineAmdL1CacheInfo(); 
   } 

   if (dwLargestExtendedFeature >= NAMESTRING_FEATURE)
   { 
      determineNameString(); 
   } 

   if (dwLargestExtendedFeature >= AMD_EXTENDED_FEATURE)
   { 
      determineExtendedFeature(); 
   } 
}

bool CpuInfo::determineCpuId(void)
{
   int fKnowsCpuId = 0;
   
   __asm
   {
      pushfd                      // save EFLAGS to stack.
      pop     eax                 // store EFLAGS in EAX.
      mov     edx, eax            // save in EBX for testing later.
      xor     eax, 0200000h       // switch bit 21.
      push    eax                 // copy "changed" value to stack.
      popfd                       // save "changed" EAX to EFLAGS.
      pushfd
      pop     eax
      xor     eax, edx            // See if bit changeable.
      jnz     short has_cpuid     // if so, mark 
      mov     fKnowsCpuId, 0      // if not, put 0
      jmp     done
has_cpuid:
      mov     fKnowsCpuId, 1      // put 1
done:
   }

   if (m_fDebug) m_osDebugResults << "CPU knows CPUID: " << fKnowsCpuId << endl;

   return ((bool)fKnowsCpuId);
}

DWORD CpuInfo::determineHighestCpuId(void)
{
   DWORD dwHighest = 0;
   char szTemp[16] = {0};

   __asm
   {
      mov      eax, 0
      CPUID

      test    eax,eax                   // 0 is highest function, then don't query more info
      jz      no_features
    
      mov     dwHighest, eax            // highest supported instruction
      mov     DWORD PTR [szTemp+0],ebx  // Stash the manufacturer string for later
      mov     DWORD PTR [szTemp+4],edx
      mov     DWORD PTR [szTemp+8],ecx

no_features:
   }

   if (dwHighest != 0)
   {
      string strVendorId = szTemp;
      m_cpuStats.setVendorId(strVendorId);
   }

   if (m_fDebug) m_osDebugResults << "Highest CPUID is: " << dwHighest << endl;

   return (dwHighest);
}

void CpuInfo::determineCpuIdentification(void)
{
   DWORD dwSignature = 0;
   DWORD dwFeatureEbx = 0;
   DWORD dwFeatureEcx = 0 ;
   DWORD dwFeatures = 0;

   __asm
   {
      mov      eax, 1
      CPUID

      mov      [dwSignature], eax     // store CPU signature
      mov      [dwFeatureEbx], ebx    
      mov      [dwFeatureEcx], ecx
      mov      [dwFeatures], edx      // features
   }  

   m_cpuStats.setSignature(dwSignature);
   m_cpuStats.setFeatureEbx(dwFeatureEbx);
   m_cpuStats.setFeatureEcx(dwFeatureEcx);
   m_cpuStats.setFeatures(dwFeatures);

   if (m_fDebug) m_osDebugResults << "CPU Signature:   " << dwSignature << endl;
   if (m_fDebug) m_osDebugResults << "CPU Feature EBX: " << dwFeatureEbx << endl;
   if (m_fDebug) m_osDebugResults << "CPU Feature ECX: " << dwFeatureEcx << endl;
   if (m_fDebug) m_osDebugResults << "CPU Features:    " << dwFeatures << endl;
}

DWORD CpuInfo::determineLargestExtendedFeature(void)
{
   DWORD dwHighest = 0;

   __asm
   {
      mov      eax, 0x80000000
      CPUID

      mov dwHighest, eax
   }

   if (m_fDebug) m_osDebugResults << "Largest extended CPU feature: " << dwHighest << endl;

   return (dwHighest);
}

void CpuInfo::determineExtendedFeature(void)
{
   DWORD dwExtendedFeatures = 0;

   __asm
   {
      mov      eax, 0x80000001
      CPUID

      mov dwExtendedFeatures, edx
   }

   m_cpuStats.setExtendedFeatures(dwExtendedFeatures);
   if (m_fDebug) m_osDebugResults << "CPU Extended features: " << dwExtendedFeatures << endl;
}

void CpuInfo::determineNameString(void)
{
   char szName[64] = {0};

   __asm
   {
      mov      eax, 0x80000002
      CPUID
      mov      DWORD PTR [szName+0],eax
      mov      DWORD PTR [szName+4],ebx
      mov      DWORD PTR [szName+8],ecx
      mov      DWORD PTR [szName+12],edx
      mov      eax, 0x80000003
      CPUID
      mov      DWORD PTR [szName+16],eax
      mov      DWORD PTR [szName+20],ebx
      mov      DWORD PTR [szName+24],ecx
      mov      DWORD PTR [szName+28],edx
      mov      eax, 0x80000004
      CPUID
      mov      DWORD PTR [szName+32],eax
      mov      DWORD PTR [szName+36],ebx
      mov      DWORD PTR [szName+40],ecx
      mov      DWORD PTR [szName+44],edx
   }

   m_cpuStats.setName(szName);
   if (m_fDebug) m_osDebugResults << "CPU name string: " << szName << endl;
}

void CpuInfo::determineAmdL1CacheInfo(void)
{
   DWORD dwEax = 0;
   DWORD dwEbx = 0;
   DWORD dwEcx = 0;
   DWORD dwEdx = 0;

   __asm
   {
      mov      eax, 0x80000005
      CPUID
      mov      dwEax, eax
      mov      dwEbx, ebx
      mov      dwEcx, ecx
      mov      dwEdx, edx
   }

   m_cpuStats.setCacheEax(dwEax);
   m_cpuStats.setCacheEbx(dwEbx);
   m_cpuStats.setCacheEcx(dwEcx);
   m_cpuStats.setCacheEdx(dwEdx);
   if (m_fDebug) m_osDebugResults << "L1 Cache Info EAX: " << dwEax << endl;
   if (m_fDebug) m_osDebugResults << "L1 Cache Info EBX: " << dwEbx << endl;
   if (m_fDebug) m_osDebugResults << "L1 Cache Info ECX: " << dwEcx << endl;
   if (m_fDebug) m_osDebugResults << "L1 Cache Info EDX: " << dwEdx << endl;
}

void CpuInfo::determineAmdL2CacheInfo(void)
{
   DWORD dwEax = 0;
   DWORD dwEbx = 0;
   DWORD dwEcx = 0;
   DWORD dwEdx = 0;

   __asm
   {
      mov      eax, 0x80000006
      CPUID
      mov      dwEax, eax
      mov      dwEbx, ebx
      mov      dwEcx, ecx
      mov      dwEdx, edx
   }

   m_cpuStats.setCache2Eax(dwEax);
   m_cpuStats.setCache2Ebx(dwEbx);
   m_cpuStats.setCache2Ecx(dwEcx);
   m_cpuStats.setCache2Edx(dwEdx);
   if (m_fDebug) m_osDebugResults << "L2 Cache Info EAX: " << dwEax << endl;
   if (m_fDebug) m_osDebugResults << "L2 Cache Info EBX: " << dwEbx << endl;
   if (m_fDebug) m_osDebugResults << "L2 Cache Info ECX: " << dwEcx << endl;
   if (m_fDebug) m_osDebugResults << "L2 Cache Info EDX: " << dwEdx << endl;
}

void CpuInfo::determineIntelCacheInfo(void)
{
   DWORD dwEax = 0;
   DWORD dwEbx = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -