例如,我有一个宿主操作系统(比如Ubuntu),启用了KVM(虚拟机管理器)。我使用QEMU开始创建一个虚拟机,来运行一个客户操作系统(比如CentOS)。据说对于宿主操作系统而言,这个虚拟机只是一个进程。所以在宿主的角度看来,它会像往常一样处理页面错误(例如,根据需要分配页面框架,根据活跃/非活跃列表交换页面)。
以下是问题和我的理解。在客户操作系统内部,由于它仍然是一个完整的操作系统,我认为它仍然具备处理虚拟内存的所有机制。它看到了QEMU提供的某些虚拟化物理内存。所谓虚拟化的物理内存,我指的是客户操作系统不知道自己在一个虚拟机中,而是像在真实物理机器上一样工作,但它所拥有的确实是QEMU提供的一个抽象层。因此,即使分配了一个页面框架,如果该框架不在客户操作系统的页表中,客户操作系统仍然会触发页面错误,然后将某些页面映射到框架上。更糟糕的是,可能会出现双重页面错误,在此情况下,客户操作系统首先在页面错误时分配一些页面框架,然后触发宿主操作系统的页面错误。
然而,我也听说过像浅表(或影子)页表这样的东西,似乎可以优化这种不必要的双重页错误和双重页表问题。我还查看了一些其他内核实现,特别是unikernels,例如 OSv、IncludeOS 等等。我没有找到与页面错误和页面表机制有关的任何内容。我确实看到了一些符号,如
在这个主题上有什么想法吗?或者如果您有一些好的参考/论文/资源来解决这个问题,或者一些提示将非常有帮助。
以下是问题和我的理解。在客户操作系统内部,由于它仍然是一个完整的操作系统,我认为它仍然具备处理虚拟内存的所有机制。它看到了QEMU提供的某些虚拟化物理内存。所谓虚拟化的物理内存,我指的是客户操作系统不知道自己在一个虚拟机中,而是像在真实物理机器上一样工作,但它所拥有的确实是QEMU提供的一个抽象层。因此,即使分配了一个页面框架,如果该框架不在客户操作系统的页表中,客户操作系统仍然会触发页面错误,然后将某些页面映射到框架上。更糟糕的是,可能会出现双重页面错误,在此情况下,客户操作系统首先在页面错误时分配一些页面框架,然后触发宿主操作系统的页面错误。
然而,我也听说过像浅表(或影子)页表这样的东西,似乎可以优化这种不必要的双重页错误和双重页表问题。我还查看了一些其他内核实现,特别是unikernels,例如 OSv、IncludeOS 等等。我没有找到与页面错误和页面表机制有关的任何内容。我确实看到了一些符号,如
page_fault_handler
,但并不像在 Linux 内核代码中看到的那么庞大。这些unikernel实现中似乎内存管理并不是一个大问题。因此,我认为QEMU/KVM和一些英特尔的虚拟化技术已经处理了这个问题。在这个主题上有什么想法吗?或者如果您有一些好的参考/论文/资源来解决这个问题,或者一些提示将非常有帮助。