xuh*_*dev 2 bash shell posix cpu-architecture
是否有一种可移植的方法可以在 shell 脚本中以可编程方式获取 POSIX 系统上的 CPU 供应商信息?特别是,我需要判断 x86_64/AMD64 CPU 是由 Intel 还是 AMD 出售的。该方法不一定适用于所有 POSIX 系统,但它应该适用于相当多的常见 POSIX 系统:GNU/Linux、MacOS 和 *BSD。例如,Linux 唯一的方法是从/proc/cpuinfo.
POSIX (IEEE Std 1003.1-2017) 不强制要求使用CPU 品牌的系统实用程序或 shell 变量。您将得到的最接近的是uname -m,它是“系统运行的硬件类型”。不幸的是,该命令不具有标准化的输出,因此,尽管你可能会得到amd64一些较老的机器,你会得到大部分i686或者x86_64这些天。
POSIX 确实要求c99,一个基本的 C 编译器接口,当 C 编译器可用时存在。你可以用它来编译一个简单的版本cpuid:
$ cat cpuid.c
#include <stdio.h>
#include <string.h>
#include <stdint.h>
int main() {
uint32_t regs[4] = { 0 };
char brand[13] = { 0 };
#ifdef _WIN32
__cpuidex((int *)regs, 0, 0);
#else
__asm volatile("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (0), "c" (0));
#endif
memcpy(&brand[0], ®s[1], 4);
memcpy(&brand[4], ®s[3], 4);
memcpy(&brand[8], ®s[2], 4);
printf("%s\n", brand);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在各种测试机器上,这是我得到的:
$ c99 -o cpuid cpuid.c && ./cpuid # MacOS X
GenuineIntel
$ c99 -o cpuid cpuid.c && ./cpuid # Intel-based AWS EC2 (M5)
GenuineIntel
$ c99 -o cpuid cpuid.c && ./cpuid # AMD-based AWS EC2 (T3a)
AuthenticAMD
Run Code Online (Sandbox Code Playgroud)
维基百科根据cpuid说明列出了许多其他可能的供应商品牌,但对于您定义的用例来说可能最有趣的是:
GenuineIntel - 英特尔AMDisbetter! - AMDAuthenticAMD - AMD如果您的路径中有这个简单的可执行文件,POSIX-y 逻辑将如下所示:
if cpuid | grep -q AMD; then
: # AMD logic here
elif cpuid | grep -q Intel; then
: # Intel logic here
else # neither Intel nor AMD
echo "Unsupported CPU vendor: $(cpuid)" >&2
fi
Run Code Online (Sandbox Code Playgroud)
如果您有一块非常非常旧的多核主板,那是 AMD 与 Intel 引脚等效的时代,那么您可能想知道 CPU0 和 CPU1 是否是同一个供应商,在这种情况下,可以修改上面的 C 程序检查处理器 1 而不是 0(相应 asm 函数的第二个参数)的装配线。
这说明了这种方法的一个特殊好处:如果您真正想知道 CPU 是否支持特定功能集(并且只是使用供应商作为代理),那么您可以修改 C 代码以检查 CPU 功能是否支持实际可用。这是对赋予汇编代码的 EAX 值的快速修改,以及对 E{B,C,D}X 结果寄存器解释的更改。
关于 的可用性c99,请注意:
POSIX的不符合系统c99证明,没有C编译器的该系统上可用。如果您的目标系统没有c99,那么您需要选择并安装 C 编译器(gcc、clang、msvc 等)或尝试使用例如/proc/cpuinfo.
该标准声明“与本标准中的所有其他非 OB 阴影实用程序不同,具有此名称的实用程序可能不会出现在本标准的下一版本中。此实用程序的名称与 ISO C 的当前版本相关联标准批准时的标准。由于 ISO C 标准和本标准由不同的组织按不同的时间表维护,我们无法预测编译器将在标准的下一版本中命名。” 因此,您应该考虑使用${C99:-c99} -o cpuid cpuid.c.