在检查QEMU内存消耗时,我在aarch64服务器上观察到以下模式(主机和来宾运行centos 7.4都使用aarch64上的64K页面大小,以防万一):
| guest mem size | qemu RSS size |
+----------------+---------------+
| 1g | 868m |
| 4g | 2.2g |
| 8g | 2.8g |
| 16g | 2.8g |
来宾仅运行默认服务,启动后我会进行测量。以我的理解,Linux在那种状态下通常只占用几百兆字节,但是上面的数据表明QEMU消耗的内存远不止于此。
以4g内存为例,下面的free命令输出显示来宾OS使用约367m内存(144m“已用”加上222m“ buff /缓存”)。另一方面,QEMU在主机上消耗2.2g内存(请参见上表)。
# free
total used free shared buff/cache available
Mem: 4097088 147968 3721536 17344 227584 3482176
Swap: 4194240 0 4194240
我知道QEMU将内存用于来宾主内存以外的其他用途。例如,固件映射到内存。另外,它需要内存来实现设备。但是我不相信所有其他用途都会占用这么多内存。因此,我看一下QEMU进程内存映射,并找到了来宾主内存的内存块(其大小为4194304字节,对应于我使用的“ -m 4096” QEMU CLI选项):
# pmap -x $qemu-pid | grep 4194304
0000fffe63e00000 4194304 2179904 2179904 rw--- [ anon ]
请注意RSS字段。它的大小为2179904k字节,约为2.1g。这意味着QEMU消耗的大部分内存确实用于来宾主内存。
QEMU通过调用malloc()分配来宾主内存。由于malloc()仅创建映射但不分配内存,因此我进行了另一个实验来确定何时在主机中分配了大多数来宾主内存(换句话说,来宾在启动时如何在不同阶段访问其物理内存)上):
| guest start-up phase | qemu process | guest main memory |
| | RSS size | RSS size (in QEMU) |
|----------------------------------+--------------+--------------------|
| created but not running [1] | 169m | 1m |
| uefi started [2] | 311m | 139m |
| grub started [3] | 807m | 638m |
| kernel started [4] | 2.3g | 2.1g |
| all systemd services started [5] | 2.3g | 2.1g |
[1] I did this by using qemu -S option
[2] I did this by going into uefi shell
[3] This was when grub menu showed up
[4] I did this by going into systemd maintenence mode
[5] This was when the system was ready for user to log in
这表明,虽然固件确实访问了来宾物理内存的许多部分,但是来宾内核访问了更多内容。考虑到来宾OS最终仅使用约367m内存,Linux内核似乎占用了更多的物理内存。我的问题是,内核接触到物理内存的那些部分时到底在做什么?
注意:我考虑过使用perf mem命令来证明我的猜测。但这在我的aarch64系统上不起作用。而且,它无法解释原因。