进程地址空间 及 页表 详解

进程地址空间:系统中每个用户空间进程所看到的内存。
Linux操作系统采用虚拟内存技术,系统中的所有进程之间以虚拟方式共享内存。

地址空间

进程地址空间由进程可寻址的虚拟内存组成,内核允许进程使用这种虚拟内存中的地址。
每个进程都有一个32位或64位的平坦地址空间,空间大小取决于体系结构。(平坦指一段独立的连续区间)

内存地址是一个给定的值,要在地址空间范围之内。
尽管一个进程可以寻址4GB(2^32)的虚拟内存,但这并不代表它就有权访问所有的虚拟地址。
可被访问的合法地址空间称为内存区域。
通过内核,进程可以给自己的地址空间动态地添加或减少内存区域。
进程只能访问有效内存区域内的内存地址。
如果一个进程访问了不在有效范围中的内存区域,或以不正确的方式访问,内核会终止该进程,并返回"段错误"信息。

进程地址空间中的任何有效地址都只能位于唯一的区域,这些内存区域不能相互覆盖。
在执行的进程中,每个不同的内存片段都对应一个独立的内存区域:栈、对象代码、全局变量、被映射的文件等。
进程地址空间 及 页表 详解_第1张图片

内存描述符

内核使用内存描述符结构体表示进程的地址空间(唯一对应),该结构包含了和进程地址空间有关的全部信息。
内存描述符由mm_struct结构体表示。

内核通常会避免使用两种数据结构组织同一种数据,但在这里有冗余。
mmap结构体作为链表,利于简单、高效地遍历所有元素;mm_rb结构体作为红黑树,适合搜索指定元素。O(lg n)
内存区域由vm_area_struct结构体描述。
即使两个独立的进程将同一个文件映射到各自的地址空间,都会有一个vm_area_struct结构体来标志自己的内存区域;
反过来,如果两个线程共享一个地址空间,那么它们也同时共享其中的所有vm_area_struct结构体。

内存区域的树形结构和链表结构

内核为了内存区域中的各种不同操作都能获得高性能,同时使用了mmap和mm_rb两种数据结构。
mmap域使用单独链表链接所有的内存区域对象,用于需要遍历全部节点。
mm_rb域使用红黑树连接所有的内存区域对象,适用于在地址空间内中定位特定内存区域的时候。

页表

当程序访问一个虚拟地址时,首先必须将虚拟地址转换为物理地址,然后处理器才能解析地址访问请求。
地址的转换工作需要通过查询页表才能完成,概括地讲,地址转换需要将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表,而页表项指向下一级别的页表或者指向最终的物理页面。
Linux中使用三级页表完成地址转换(线程会共享页表),利用多级页表能够节约地址转换需占用的存放空间。(最大公约数)
进程地址空间 及 页表 详解_第2张图片
顶级页表是页全局目录(PGD),包含了一个pgd_t类型的数组,页表项指向二级页目录中的表项:PMD
二级页表是中间页目录(PMD),它是个pmd_t类型数组,页表项指向PTE中的表项
最后一级页表简称页表,包含了pte_t类型的页表项,指向物理页面。

多数体系结构都实现了一个翻译后缓冲器 TLB 。TLB作为一个将虚拟地址映射到物理地址的硬件缓存,当请求访问一个虚拟地址时,处理器首先检查TLB是否缓存了该虚拟地址到物理地址的映射,如果在缓存中直接命中,物理地址立即返回;否则,就需要通过页表搜索需要的物理地址。

你可能感兴趣的:(linux)