我在 OS X Yosemite 上运行了以下代码:
unsigned long num_;
sysctl((int[]){CTL_HW, HW_PHYSMEM}, 2, &num_, &len, NULL, 0);
printf("AMT MEM: , %lu\n", num_);
并回来140735340871680
这没有意义:(在 IPython 3 中)
In [3]: mem / (1024 ** 3)
mem / (1024 ** 3)
Out[3]: 131070.0
因为我有 16 GB 物理内存。我查看了标题sysctl.h
并看到
#define HW_PHYSMEM 5 /* int: total memory */
#define HW_USERMEM 6 /* int: non-kernel memory */
所以现在这真的没有意义,如果我通过了我可以相信这个数字HW_USERMEM
,但我特意要求了总内存。是什么赋予了?
我在 Python 代码中犯了一些愚蠢的数学错误吗?
答案1
我在 Python 代码中犯了一些愚蠢的数学错误吗?
实际上,这是你的C代码错误的。
对代码最直接的修复是这样的:
#include <stdio.h>
#include <sys/sysctl.h>
int main(void)
{
int64_t bytes;
size_t len = sizeof(bytes);
sysctl({ CTL_HW, HW_PHYSMEM64 }, 2, &bytes, &len, NULL, 0);
int megs = bytes / 1024 / 1024;
printf("AMT MEM: %d MiB\n", megs);
}
如果您HW_PHYSMEM
改为使用,它仅适用于 RAM 高达 2 GiB 的计算机,因为它将字节计数存储到假定大小为 32 位的变量中。对 64 位参数的更改需要新sysctl
值以避免破坏向后兼容性。这就是为什么 OpenBSD 的sysctl(3)
手册页说HW_PHYSMEM
已经过时了。
我在上面的代码中做了一些改动。我正在 C 代码中进行部分数学运算,这样我就可以读取输出,而无需通过计算器进行输入。我还修复了几个整数类型警告,并将变量重命名num_
为bytes
以便清楚起见。
该代码在某些 BSD 上运行良好,但不能在 OS X 或 FreeBSD 上运行。
在查看 OS X 手册页时,他们似乎希望您使用sysctlbyname(3)
反而。这在优胜美地这里工作得很好:
#include <stdio.h>
#include <sys/sysctl.h>
int main(void)
{
int64_t bytes;
size_t len = sizeof(bytes);
sysctlbyname("hw.memsize", &bytes, &len, NULL, 0);
int megs = bytes / 1024 / 1024;
printf("AMT MEM: %d MiB\n", megs);
}
我有 16 GiB 的物理 RAM,它正确报告 16384 MiB。
但是,如果您在 FreeBSD 上尝试这样做,您将得到 0 作为答案。稍微打探一下就会发现它想要hw.physmem
相反。
我们再一次碰壁了,因为尝试那 sysctlbyname
OS X 上的 value 给出了您发现的那种虚假结果。
因此,最根本的答案是,所有这些都是高度特定于系统的。如果您需要它是跨平台的,您将需要大量的#ifdefs
.
脚注:
抱歉,我还没有把 2 的幂记成十亿。 :)
在 OpenBSD 5.5 和 NetBSD 6.0.1 上测试。