获取CPU处理器信息(GetLogicalProcessorInformation)

本文介绍如何使用GetLogicalProcessorInformation函数检索关于系统中逻辑处理器及其相关硬件的信息,包括NUMA节点、共享资源等,并提供了一个示例代码来展示如何利用此函数获取处理器核心数、逻辑处理器数及缓存数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



Retrieves information about logical processors and related hardware.

To retrieve information about logical processors and related hardware, including processor groups, use the GetLogicalProcessorInformationEx function.

Syntax

C++
BOOL WINAPI GetLogicalProcessorInformation(
  _Out_   PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
  _Inout_ PDWORD                                ReturnLength
);

Parameters

Buffer [out]

A pointer to a buffer that receives an array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION structures. If the function fails, the contents of this buffer are undefined.

ReturnLength [in, out]

On input, specifies the length of the buffer pointed to by Buffer, in bytes. If the buffer is large enough to contain all of the data, this function succeeds and ReturnLength is set to the number of bytes returned. If the buffer is not large enough to contain all of the data, the function fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and ReturnLength is set to the buffer length required to contain all of the data. If the function fails with an error other than ERROR_INSUFFICIENT_BUFFER, the value of ReturnLength is undefined.

Return value

If the function succeeds, the return value is TRUE and at least one SYSTEM_LOGICAL_PROCESSOR_INFORMATION structure is written to the output buffer.

If the function fails, the return value is FALSE. To get extended error information, call GetLastError.

Remarks

GetLogicalProcessorInformation can be used to get information about the relationship between logical processors in the system, including:

  • The logical processors that are part of a NUMA node.
  • The logical processors that share resources. An example of this type of resource sharing would be hyperthreading scenarios.

Your application can use this information when affinitizing your threads and processes to take best advantage of the hardware properties of the platform, or to determine the number of logical and physical processors for licensing purposes.

Each of the SYSTEM_LOGICAL_PROCESSOR_INFORMATION structures returned in the buffer contains the following:

  • A logical processor affinity mask, which indicates the logical processors that the information in the structure applies to.
  • A logical processor mask of type LOGICAL_PROCESSOR_RELATIONSHIP, which indicates the relationship between the logical processors in the mask. Applications calling this function must be prepared to handle additional indicator values in the future.

Note that the order in which the structures are returned in the buffer may change between calls to this function.

The size of the SYSTEM_LOGICAL_PROCESSOR_INFORMATION structure varies between processor architectures and versions of Windows. For this reason, applications should first call this function to obtain the required buffer size, then dynamically allocate memory for the buffer.

On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.

Examples

The following C++ example uses the GetLogicalProcessorInformation function to display information about processors on the current system. Because GetLogicalProcessorInformation is not present on all systems, this example uses the GetProcAddress function instead of calling GetLogicalProcessorInformation directly.

This example reports the number of active processor cores. This example also reports the number of NUMA nodes, physical packages, and caches on systems that support this information. For more information, see the description of the Relationship member of the SYSTEM_LOGICAL_PROCESSOR_INFORMATION structure.

Windows Server 2003, Windows XP Professional x64 Edition and Windows XP with SP3:  This example reports the number of physical processors rather than the number of active processor cores.

C++
#include <windows.h>
#include <malloc.h>    
#include <stdio.h>
#include <tchar.h>

typedef BOOL (WINAPI *LPFN_GLPI)(
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, 
    PDWORD);


// Helper function to count set bits in the processor mask.
DWORD CountSetBits(ULONG_PTR bitMask)
{
    DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;
    DWORD bitSetCount = 0;
    ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;    
    DWORD i;
    
    for (i = 0; i <= LSHIFT; ++i)
    {
        bitSetCount += ((bitMask & bitTest)?1:0);
        bitTest/=2;
    }

    return bitSetCount;
}

