【问题标题】:Getting the machine serial number and CPU ID using C/C++ in Linux在 Linux 中使用 C/C++ 获取机器序列号和 CPU ID
【发布时间】:2011-06-27 10:34:44
【问题描述】:

在Linux系统中如何获取机器序列号和CPU ID?

非常感谢示例代码。

【问题讨论】:

  • @viraptor ,1. 页面上的所有点击都没有真正的答案。 1.这个问题现在很热门,如果能得到真正的答案就好了。这是 SO 的目的之一。提供针对特定问题的规范答案,而不是论坛的所有死内容。
  • “机器序列号”是指CPU的序列号还是主板的序列号?
  • @viraptor 确实很有趣。答案有很多赞成票,甚至有一个被接受,即使它根本没有回答问题。我想我会对所有这些投反对票并标记这个问题。说真的,这很荒谬。甚至安德烈·霍尔兹纳(Andre Holzner)都要求澄清,然后发布了一些内容以加入积分竞赛,然后被接受了一个废话答案。

标签: c++ c linux


【解决方案1】:

Here 是 Linux 内核似乎使用的:

static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
                                unsigned int *ecx, unsigned int *edx)
{
        /* ecx is often an input as well as an output. */
        asm volatile("cpuid"
            : "=a" (*eax),
              "=b" (*ebx),
              "=c" (*ecx),
              "=d" (*edx)
            : "0" (*eax), "2" (*ecx));
}

然后哪个可以用作例如:

#include <stdio.h>

int main(int argc, char **argv)
{
  unsigned eax, ebx, ecx, edx;

  eax = 1; /* processor info and feature bits */
  native_cpuid(&eax, &ebx, &ecx, &edx);

  printf("stepping %d\n", eax & 0xF);
  printf("model %d\n", (eax >> 4) & 0xF);
  printf("family %d\n", (eax >> 8) & 0xF);
  printf("processor type %d\n", (eax >> 12) & 0x3);
  printf("extended model %d\n", (eax >> 16) & 0xF);
  printf("extended family %d\n", (eax >> 20) & 0xFF);

  /* EDIT */
  eax = 3; /* processor serial number */
  native_cpuid(&eax, &ebx, &ecx, &edx);

  /** see the CPUID Wikipedia article on which models return the serial 
      number in which registers. The example here is for 
      Pentium III */
  printf("serial number 0x%08x%08x\n", edx, ecx);

}

this Wikipedia article 中提供了有关如何使用 CPUID 指令的良好参考。

编辑 Wikipedia 文章称,序列号是在 Pentium III 中引入的,但由于隐私问题不再在以后的模型中实现。在 Linux 系统上,您可以通过以下方式检查此功能(PSN 位)是否存在:

grep -i --color psn /proc/cpuinfo

如果这没有显示任何内容,则您的系统不支持处理器序列号。

【讨论】:

  • 此调用的结果不是“序列号”。它是计算机中安装的 CPU 型号的非唯一标识符(例如,“Intel Xeon E5-2630”)。
  • 确实,在 Intel CPU 中,似乎只有 Pentium III 支持它(并且只有在 BIOS 中启用它时)。我更新了答案。
【解决方案2】:

GCC 中有一个 cpuinfo.h。它是安全的,使用它。

示例(我有 GCC 4.7+,很高兴在这里使用“auto”):

#include <cpuid.h>
#include <iostream>
#include <map>
#include <string>

using namespace std;

struct CPUVendorID {
    unsigned int ebx;
    unsigned int edx;
    unsigned int ecx;

    string toString() const {
        return string(reinterpret_cast<const char *>(this), 12);
    }
};

int main() {
    unsigned int level = 0;
    unsigned int eax = 0;
    unsigned int ebx;
    unsigned int ecx;
    unsigned int edx;

    __get_cpuid(level, &eax, &ebx, &ecx, &edx);

    CPUVendorID vendorID { .ebx = ebx, .edx = edx, .ecx = ecx };

    map<string, string> vendorIdToName;
    vendorIdToName["GenuineIntel"] = "Intel";
    vendorIdToName["AuthenticAMD"] = "AMD";
    vendorIdToName["CyrixInstead"] = "Cyrix";
    vendorIdToName["CentaurHauls"] = "Centaur";
    vendorIdToName["SiS SiS SiS "] = "SiS";
    vendorIdToName["NexGenDriven"] = "NexGen";
    vendorIdToName["GenuineTMx86"] = "Transmeta";
    vendorIdToName["RiseRiseRise"] = "Rise";
    vendorIdToName["UMC UMC UMC "] = "UMC";
    vendorIdToName["Geode by NSC"] = "National Semiconductor";

    string vendorIDString = vendorID.toString();

    auto it = vendorIdToName.find(vendorIDString);
    string vendorName = (it == vendorIdToName.end()) ? "Unknown" : it->second;

    cout << "Max instruction ID: " << eax << endl;
    cout << "Vendor ID: " << vendorIDString << endl;
    cout << "Vendor name: " << vendorName << endl;
}

