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

时间:2009-01-21 18:10:10

标签: c++ gcc cpu

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

6 个答案:

答案 0 :(得分:13)

cpuid一起使用的EAX=0指令将按顺序在EBXEDXECX中返回12个字符的供应商字符串。< / p>

对于英特尔,此字符串为“G​​enuineIntel”。对于AMD来说,它是“AuthenticAMD”。其他已创建x86芯片的公司也有自己的字符串。cpuid 0x6c65746e列出了许多(全部?)字符串,以及用于检索详细信息的示例ASM列表。

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

开头
  • 对于英特尔,这是0x444d4163
  • 对于AMD,这是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; }

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

示例代码:

IsAMD

编辑:另一件事 - 只需更改{{1}中的幻数即可轻松将其更改为IsVIA函数,IsTransmeta函数,if函数等。 }}

答案 1 :(得分:11)

如果你在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;
}

答案 2 :(得分:2)

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

在Linux上,尝试sysinfo

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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