9.8 存储器映射

主要知识点为写时拷贝,与fork函数execve函数

如下图:只要没有进程驶入写它自己的私有区域,它们就可以继续共享物理内存中对象的一个单独拷贝。然而,只要有一个进程试图写私有区域内的某个页面,那么这个写操作就会触发一个保护故障。

当故障处理程序注意到保护异常是由于进程试图写私有的写时拷贝区域中的一个页面引起的,它就会在物理存储器中创建这个页面的一个新拷贝。


通过延迟私有对象中的拷贝直到最后可能的时刻,写时拷贝最充分的使用了稀有的物理存储器。

9.8.2 再看fork函数

fork函数是如何创建一个带有自己独立虚拟地址空间的新进程的?

当fork函数被当前进程调用时,内核为新进程创建了各种数据结构,并分配给它一个唯一的PID。为了给这个新进程创建虚拟存储器,它创建了当前进程的mm_struct、区域结构和页表的原样拷贝。它将两个进程中的每个页表都标记为只读(读时共享),并将两个进程中的区域结构都标记为私有的写时拷贝。

当fork在新进程中返回时,新进程现在的虚拟存储器刚好和调用fork时存在的虚拟存储器相同。当这两个进程中任一个后来进行写操作时,写时拷贝机制就会创建新页表,因此,也就为每个进程保持了私有地址空间的抽象概念

9.8.3 再看execve函数

假设运行在当前进程中的程序执行了如下的调用:

execve("a.out", NULL, NULL);

execve函数在当前进程中加载并运行包含在可执行目标文件a.out中的程序,用a.out程序有效替代了当前程序。加载并运行a.out需要以下几个步骤

删除已存在的用户区域。删除当前进程虚拟地址的用户部分中的已存在的区域结构。

映射私有区域。为新程序的文本、数据、bss和栈区域创建新的区域结构。所有这些新的区域都是私有的,写时拷贝的。

映射共享区域。如果a.out程序与共享对象或目标链接,比如标准库,那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域中。

设置程序计数器(PC)。execve做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向文本区域的入口点。

【参考】
[1] 《深入理解计算机系统》

欢迎转载,转载请注明出处:wenmingxing 你好呀CSAPP

你可能感兴趣的:(9.8 存储器映射)