繁体   English   中英

以编程方式从Mac OS X获取处理器详细信息

[英]Programmatically get processor details from Mac OS X

我的应用程序在Mac OS X上运行,需要检索有关其所运行机器的详细信息以报告系统信息。 我需要的项目之一是有关计算机中安装的处理器的详细信息。

我的代码目前可以运行,但远非理想的解决方案,实际上我认为这是一个糟糕的解决方案,但是我没有找到更好的解决方案的运气。

经过一些格式化后,我当前报告的信息如下所示:

处理器:Intel Core 2 Duo 2.1 GHz,Family 6 Model 23 Steping 6

我获得的所有信息都是通过从popen()调用的命令行实用程序获得的。 处理器描述的可读部分来自“ system_profiler”命令输出,而Family,Model和Stepping值则来自“ sysctl”命令。

这些命令行实用程序必须从某处获取信息。 我想知道是否有可用的编程界面来获取相同的信息?


有关:

使用sysctlbyname而不是sysctl ,例如

#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>

uint64_t get_cpu_freq(void)
{
    uint64_t freq = 0;
    size_t size = sizeof(freq);

    if (sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0) < 0)
    {
        perror("sysctl");
    }
    return freq;
}

通过systctlbyname查看sysctl -a的输出,可以获得可以传递给systctlbyname的名称的列表。

您需要查看IOKit API。 IORegistryExplorer应用程序(标准devtools安装的一部分)将帮助您找到所需的内容。

例如,在MacBook Pro的IORegistryExplorer中,我从窗口左上角的下拉菜单中选择“ IODeviceTree”,然后在下面的树状视图中可以看到两个CPU。 选择任何一个都会为我提供以下信息:

IORegistryExplorer屏幕截图http://blog.alanquatermain.net/images/IORegistryExplorer-CPUs.png

“总线频率”和“时钟频率”以及“时基频率”都是数据对象中的32位整数包装器,因此必须在此处进行字节交换以解释(小尾数i386机器字),然后才能正常工作得出以下值:

  • 总线频率:1064000000 Hz => 1.064 GHz
  • 时钟频率:2530000000 Hz => 2.53 GHz
  • 时基频率:1000000000 HZ => 1.0 GHz

但是,如果您是通过IOKit读取这些内容,则将获得CFDataRef,可以将字节复制到自己的uint32_t中,如下所示:

uint32_t bus_frequency = 0;
CFDataGetBytes( theData, (UInt8 *) &bus_frequency, sizeof(uint32_t) );

接下来,您可以使用NXArchInfo()调用获取处理器信息,该调用通过包含<mach-o/arch.h> 这将返回一个包含cpu类型和子类型代码以及C字符串名称和描述的结构。 如果其中不包含步进ID,那么我唯一想到的方法就是通过CPUID指令。 创建一个.s和.h文件,并输入以下代码:

.s文件:

#ifdef __i386__ || __x86_64__

.macro ENTRY
    .text
    .private_extern $0
    .align  4, 0x90
$0:
.endmacro

// __private_extern__ unsigned long GetCPUSteppingID( void )
ENTRY _GetCPUSteppingID
    push        %ebp                // store existing frame pointer
    mov         %esp,%ebp           // make a new frame pointer from stack pointer
#if __x86_64__
    push        %rbx
#endif
    push        %ebx                // we save %ebx because the cpuid instruction
                                    // will overwrite it, and it's expected
                                    // to be unchanged in the caller after
                                    // calling another function
    movl        $1,%eax             // fetch cpu info
    cpuid                           // stepping-id is in low 4 bits of %edx now
    and         $0x0000000f,%edx    // clear out everything we don't want
#if __x86_64__
    mov         %edx,%rax           // %rax is 64-bit arch result register
#else
    mov         %edx,%eax           // %eax is 32-bit arch result register
#endif
    pop         %ebx                // restore saved value of %ebx
#if __x86_64__
    pop         %rbx                // restore saved value of %rbx
#endif
    leave                           // restores prior stack frame from %ebp
    ret                             // returns to caller

#endif // __i386__ || __x86_64__

.h文件:

#ifndef __GET_STEPPING_ID__
#define __GET_STEPPING_ID__

/* unsigned long is register-sized on both 32-bit and 64-bit OS X */
__private_extern__ unsigned long GetSteppingID( void );

#endif /* __GET_STEPPING_ID__ */

请注意,我不确定上面的x86_64位; 从理论上讲,我在此处键入的内容将确保相同的代码可针对64位编译,并且在这种情况下将返回64位值。 它还将保存/恢复%ebx寄存器的64位版本%rbx寄存器。 从理论上讲 ,它将覆盖所有基础。

sysctl(3)可能是一个不错的起点。 您可能需要CTL_HW选择器定义的CTL_HW

如果您特别想要CPU信息,则使用cpuid(在C __asm cpuid中)指令。 它提供了CPU的所有可能信息,包括其系列,型号,公司,内核数等。主要是,所有API均使用此指令来检索CPU信息。 您可以在Web上获取有关CPUID的详细信息,包括示例代码和教程。

Paul R方法的一种变体

#include <iostream>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>

void show_cpu_info(void)
{
    char buffer[1024];
    size_t size=sizeof(buffer);
    if (sysctlbyname("machdep.cpu.brand_string", &buffer, &size, NULL, 0) < 0) {
        perror("sysctl");
    }
    std::cout << buffer << '\n';
}

将直接显示类似Intel(R) Core(TM)2 Duo CPU L9400 @ 1.86GHz

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM