RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1014944
Accepted
Honey Cake
Honey Cake
Asked:2020-08-19 05:09:14 +0000 UTC2020-08-19 05:09:14 +0000 UTC 2020-08-19 05:09:14 +0000 UTC

如何使用 C++ 获取处理器(CPU)的唯一标识符?

  • 772

对使用 c ++ 获取处理器 ID 的方法感兴趣。

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    MSDN.WhiteKnight
    2020-08-21T01:57:01Z2020-08-21T01:57:01Z

    并非每个处理器都在 CPUID 中返回唯一的序列号。为了唯一标识一台计算机,使用由多个值组成的复合硬件标识符是有意义的,例如:

    • CPUID
    • SMBIOS 系统 UUID
    • 系统单元的序列号
    • 主板序列号

    所有这些值都可以通过编程方式从SMBIOS 表中检索。当然,也可以添加网络接口的 MAC 地址,但请记住,一台计算机可以有多个网络接口,不能只取第一个,它可以是虚拟的。

    Windows 示例(读取 SMBIOS 表的代码取自sysinv项目):

    #include <stdio.h>
    #include <Windows.h>
    #include <tchar.h>
    
    // SMBIOS Table Type numbers
    #define SMB_TABLE_BIOS              0
    #define SMB_TABLE_SYSTEM            1
    #define SMB_TABLE_BASEBOARD         2
    #define SMB_TABLE_CHASSIS           3
    #define SMB_TABLE_PROCESSOR         4
    #define SMB_TABLE_MEMCTRL           5
    #define SMB_TABLE_MEMMODULES        6
    #define SMB_TABLE_PORTS             8
    #define SMB_TABLE_SLOTS             9
    #define SMB_TABLE_OEM_STRINGS       11
    #define SMB_TABLE_SYS_CFG_OPTIONS   12
    #define SMB_TABLE_MEM_ARRAY         16
    #define SMB_TABLE_MEM_DEVICE        17
    #define SMB_TABLE_END_OF_TABLE      127
    
    // 64bit Word type
    typedef unsigned long long QWORD;
    
    /*
    * Structures
    */
    typedef struct _RawSmbiosData
    {
        BYTE    Used20CallingMethod;
        BYTE    SMBIOSMajorVersion;
        BYTE    SMBIOSMinorVersion;
        BYTE    DmiRevision;
        DWORD   Length;
        BYTE    SMBIOSTableData[1];
    } RAW_SMBIOS_DATA, * PRAW_SMBIOS_DATA;
    
    typedef struct _SmbiosStructHeader
    {
        BYTE Type;
        BYTE Length;
        WORD Handle;
    } SMBIOS_STRUCT_HEADER, *PSMBIOS_STRUCT_HEADER;
    
    // Structures
    typedef struct _NODE {
        wchar_t *Name;                      // Name of the node
        struct _NODE_ATT_LINK *Attributes;  // Array of attributes linked to the node
        struct _NODE *Parent;               // Parent node
        struct _NODE_LINK *Children;        // Array of linked child nodes
        int Flags;                          // Node configuration flags
    } NODE, * PNODE;
    
    typedef struct _NODE_LINK {
        struct _NODE *LinkedNode;           // Node attached to this node
    } NODE_LINK, * PNODE_LINK;
    
    typedef struct _NODE_ATT {
        wchar_t *Key;                       // Attribute name
        wchar_t *Value;                     // Attribute value string (may be null separated multistring if NAFLG_ARRAY is set)
        int Flags;                          // Attribute configuration flags
    } NODE_ATT, *PNODE_ATT;
    
    typedef struct _NODE_ATT_LINK {
        struct _NODE_ATT *LinkedAttribute;  // Attribute linked to this node
    } NODE_ATT_LINK, *PNODE_ATT_LINK;
    
    
    /********************************************************************/
    
    PRAW_SMBIOS_DATA GetSmbiosData()
    {
        DWORD bufferSize = 0;
    
        PRAW_SMBIOS_DATA smbios = NULL;
    
        // Get required buffer size
        bufferSize = GetSystemFirmwareTable('RSMB', 0, NULL, 0);
        if (bufferSize) {
            smbios = (PRAW_SMBIOS_DATA)LocalAlloc(LPTR, bufferSize);
            bufferSize = GetSystemFirmwareTable('RSMB', 0, (PVOID)smbios, bufferSize);
        }
    
        return smbios;
    }
    
    PSMBIOS_STRUCT_HEADER GetNextStructure(PRAW_SMBIOS_DATA smbios,PSMBIOS_STRUCT_HEADER previous)
    {
        PSMBIOS_STRUCT_HEADER next = NULL;
        PBYTE c = NULL;
        
        // Return NULL is no data found
        if (NULL == smbios)
            return NULL;
    
        // Return first table if previous was NULL
        if (NULL == previous)
            return (PSMBIOS_STRUCT_HEADER)(&smbios->SMBIOSTableData[0]);
    
        // Move to the end of the formatted structure
        c = ((PBYTE)previous) + previous->Length;
    
        // Search for the end of the unformatted structure (\0\0)
        while (true) {
            if ('\0' == *c && '\0' == *(c + 1)) {
                /* Make sure next table is not beyond end of SMBIOS data
                 * (Thankyou Microsoft for ommitting the structure count
                 * in GetSystemFirmwareTable
                 */
                if ((c + 2) < ((PBYTE)smbios->SMBIOSTableData + smbios->Length))
                    return (PSMBIOS_STRUCT_HEADER)(c + 2);
                else
                    return NULL; // We reached the end
            }
    
            c++;
        }
    
        return NULL;
    }
    
    PSMBIOS_STRUCT_HEADER GetNextStructureOfType(PRAW_SMBIOS_DATA smbios,PSMBIOS_STRUCT_HEADER previous, DWORD type)
    {
        PSMBIOS_STRUCT_HEADER next = previous;
        while (NULL != (next = GetNextStructure(smbios,next))) {
            if (type == next->Type)
                return next;
        }
    
        return NULL;
    }
    
    PSMBIOS_STRUCT_HEADER GetStructureByHandle(PRAW_SMBIOS_DATA smbios,WORD handle)
    {
        PSMBIOS_STRUCT_HEADER header = NULL;
    
        while (NULL != (header = GetNextStructure(smbios,header)))
            if (handle == header->Handle)
                return header;
    
        return NULL;
    }
    
    void GetSmbiosString(PSMBIOS_STRUCT_HEADER table, BYTE index, LPWSTR output, int cchOutput)
    {
        DWORD i = 0;
        DWORD len = 0;
        wcscpy(output,L"");
    
        if (0 == index) return;
    
        char *c = NULL;
    
        for (i = 1, c = (char *)table + table->Length; '\0' != *c; c += strlen(c) + 1, i++) {
            if (i == index) {
                len = MultiByteToWideChar(CP_UTF8, 0, c, -1, output,cchOutput);
                break;
            }
        }
    }
    
    //вывод значения числового параметра таблицы SMBIOS по указанному смещению
    void PrintBiosValue(PRAW_SMBIOS_DATA smbios,DWORD type,DWORD offset, DWORD size)
    {
        PSMBIOS_STRUCT_HEADER head=NULL;
        PBYTE cursor = NULL; 
    
        head = GetNextStructureOfType(smbios,head, type);
        if (NULL == head){ printf("PrintBiosValue Error!\n");return;}
    
        cursor=((PBYTE)head+offset);
    
        //value           
        for(int i=0;i<size;i++) {
            printf("%02x",(unsigned int) *cursor);     
            cursor++;
        }
        printf("\n");
    }
    
    //вывод значения строкового параметра таблицы SMBIOS по указанному смещению
    void PrintBiosString(PRAW_SMBIOS_DATA smbios,DWORD type,DWORD offset)
    {
        PSMBIOS_STRUCT_HEADER head;
        head=NULL;
        PBYTE cursor = NULL;
        WCHAR buf[1024];
    
        head = GetNextStructureOfType(smbios,head, type);
        if (NULL == head){printf("PrintString Error!\n");return;}
        cursor=((PBYTE)head+offset);
        BYTE val=*cursor;
            
        GetSmbiosString((head), *cursor,buf,1024);
        //  value           
        wprintf(L"%s\n",buf);
    }
    
    int main(){
    
        PRAW_SMBIOS_DATA data = GetSmbiosData();
    
        if(data==NULL){
            printf("Can't get SMBIOS data!"); 
            return 1;
        }
    
        printf("System UUID: ");
        PrintBiosValue(data,SMB_TABLE_SYSTEM,8, 16);
    
        printf("Chassis serial: ");
        PrintBiosString(data,SMB_TABLE_CHASSIS,7);
    
        printf("Motherboard serial: ");
        PrintBiosString(data,SMB_TABLE_BASEBOARD,7);
    
        printf("CPUID: ");
        PrintBiosValue(data,SMB_TABLE_PROCESSOR,8, 8);  //Таблица SMBIOS содержит только 2 DWORD-значения CPUID из 4, но этого обычно достаточно
    
        getchar();
    }
    
    • 4
  2. AlexGlebe
    2020-08-19T16:32:56Z2020-08-19T16:32:56Z

    尝试使用cpuid命令。完整说明:

    https://c9x.me/x86/html/file_module_x86_id_45.html

    也许有你正在寻找的东西。例子 :

    # include <cstdint>
    # include <cstdio>
    struct CPUIDinfo
        {
            uint32_t EAX;
            uint32_t EBX;
            uint32_t ECX;
            uint32_t EDX;
        };
    
        static inline void CpuId(unsigned int func, unsigned int subfunc,
    CPUIDinfo& info)
        {
            __asm__ __volatile__ (
                "cpuid"
                : "=a"(info.EAX), "=b"(info.EBX), "=c"(info.ECX), "=d"(info.EDX)
                : "a"(func), "c"(subfunc)
            );
        }
    
    int main(){
    for(int i=0;i<6;++i){
      CPUIDinfo info;
      CpuId(i,0,info);
      printf("%d,0:%d,%d,%d,%d\n",i,info.EAX,info.EBX,info.ECX,info.EDX);}
    }
    

    4.2. 形成 96 位处理器序列号 96 位处理器序列号是三个 32 位实体的串联。要访问处理器序列号的最高 32 位,程序应将 EAX 寄存器参数值设置为“1”,然后执行 CPUID 指令,如下所示: MOV EAX, 01H CPUID 执行 CPUID 指令后,EAX 寄存器包含处理器签名。处理器签名包括处理器序列号的最高有效 32 位。在收集处理器序列号的剩余 64 位之前,应保存 EAX 中的值。要访问处理器序列号的剩余 64 位,程序应将 EAX 寄存器参数值设置为“3”,然后执行 CPUID 指令,如下所示:MOV EAX, 03H CPUID CPUID 指令执行后,EDX 寄存器包含处理器序列号的中间 32 位,ECX 寄存器包含处理器序列号的低 32 位。然后,软件可以在返回完整的 96 位处理器序列号之前连接保存的处理器签名、EDX 和 ECX。处理器序列号应显示为 6 组 4 个十六进制半字节(例如 XXXX-XXXX-XXXX-XXXXXXXX-XXXX,其中 X 代表十六进制数字)。字母十六进制字符应显示为大写字母。处理器序列号应显示为 6 组 4 个十六进制半字节(例如 XXXX-XXXX-XXXX-XXXXXXXX-XXXX,其中 X 代表十六进制数字)。字母十六进制字符应显示为大写字母。处理器序列号应显示为 6 组 4 个十六进制半字节(例如 XXXX-XXXX-XXXX-XXXXXXXX-XXXX,其中 X 代表十六进制数字)。字母十六进制字符应显示为大写字母。

    从隐私来看,请求EAX=0x03总是返回零。使用所有其他可用信息。有时人们使用虚拟计算机。因此,身份请求对您来说效果不佳。

    • 1

相关问题

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5