int _cdecl _tmain ()
{
    LPFN_GLPI glpi;
    BOOL done = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
    DWORD returnLength = 0;
    DWORD logicalProcessorCount = 0;
    DWORD numaNodeCount = 0;
    DWORD processorCoreCount = 0;
    DWORD processorL1CacheCount = 0;
    DWORD processorL2CacheCount = 0;
    DWORD processorL3CacheCount = 0;
    DWORD processorPackageCount = 0;
    DWORD byteOffset = 0;
    PCACHE_DESCRIPTOR Cache;

    glpi = (LPFN_GLPI) GetProcAddress(
                            GetModuleHandle(TEXT("kernel32")),
                            "GetLogicalProcessorInformation");
    if (NULL == glpi) 
    {
        _tprintf(TEXT("\nGetLogicalProcessorInformation is not supported.\n"));
        return (1);
    }

    while (!done)
    {
        DWORD rc = glpi(buffer, &returnLength);

        if (FALSE == rc) 
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
            {
                if (buffer) 
                    free(buffer);

                buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
                        returnLength);

                if (NULL == buffer) 
                {
                    _tprintf(TEXT("\nError: Allocation failure\n"));
                    return (2);
                }
            } 
            else 
            {
                _tprintf(TEXT("\nError %d\n"), GetLastError());
                return (3);
            }
        } 
        else
        {
            done = TRUE;
        }
    }

    ptr = buffer;

    while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) 
    {
        switch (ptr->Relationship) 
        {
        case RelationNumaNode:
            // Non-NUMA systems report a single record of this type.
            numaNodeCount++;
            break;

        case RelationProcessorCore:
            processorCoreCount++;

            // A hyperthreaded core supplies more than one logical processor.
            logicalProcessorCount += CountSetBits(ptr->ProcessorMask);
            break;

        case RelationCache:
            // Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache. 
            Cache = &ptr->Cache;
            if (Cache->Level == 1)
            {
                processorL1CacheCount++;
            }
            else if (Cache->Level == 2)
            {
                processorL2CacheCount++;
            }
            else if (Cache->Level == 3)
            {
                processorL3CacheCount++;
            }
            break;

        case RelationProcessorPackage:
            // Logical processors share a physical package.
            processorPackageCount++;
            break;

        default:
            _tprintf(TEXT("\nError: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.\n"));
            break;
        }
        byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        ptr++;
    }

    _tprintf(TEXT("\nGetLogicalProcessorInformation results:\n"));
    _tprintf(TEXT("Number of NUMA nodes: %d\n"), 
             numaNodeCount);
    _tprintf(TEXT("Number of physical processor packages: %d\n"), 
             processorPackageCount);
    _tprintf(TEXT("Number of processor cores: %d\n"), 
             processorCoreCount);
    _tprintf(TEXT("Number of logical processors: %d\n"), 
             logicalProcessorCount);
    _tprintf(TEXT("Number of processor L1/L2/L3 caches: %d/%d/%d\n"), 
             processorL1CacheCount,
             processorL2CacheCount,
             processorL3CacheCount);
    
    free(buffer);

    return 0;
}



Requirements

Minimum supported client

Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP3 [desktop apps only]

Minimum supported server

Windows Server 2003 [desktop apps only]

Header

WinBase.h on Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 and Windows Server 2008 R2 (include Windows.h); Sysinfoapi.h on Windows 8 and Windows Server 2012

Library

Kernel32.lib

DLL

Kernel32.dll
在Rust中,如果你想要通过`winapi`库获取Windows系统上的CPU硬件ID(如哈希或型号等),通常需要访问硬件描述符数据库,这超出了标准库的范围。不过,可以借助第三方库,比如`winapi-x86_64-pc-windows-gnu`配合`cfg-if`条件编译,以便在Windows平台上实现。 以下是一个基本的例子,使用`winapi`库尝试获取处理器制造商和产品名称,但这并不能直接得到CPU硬件ID,因为`winapi`本身并不提供完整的硬件识别服务: ```rust #[cfg(target_os = "windows")] use std::ffi::OsStr; use winapi::um::winbase::{GetLogicalProcessorInformation, SYSTEM_LOGICAL_PROCESSOR_INFORMATION}; use winapi::um::winnt::{SYSTEM_INFO, PROCESSOR_ARCHITECTURE, LOGICAL_PROCESSOR_RELATIONSHIP}; // 获取处理器信息 fn get_processor_info() -> Option<String> { let mut si = unsafe { std::mem::zeroed::<SYSTEM_INFO>() }; si.Length = memsize!(si); let success = unsafe { GetSystemInfo(&si) }; if !success { return None; } // 根据处理器架构选择正确的处理器信息类型 let architecture = si.wProcessorArchitecture as u32; let info_size = match architecture { PROCESSOR_ARCHITECTURE_X86 => memsize!(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) as usize, _ => return None, // 不支持其他架构 }; let mut buffer = Vec::with_capacity(info_size); buffer.set_len(info_size); let handle = unsafe { GetLogicalProcessorInformation(buffer.as_mut_ptr(), info_size as size_t) }; if handle == 0 { return None; } let processor_info = unsafe { SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX::from_raw_parts_mut(buffer.as_mut_ptr(), buffer.len()) }; let cpu_count = processor_info.ProcessorIds.len(); let mut hardware_ids = String::new(); for (index, id) in processor_info.ProcessorIds.iter().enumerate() { let manufacturer = OsStr::from_wide(processor_info.Manufacturer).decode_utf8_lossy().to_string(); let product_name = OsStr::from_wide(processor_info.Product).decode_utf8_lossy().to_string(); hardware_ids.push_str(&format!("Processor #{} - Manufacturer: {}, Product: {}\n", index, manufacturer, product_name)); } Some(hardware_ids.trim_end_matches('\n')) } fn main() { match get_processor_info() { Some(id_info) => println!("{}", id_info), None => println!("Failed to retrieve CPU information"), } } ``` 注意,这个示例只能获取处理器制造商和产品名,并非严格的硬件ID。真正的硬件ID通常由主板BIOS生成并保存在硬件上,可能需要额外的BIOS读取工具或者硬件检测库才能获得。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值