解释 sysctl 中的“丢失内存”

解释 sysctl 中的“丢失内存”

我在 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相反。

我们再一次碰壁了,因为尝试 sysctlbynameOS X 上的 value 给出了您发现的那种虚假结果。

因此,最根本的答案是,所有这些都是高度特定于系统的。如果您需要它是跨平台的,您将需要大量的#ifdefs.


脚注:

  1. 抱歉,我还没有把 2 的幂记成十亿。 :)

  2. 在 OpenBSD 5.5 和 NetBSD 6.0.1 上测试。

相关内容