输出:

$ make
g++ --std=c++11 main.cc -o cpuid
$ ./cpuid 
Max instruction ID: 6
Vendor ID: GenuineIntel
Vendor name: Intel

【讨论】:

    【解决方案3】:

    您可以从/proc/cpuinfo 中提取的有关处理器的信息。

    要获得序列号,您应该查看dmidecode。我现在没进去看,但是dmidecode 可以告诉你序列号,所以我会从那里开始。

    【讨论】:

      【解决方案4】:
      #include <stdio.h>
      
      void getPSN(char *PSN)
      {
          int varEAX, varEBX, varECX, varEDX;
          char str[9];
          //%eax=1 gives most significant 32 bits in eax 
          __asm__ __volatile__ ("cpuid"   : "=a" (varEAX), "=b" (varEBX), "=c" (varECX), "=d" (varEDX) : "a" (1));
          sprintf(str, "%08X", varEAX); //i.e. XXXX-XXXX-xxxx-xxxx-xxxx-xxxx
          sprintf(PSN, "%C%C%C%C-%C%C%C%C", str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
          //%eax=3 gives least significant 64 bits in edx and ecx [if PN is enabled]
          __asm__ __volatile__ ("cpuid"   : "=a" (varEAX), "=b" (varEBX), "=c" (varECX), "=d" (varEDX) : "a" (3));
          sprintf(str, "%08X", varEDX); //i.e. xxxx-xxxx-XXXX-XXXX-xxxx-xxxx
          sprintf(PSN, "%s-%C%C%C%C-%C%C%C%C", PSN, str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
          sprintf(str, "%08X", varECX); //i.e. xxxx-xxxx-xxxx-xxxx-XXXX-XXXX
          sprintf(PSN, "%s-%C%C%C%C-%C%C%C%C", PSN, str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
      }
      
      int main()
      {
           char PSN[30]; //24 Hex digits, 5 '-' separators, and a '\0'
           getPSN(PSN);
          printf("%s\n", PSN); //compare with: lshw | grep serial:
           return 0;
      }
      

      【讨论】:

        【解决方案5】:

        此程序将帮助您以编程方式运行 Linux 命令:

        char* GetSystemOutput(char* cmd)
        {
            int buff_size = 32;
            char* buff = new char[buff_size];
        
            char* ret = NULL;
            string str = "";
        
            int fd[2];
            int old_fd[3];
            pipe(fd);
        
            old_fd[0] = dup(STDIN_FILENO);
            old_fd[1] = dup(STDOUT_FILENO);
            old_fd[2] = dup(STDERR_FILENO);
        
            int pid = fork();
            switch(pid)
            {
                case 0:
                       close(fd[0]);
                       close(STDOUT_FILENO);
                       close(STDERR_FILENO);
                       dup2(fd[1], STDOUT_FILENO);
                       dup2(fd[1], STDERR_FILENO);
                       system(cmd);
                       //execlp((const char*)cmd, cmd,0);
                       close (fd[1]);
                       exit(0);
                       break;
        
                case -1:
                       cerr << "GetSystemOutput/fork() error\n" << endl;
                       exit(1);
        
                default:
                       close(fd[1]);
                       dup2(fd[0], STDIN_FILENO);
        
                       int rc = 1;
                       while (rc > 0)
                       {
                           rc = read(fd[0], buff, buff_size);
                           str.append(buff, rc);
                           //memset(buff, 0, buff_size);
                       }
        
                       ret = new char [strlen((char*)str.c_str())];
        
                       strcpy(ret, (char*)str.c_str());
        
                       waitpid(pid, NULL, 0);
                       close(fd[0]);
            }
        
            dup2(STDIN_FILENO, old_fd[0]);
            dup2(STDOUT_FILENO, old_fd[1]);
            dup2(STDERR_FILENO, old_fd[2]);
        
            return ret;
        }
        

        API 使用:GetSystemOutput("/usr/bin/lsb_release -a")

        并遵循命令:

        cat /proc/cpuinfo = tells you CPU information
        

        【讨论】:

          猜你喜欢
          • 2010-09-19
          • 1970-01-01
          • 2017-05-31
          • 2015-04-27
          • 2012-12-11
          • 1970-01-01
          • 2012-05-01
          • 2011-07-13
          • 1970-01-01
          相关资源
          最近更新 更多