代码之家  ›  专栏  ›  技术社区  ›  vivekian2

如何检测运行时使用的CPU?

  •  5
  • vivekian2  · 技术社区  · 16 年前

    如何检测运行时使用的CPU?c++代码需要区分AMD/Intel架构吗?使用gcc 4.2。

    6 回复  |  直到 13 年前
        1
  •  13
  •   Branan    16 年前

    这个 cpuid 使用说明 EAX=0 将在中返回一个12个字符的供应商字符串 EBX , EDX , ECX ,按照这个顺序。

    对于英特尔,这个字符串是“GenuineIntel”。对于AMD来说,这是“真正的AMD”。其他制造x86芯片的公司也有自己的字符串。这个 Wikipedia page 标识符 列出了许多(所有?)字符串,以及一个用于检索详细信息的示例ASM列表。

    您实际上只需要检查ECX是否与最后四个字符匹配。你不能使用前四个,因为一些Transmeta CPU也以“正版”开头

    • 对于英特尔来说,这是 0x6c65746e
    • 对于AMD来说,这是 0x444d4163

    如果你将其中的每个字节转换为一个字符,它们会看起来是向后的。这只是x86的小端设计的结果。如果你将寄存器复制到内存中,并将其视为字符串,它就会正常工作。

    示例代码:

    bool IsIntel() // returns true on an Intel processor, false on anything else
    {
      int id_str; // The first four characters of the vendor ID string
    
      __asm__ ("cpuid":\    // run the cpuid instruction with...
      "=c" (id_str) :       // id_str set to the value of EBX after cpuid runs...
      "a" (0) :             // and EAX set to 0 to run the proper cpuid function.
      "eax", "ebx", "edx"); // cpuid clobbers EAX, ECX, and EDX, in addition to EBX.
    
      if(id_str==0x6c65746e) // letn. little endian clobbering of GenuineI[ntel]
        return true;
      else
        return false;
    }
    

    编辑:还有一件事——这很容易变成 IsAMD 功能, IsVIA 功能, IsTransmeta 只需更改函数中的幻数 if .

        2
  •  11
  •   Adam Rosenfield    16 年前

    如果你在Linux上(或在Cygwin下运行的Windows上),你可以通过读取特殊文件来弄清楚 /proc/cpuinfo 并寻找以…开头的那条线 vendor_id 。如果字符串是 GenuineIntel ,你运行的是英特尔芯片。如果你得到 AuthenticAMD ,你运行的是AMD芯片。

    void get_vendor_id(char *vendor_id)  // must be at least 13 bytes
    {
        FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
        if(cpuinfo == NULL)
            ;  // handle error
        char line[256];
        while(fgets(line, 256, cpuinfo))
        {
            if(strncmp(line, "vendor_id", 9) == 0)
            {
                char *colon = strchr(line, ':');
                if(colon == NULL || colon[1] == 0)
                    ;  // handle error
                strncpy(vendor_id, 12, colon + 2);
                fclose(cpuinfo);
                return;
            }
        }
    
        // if we got here, handle error
        fclose(cpuinfo);
    }
    

    如果你知道你在x86架构上运行,一种不太便携的方法是使用CPUID指令:

    void get_vendor_id(char *vendor_id)  // must be at least 13 bytes
    {
        // GCC inline assembler
        __asm__ __volatile__
            ("movl $0, %%eax\n\t"
             "cpuid\n\t"
             "movl %%ebx, %0\n\t"
             "movl %%edx, %1\n\t"
             "movl %%ecx, %2\n\t"
             : "=m"(vendor_id), "=m"(vendor_id + 4), "=m"(vendor_id + 8)  // outputs
             : // no inputs
             : "%eax", "%ebx", "%edx", "%ecx", "memory");  // clobbered registers
        vendor_id[12] = 0;
    }
    
    int main(void)
    {
        char vendor_id[13];
        get_vendor_id(vendor_id);
    
        if(strcmp(vendor_id, "GenuineIntel") == 0)
            ; // it's Intel
        else if(strcmp(vendor_id, "AuthenticAMD") == 0)
            ; // it's AMD
        else
            ; // other
        return 0;
    }
    
        3
  •  2
  •   Kevin    16 年前

    在Windows上,您可以使用 GetNativeSystemInfo 功能

    在Linux上,尝试 sysinfo

        4
  •  1
  •   MSalters    16 年前

    你可能根本不应该检查。相反,请检查CPU是否支持 特征 您需要,例如SSE3。两款英特尔芯片之间的差异可能比AMD和英特尔芯片之间更大。

        5
  •  0
  •   Jorge Niedbalski R.    16 年前

    您必须在Makefile arch中定义它= uname -p 2>&1 ,然后为不同的架构使用#ifdef i386和#endif。

        6
  •  0
  •   Bartosz Pachołek    12 年前

    我发布了一个小项目: http://sourceforge.net/projects/cpp-cpu-monitor/ 它使用 libgtop 库,并通过UDP公开数据。您可以根据需要进行修改。GPL开源。如果您对此有任何疑问,请提问。