我正在读一本关于Linux如何管理私有对象的教科书,如下图所示:
该图显示了两个进程将一个私有对象映射到其虚拟内存的不同区域,但共享该对象的相同物理副本的情况。对于映射私有对象的每个进程,相应私有区域的页表条目被标记为只读,并且区域结构被标记为私有写时复制。一旦进程尝试写入私有区域中的某个页面,该写入就会触发保护错误。当错误处理程序注意到保护异常是由尝试写入私有复制中的页面引起的时,写区域,它在物理内存中创建该页的新副本,更新页表条目以指向新副本,然后恢复该页的写权限
我们知道Linux使用vm_area_struct
(area structs)来表征当前虚拟地址空间的一个区域为:
我认为vm_flags
私人区域将设置为“私人”,以便写入时复制可以工作
我的问题是,假设进程 2 的虚拟内存中私有对象的私有区域称为pa2
。因此,一开始,进程 2 尝试在 中写入一个页面(假设起始虚拟地址是0x404000
)pa2
,这会触发保护错误,然后对其进行处理并在物理内存中创建该页面的新副本。假设一段时间后,程序需要0x404000
再次修改从处开始的页面,由于pa2
仍然是私有区域,因此会触发另一个保护错误,然后在物理内存中创建该页面的另一个新副本,但是第一个新页面呢?在第一个故障处理程序期间创建?它不再被虚拟地址引用,仍然驻留在物理内存中,这是否浪费资源?
答案1
当发生页面错误时,如果内核确定在写时复制场景中写入失败,并且该页面至少有两个用户,则会将原始页面复制到新页面(如您所描述的),并且它使新页面可写。所属进程对同一页面的后续写入不会导致任何页面错误。