【问题标题】:virtual memory page replacement虚拟内存页面替换
【发布时间】:2012-04-04 02:21:15
【问题描述】:

众所周知,在所有帧都满了的情况下,分页的需求需要更换一些页面。但是,页面可以作为文本,rodata,数据,这些都是从磁盘I/O中调用的,但是页面这样一个程序的栈、堆只分配在内存中,在磁盘中没有副本。我想知道栈和堆的页面是否涉及页面替换,如果是,是否应该将它们临时交换到磁盘中?否则,是否应该将它们固定在内存中?可能这个问题和具体的实现密切相关,可以采取不同的策略,但是我很想知道通常的做法。

【问题讨论】:

    标签: memory-management operating-system x86 kernel


    【解决方案1】:

    所有用户模式页面都可以从 RAM 中删除。未经修改并由磁盘上的真实数据支持的页面(例如 DLL 和 EXE 的可执行和只读部分)简单地从内存中删除并请求分页回。所有其他页面都写入页面文件并请求分页回. 这包括堆栈、堆和 VirtualAlloc 的内存。

    靠近活动线程的堆栈内存往往不会被分页,因为它最近被访问过,因此由分页守护进程/APC 分页是一个糟糕的选择,但页面在调用堆栈和上经常挂起的线程被系统调出,当然不会固定在内存中。

    唯一的一般例外是内核堆栈。每个内核必须至少有一个永远不会被调出的内核堆栈,否则页面错误会导致处理器出现三倍故障并重新启动内核。

    另外,Linux 和 Windows 都有一个“非分页池”的概念,它是永远不会被分页的堆内存。这与“paged-pool”内存形成对比,后者根据需要由分页守护进程调出和调入。 (这种“非分页”内存是为页面错误守护进程本身、核心系统服务和分页守护进程工作所需的服务(例如文件系统驱动程序、内存管理器等)提供服务所必需的)

    【讨论】:

    • 如果一个程序的数据段由磁盘上的真实数据支持,如果被修改或脏了,它应该在哪里,它支持的交换或磁盘?
    • 一旦你的程序修改了它的初始化数据段,它就不再支持磁盘上的数据:它们的内容是不同的。因此,未修改的页面可能由文件中的程序图像支持,并且修改的页面总是会交换。
    • 程序的数据段被标记为copy-on-write和no-commit。这意味着在被触摸之前,数据由磁盘上的文件支持。在它被弄脏后,数据被复制到内存中,现在由页面文件支持。这与以读/写方式打开的内存映射文件形成鲜明对比,其中脏页被刷新回磁盘,而磁盘仍然支持这些页。
    【解决方案2】:

    这就是您需要交换或分页文件的原因。如果您有脏页(内存中的副本已被修改)但长时间未访问,则可以将它们占用的物理内存用于更有用的唯一方法是首先将它们写到磁盘.

    干净的页面(只包含零、没人关心的数据或存储在磁盘上的文件副本)可以简单地从内存中丢弃,然后用于其他目的。

    通常,唯一固定在内存中的页面是内核使用的页面或已被特权进程固定的页面。许多内核函数临时将内容固定在内存中,以便它们可以访问它们而不必担心页面错误。这些页面在内核返回用户空间之前被取消固定。

    这是一个通用答案,应该同样适用于所有主流现代通用操作系统。

    【讨论】:

    • 如果一个程序的数据段由磁盘上的真实数据支持,如果被修改或脏了,它应该在哪里,它支持的交换或磁盘?
    • 这取决于数据段的映射方式。通常它会被映射为 private,因此必须将更改写出以进行交换,并且文件本身不会被修改,只有该进程的映射页面。
    • 进程的页表怎么办,是固定在内存中还是替换到交换区?我猜应该是在内存中pin了,因为当需要替换休眠进程的一个页面时,相关的页表也应该被修改,因为如果替换掉到swap会产生冗余IO。以上所有问题都是基于假设进程页表存在于用户空间而不是内核空间,因为太多的进程占用了太多的内核空间。我说得对吗?
    • @venus.w:我不确定您所说的“内核空间过多”是什么意思。为什么内核空间会受到限制?你是说PAE吗? (您有什么特别的操作系统吗?)
    • :是的,我正在开发一个关于操作系统内核的项目,它限制在16M以内。你的意思是进程页表一般存在于内核空间中吗?
    猜你喜欢
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 2023-03-31
    相关资源
    最近更新 更多