【问题标题】:Determine CPU type / architecture in macOS确定 macOS 中的 CPU 类型/架构
【发布时间】:2020-11-22 15:38:00
【问题描述】:

随着即将推出的 Apple Silicon 硬件,一些应用可能想要确定 CPU 是 Intel 还是 Apple 的。

哪些 API 和系统调用可以提供该信息?

作为@MarkSetchell points outsysctl -a 可以提供一些信息。对于 DTK (macOS 11b3),它返回:

machdep.cpu.brand_string: Apple processor

OTOH,Apple 的 System Profiler.app 显示:

Processor Name: Apple A12Z Bionic

我喜欢有类似的结果,即“Apple A12Z Bionic”而不是“Apple 处理器”。

在系统卷上快速搜索“Apple A12Z Bionic”显示它出现在“dyld_shared_cache_arm64e”中的某个位置,但不在System Profiler.app 中,这表明该字符串是由框架函数提供的,而不是硬-在 Profiler 应用程序中编码。因此,我希望找到提供这个更具描述性名称的系统调用。

【问题讨论】:

标签: macos apple-silicon


【解决方案1】:

我的 Swift 5.x 两分钱(在 Mac、iOS 和....(NDA 规则..)中测试)

func CPUType() ->Int {
    
    var cputype = UInt32(0)
    var size = cputype.byteWidth
    
    let result = sysctlbyname("hw.cputype", &cputype, &size, nil, 0)
    if result == -1 {
        if (errno == ENOENT){
            return 0
        }
        return -1
    }
    return Int(cputype)
}


let CPU_ARCH_MASK          = 0xff      // mask for architecture bits

let CPU_TYPE_X86           = cpu_type_t(7)
let CPU_TYPE_ARM           = cpu_type_t(12)

func CPUType() ->String {
    
    let type: Int = CPUType()
    if type == -1 {
        return "error in CPU type"
    }
    
    let cpu_arch            = type & CPU_ARCH_MASK
    
    if cpu_arch == CPU_TYPE_X86{
        return "X86"
    }
    
    if cpu_arch == CPU_TYPE_ARM{
        return "ARM"
    }
    
    return "unknown"
}

// 附件f.:

extension FixedWidthInteger {
    var byteWidth:Int {
        return self.bitWidth/UInt8.bitWidth
    }
    static var byteWidth:Int {
        return Self.bitWidth/UInt8.bitWidth
    }
}

【讨论】:

  • 您的代码中有一个小错误。你错误地使用了面具。你屏蔽它的方式,你需要屏蔽低 24 位,而不仅仅是你屏蔽的 8 位。我代码中的 0xff000000 掩码用于获取拱位。虽然您的代码目前有效,但由于所有代码仍低于 256,它并不像 Apple 所希望的那样真正正确。
  • 天啊...我会修复的。 ;(
【解决方案2】:

正如 cmets 建议的那样,sysctl 函数可用于识别 CPU 类型(但不提供我正在寻找的“Apple A12Z Bionic”文本)。

这是一个代码示例:

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

int main(int argc, const char * argv[]) {
    uint32_t cputype = 0;
    size_t size = sizeof (cputype);
    int res = sysctlbyname ("hw.cputype", &cputype, &size, NULL, 0);
    if (res) {
        printf ("error: %d\n", res);
    } else {
        printf ("cputype: 0x%08x\n", cputype);
    }
    return 0;
}

这在 Intel Mac 上打印 0x00000007,在 Apple Silicon DTK 上打印 0x0100000c(自 BigSur beta 3 起)。

最高有效字节中的01 是表示ARM 64 位系统的标志。定义在machine.h:

#define CPU_ARCH_MASK           0xff000000      /* mask for architecture bits */
#define CPU_ARCH_ABI64          0x01000000      /* 64 bit ABI */
#define CPU_ARCH_ABI64_32       0x02000000      /* ABI for 64-bit hardware with 32-bit types; LP32 */

#define CPU_TYPE_X86            ((cpu_type_t) 7)
#define CPU_TYPE_ARM            ((cpu_type_t) 12)
#define CPU_TYPE_ARM64          (CPU_TYPE_ARM | CPU_ARCH_ABI64)
#define CPU_TYPE_ARM64_32       (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)

另请参阅:macOS CPU Architecture (Ohanaware)

【讨论】:

  • 请不要写 if (cputype).. 正如苹果所说:“永远不要假设 BOOL 的数值不是 0 或 1。”在:developer.apple.com/documentation/apple_silicon/…
  • 哦,但是根据 C 的定义,“if (x)”测试 != 0,所以这完全没问题。另外,您的意思是“如果(res)”,而不是“如果(cputype)”,对吗?例如,Apple 的意思是你不应该假设 BOOL 可以是 -1。在这方面,我正在做最安全的测试。而且我的测试甚至不涉及 BOOL 类型。所以,一切都很好。
  • 我一直以为你,-33 mena TRUE(因为 CPU 会考虑零标志,但 Appel 通知确实吓到我了 :))
  • 似乎这个 sysctl 函数在 Rosetta 下以编程方式返回类型 0x00000007 (X86) 而不是命令行生成的类型 0x0100000C (ARM64)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 2011-03-20
  • 2011-09-13
  • 2011-01-02
  • 1970-01-01
  • 2022-01-14
相关资源
最近更新 更多