CSAPP : 内存映射

内存映射单独拿出来说,因为很有趣,不仅关系到共享库,还有fork等

什么叫内存映射?

  • linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,也就是一个文件到一块内存的映射。

共享对象

我们已经知道,进程这一抽象能够为每个进程提供自己私有的虚拟地址空间,但是如果许多进程有同样的只读代码区域呢?比如相同的库函数,如果每个进程拥有一份副本,那太浪费空间了,所以内存映射提供了机制来控制多个进程共享对象。


CSAPP : 内存映射_第1张图片
共享对象.png

写时复制

私有对象一开始与共享对象一样,在物理内存中只保留一份副本。进程中相应私有区域的页表条目都被标记为只读,并且区域结构被标记为私有的写时复制,只要没有进程试图写私有区域,那么就继续共享物理内存中的对象副本。一旦一个进程试图写私有区域内的某个页面,就会触发一个保护故障。
当故障处理程序发现保护异常时由于进程试图写私有的写时复制区域的一个页面引起的,就会在物理内存中创建这个页面的一个副本,更新页表条目指向这个新的副本,然后恢复这个页面的可写权限。
延迟私有对象的副本直到最后时刻,写时复制最充分的利用了稀有的物理内存

CSAPP : 内存映射_第2张图片
私有对象写时复制.png

fork函数

那么现在我们可以深刻理解fork函数了:
当fork函数被当前进程调用时,内核为新进场创建各种数据结构,并分配唯一的PID。为了给这个新进程创建虚拟内存,它创建了当前进程的mm_struct、区域结构和页表的原样副本。将两个进程中的每个页面都标记为只读,并将两个进程中的每个区域结构都标记为私有的写时复制。
当两个进程中的任一个后来进行写操作时,写时复制机制就会创建新页面,也就为每个进程保持了私有地址空间的概念。

execve函数

execve("a.out", NULL, NULL); //在当前进程中加载并运行a.out
以下几个步骤:

  1. 删除已存在的用户区域
  2. 映射私有区域,为新程序的代码、数据等创建新的区域结构,都是私有的写时复制的。
  3. 映射共享区域,把动态链接库映射到共享区域
  4. 设置程序计数器(PC),使之指向代码区域的入口点。

mmap函数

linux进程使用mmap函数来创建新的虚拟内存区域,并将对象映射到这些区域中。具体就不管啦。

你可能感兴趣的:(CSAPP : 内存映射)