您需要查看 IOKit API。 IORegistryExplorer 应用程序(标准 devtools 安装的一部分)将帮助您找到所需内容。
例如,在我的 MacBook Pro 上,在 IORegistryExplorer 中,我从窗口左上角的下拉菜单中选择“IODeviceTree”,我可以在下面的树视图中看到两个 CPU。选择其中任何一个都会得到以下信息:
IORegistryExplorer screenshot http://blog.alanquatermain.net/images/IORegistryExplorer-CPUs.png
'bus-frequency' 和 'clock-frequency' 和 'timebase-frequency' 都是数据对象中的 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) );
接下来,您可以使用通过包含<mach-o/arch.h> 获得的NXArchInfo() 调用来获取处理器信息。这将返回一个包含 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 位的值。它还将保存/恢复 %rbx 寄存器,即 %ebx 寄存器的 64 位版本。 理论上将涵盖所有基础。