我的内存怎么了?

lea*_*ner 6 linux memory

我试图了解 Linux 操作系统的基础知识。我在 64 位 CPU 上运行 64 位 Ubuntu 12.04。该系统具有 2GB 的 RAM。

cat /proc/meminfo 
MemTotal:        2012040 kB
Run Code Online (Sandbox Code Playgroud)

问题一:85112KB 的内存缺失在哪里?

2097152 (2 gb in kilobytes)
2012040 -
______________
 85112
Run Code Online (Sandbox Code Playgroud)

这是保留用于其他用途还是这是系统无法使用 4% 的 RAM 的硬件限制?

问题 2:我的初步阅读告诉我用户内核空间有 3:1 的分割。为什么这里不是这样?

(3/4)*2097152 =1572864 for user space
(1/4)*2097152 =524288  for kernel space
Run Code Online (Sandbox Code Playgroud)

我知道 Linux RAM 缓存和缓冲区(我至少花了一些研究工作来理解这一点),但这种情况与此无关,那么发生了什么?

der*_*ert 9

你真的不应该把两个问题合二为一,但是……

问题 1

其中一些内存用于内核代码本身,一些是保留的,等等。内核在系统引导消息中吐出它:

[    0.000000] Memory: 6106920k/7340032k available (3633k kernel code, 1057736k absent, 175376k reserved, 3104k data, 616k init)
Run Code Online (Sandbox Code Playgroud)

“不存在”行是实际不存在的内存(这台机器目前安装了 6GiB 的 RAM)。内核还会吐出内存映射(这是在引导消息的较早部分):

[    0.000000] e820: BIOS-provided physical RAM map:
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009ebff] usable
[    0.000000] BIOS-e820: [mem 0x000000000009ec00-0x000000000009ffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000000e2c00-0x00000000000fffff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x00000000bf77ffff] usable
[    0.000000] BIOS-e820: [mem 0x00000000bf780000-0x00000000bf797fff] ACPI data
[    0.000000] BIOS-e820: [mem 0x00000000bf798000-0x00000000bf7d9fff] ACPI NVS
[    0.000000] BIOS-e820: [mem 0x00000000bf7da000-0x00000000bfffffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000ffe00000-0x00000000ffffffff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000100000000-0x00000001bfffffff] usable
Run Code Online (Sandbox Code Playgroud)

然后内核对该映射进行各种修复,通常会保留更多内存。尤其是在驱动程序加载时。

问题2

内核/用户拆分是虚拟地址空间,而不是内存。它在 64 位机器上几乎无关紧要,因为有太多的地址空间可供使用。

在 32 位机器上,虚拟地址 0x00000000–0xBFFFFFFF 用于用户地址空间。0xC0000000–0xFFFFFFFF 被内核使用(这是 3:1 分割,其他选项包括 2:2 分割。注意这些数字是千兆字节,所以它是 2:2 而不是 1:1)。虚拟地址也是特定于进程的(每个进程可以在 0x00001000 处有一个页面,它是一个不同的页面)。

但是一个虚拟地址并不对应一个字节的内存。它基本上可以由四件事来支持:

  1. 没有。该页面未在使用中。尝试访问它,得到段错误。
  2. 物理内存。MMU 将虚拟地址转换为某个物理地址,该地址实际上对应于某个 DIMM 上的电容器。
  3. 交换(或内存映射文件)。如果您访问它,就会出现页面错误,并且内核将在将数据读入内存时挂起您的进程(并可能将其他数据写入磁盘以腾出空间)。然后内核更新页表,把它变成情况#2。
  4. 零页。这是一个新分配的页面,尚未使用。当它是时,内核将找到一页物理内存(可能交换其他内容),用零填充它(为了安全),然后是情况 #2。

透明的大页面使更多的案例。可能还有一些不太重要的我也忘记了......

无论如何,我的 64 位芯片有一个 48 位的虚拟地址大小。我不确定内核使用什么分割,但即使它是一半,也有 47 位空间,远远超过 36 位物理地址大小。并且 131,072 GiB 的 RAM 太贵了……(而且,请记住,当它变得更便宜时,64 中还剩下很多位,未来的处理器可能只会允许更多位)。