当程序调用mmap分配匿名页(也称为需求零页)时,对应的页表条目(PTE)的地址字段中会出现什么?我假设内核不会在物理内存中创建一个初始化为零的页面(并在PTE中输入物理页面的页码),直到请求进程实际接触到该页面--因此术语demand--为零。因为它不会是磁盘地址,也不会是0(对于未分配的页面),那么会出现什么值呢?作为一个不同但相关的问题,内核如何“知道”此页将作为需求零页处理,即错误处理程序应该找到一个物理页并用0初始化它,而不是从磁盘复制一个页面?
发布于 2021-11-24 17:48:57
我假设内核不会在物理内存中创建一个零初始化的页面。
事实上,情况通常是这样的。除非是特殊情况,例如,如果指定MAP_POPULATE来显式请求要初始化的页面(也称为“pre”)。
对应的页表条目(PTE)的地址字段中显示了什么?
在mmap之后,您甚至没有为页面分配PTE (或者通常,您在任何页面表级别上都没有任何条目)。对于CPU而言,页面甚至不存在。如果您要遍历页面表,您只需到达一个点(在任意级别上),其中相应的条目被标记为“不存在”。
因为它不会是磁盘地址,也不会是0(对于未分配的页面),那么会出现什么值呢?
对于CPU而言,页面是未分配的。在第一页出错时,可能会发生两件事:
直接引用文献资料
匿名内存或匿名映射表示没有文件系统支持的内存。这些映射是为程序的堆栈和堆隐式创建的,或者是通过对mmap(2)系统调用的显式调用创建的。通常,匿名映射只定义程序允许访问的虚拟内存区域。读取访问将导致创建一个引用填充了零的特殊物理页的页表条目。当程序执行写操作时,将分配一个常规的物理页来保存所写的数据。该页将被标记为脏,如果内核决定重新使用它,则脏页将被交换掉。
内核如何“知道”此页将作为需求零页处理,即错误处理程序应该找到一个物理页并用0初始化它,而不是从磁盘复制一个页面?
当发生页面错误时,内核页错误处理程序(依赖于体系结构)确定该页属于哪个struct vm_area_struct,并检索相应的mmap (这是由内核本身或由mmapsyscall创建的)。然后,该结构与所需的故障信息(struct vm_fault)一起传递给与体系结构无关的代码(struct vm_fault)。
然后,vm_area_struct包含处理故障所需的所有剩余信息(例如,在文件支持的映射情况下,->vm_file字段是!= NULL )。字段->vm_ops指向一个struct vm_operations_struct,它定义了在不同情况下调用的一组函数指针。特别是匿名VMA有->vm_ops == NULL。
对于其他类型的页面,->fault()是处理页面错误时使用的函数。这个函数知道要检查什么,以及如何实际处理错误。
B&O也描述了VMA,但不要解释内核如何使用VMA来区分未分配的页面和要创建的分配页面以及零初始化的页面。
简单来说,只需检查vma->vm_ops == NULL,在这种情况下,您就知道页面是一个需求为零的页面。然后根据需要在页面上执行错误操作(读取故障->更新PTE以指向全局零页,编写故障->分配页面和更新PTE)。
https://stackoverflow.com/questions/70090432
复制相似问题