13.1 进程的虚拟地址空间
每个进程都有自己的虚拟地址空间,如32进程,这个地址空间大小为4GB(2^32bytes)。因为进程都有自己的专有地址空间,进程中个各线程只能访问该进程的地址空间,而无法访问到其他进程的空间。但虚拟地址空间不是物理存储器,只是一个内存地址空间。 为了正常读写数据,要相应物理存储器分配或者映射到相应的地址空间。(注意一个地址位如0x00010001-0x00010000为一个byte,以字节为单位,因此一个int占四个地址位)
13.2 虚拟地址空间的分区
每个进程的虚拟地址空间被划分为多个分区。具体与操作系统底层实现有关。 以32位Windows为例:
空指针赋值分区: 用于帮助程序员对空指针的赋值。以任何方式试图访问该分区的地址,就会引发访问违规。
用户模式分区:进程的大部分数据都保存在这一分区。 普通的X86系统约为2GB。
内核模式分区: 这一分区是操作系统代码的驻地,如线程调度、内存管理、设备驱动等相关的代码都载入到该分区,这个分区占到整个地址空间的上半部分。 驻留这一分区的所有东西为所有进程共有。应用程序试图读写该分区的内存空间都会引发访问违规。
13.3 地址空间中的区域
系统页面:页面一个内存单元,系统通过页面来管理内存。在X86和X64系统中使用的页面大小为4KB。
13.4 给区域调拨物理存储器
为了使用预定的区域,必须分配物理存储器,并把存储器映射到分配的地址区域。 这个过程称为调拨(committing)物理存储器(始终以页面为单位来进行调拨),当不在需要该区域时,需要撤销调拨(decommitting)物理存储器。
13.5 物理存储器和交换页面
磁盘上的文件一般被称为交换文件(paging file),其中包含虚拟内存,可供任何进程使用。为了使用虚拟内存,搓澡系统需要CPU的大力协作。页面交换文件增大了应用程序可用内存总量,如机器内存为1G,而有1G的交换文件,这应用程序可用的内存总量为2G。实际是把内存的一部分保存在页面交换文件中,当需要的时候,再把交换文件的相应部分载入内存中。 交换文件是影响可用内存大小的重要因素。
当线程试图访问进程中地址空间中的一块数据时,会出现两种情况:
系统需要在内存和页交换文件之前复制页面的频率越高,硬盘颠簸(thrash)得月厉害,系统运行的越慢(系统把所有时间都用在页面交换文件与内存之间交换数据,从而没有时间运行程序)。
不在页交换文件中维护的物理存储器:
打开一个.exe文件时,系统计算应用程序代码和数据的大小,然后预定一块地址空间,并注明与该区域相关联的物理存储器就是该.exe文件本身,而不是从页交换文件中分配空间,这样就能快速载入程序,并且能够维持页交换文件维持在一个合理大小。把一个程序位于硬盘上的文件映像(即.exe ,dll)用作地址空间的对应物理存储器时,即称这个文件映像为内存映射文件(memory mapped file),当载入exe dll时,系统会自动预定地址空间区域,并把文件映像映射到该地址区域。
widows可以使用多个页交换文件,如果多个页交换文件位于不同物理硬盘时,系统运行速度更快,因为系统可以他同时写多个硬盘。
13.8 数据对齐的重要性
只有当访问已对齐的数据时,cpu的执行速度最快。把数据的地址摸除(A/B的余数)数据的大小结果为0时,即为对齐。CPU访问非对齐的数据时最好也要花两倍的时间。与让cpu捕获数据的错位并交给系统修正错位相比(可通过设置来抛出错位异常或者修正错位),让编译器生成额外代码来修正数据错位的效率要高得多。