分段机制和分页机制

330 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

首先我们需要搞清楚到底什么是并发,它在系统中又是以何种形式存在的。

分段机制

人们最早想到的一种解决方案是分段(segmentation)机制,其基本思想是把程序所需的内存空间的虚拟地址映射到某个物理地址空间中。 分段机制可以解决地址空间保护问题,进程A和进程B会被映射到不同的物理地址空间中,它们在物理地址空间是不会有重叠的。因为进程看到的是虚拟地址空间,不关心它实际映射到了哪个物理地址。如果一个进程访问了没有映射的虚拟地址空间,或者访问了不属于该进程的虚拟地址空间,那么CPU会捕捉这个越界访问,并且拒绝该次访问。同时CPU会发送一个异常给操作系统,由操作系统处理这些异常,这就是我们常说的缺页异常。另外,对于进程来说,它不再需要关心物理地址的布局,它访问的地址是虚拟地址,只需要按照原来的地址编写程序和访问地址,这样程序就可以无缝地迁移到不同的操作系统中了。 分段机制解决问题的思路可以总结为增加一个虚拟内存(virtual memory)。进程运行时看到的地址是虚拟地址,因此需要通过CPU提供的地址映射方法,把虚拟地址转换成实际的物理地址。这样多个进程同时运行时,就可以保证每个进程的虚拟内存空间是相互隔离的,操作系统只需要维护虚拟地址到物理地址的映射关系即可。 另外,分段机制把进程分成若干段,每个段的大小是不固定的。如一个进程可以分成代码段、数据段栈段与堆段等。分段机制有点类似于动态分区法,这些段的物理地址可以不连续,这样可以解决内存碎片问题,但是会产生外部碎片。程序员需要为每个进程的各个段合理分配物理地址空间,否则容易发生问题。 分段机制是一个比较明显的改进,但是它的内存使用效率依然比较低。分段机制对虚拟内存到物理内存的映射依然以进程为单位。也就是说,当物理内存不足时,通常做法是把这个进程的所有段都换出到磁盘,因此会导致大量的磁盘访问,从而影响系统性能。站在进程的角度来看,把整个进程进行换出/换入的方法还很麻烦。进程在运行时,根据局部性原理,只有一部分数据是一直在使用的,若把那些不常用的数据交换出磁盘,就可以节省很多系统带宽,而那些常用的数据驻留在物理内存中,因此可以得到比较好的性能。于是,人们在分段机制的实践之后又发明了新的机制,这就是分页(paging)机制。

分页机制

刚才提到分段机制的地址映射的粒度太大,以整个进程地址空间为单位的分配方式导致内存利用率不高。分页机制把这个分配机制的单位继续细分成固定大小的页面(page),进程的虚拟地址空间也按照页面来分割,这样常用的数据和代码就可以以页面为单位驻留在内存中。而那些不常用的页面可以交换到磁盘中,从而节省物理内存,这比分段机制要高效很多。进程以页面为单位的虚拟内存通过CPU的硬件单元映射到物理内存中,物理内存也以页面为单位来管理,这些物理内存称为物理页面(physical page)或者页帧(page frame)。进程的虚拟地址空间中的页面称为虚拟页面(virtual page)。操作系统为了管理这些页帧需要按照物理地址给每个页帧编号,这个编号称为页帧号(Page Frame Number,PFN)。

现在常用的操作系统中默认支持的页面大小是4KB,但是CPU通常可以支持多种大小的页面,如4KB、16KB以及64KB的页面。另外,现在的计算机系统内存已经变得很大,特别是服务器上使用以TB为单位的内存,所以使用4KB的内存页面会产生很多性能上的缺陷。主要的缺点是内存管理成本变得很高,操作系统需要管理这些物理内存的页帧,因此每个页帧都需要一个数据结构来描述,这个数据结构至少要几十字节。现代的处理器都支持大页面,如Intel的至强处理器支持以2MB和1GB为单位的大页面,以提高应用程序效率。 分页机制的实现离不开硬件的支持,在CPU内部有一个专门的硬件单元来负责这个虚拟页面到物理页面的转换,它就是一个称为MMU的硬件单元。ARM处理器的MMU包括TLB和页表遍历单元两个部件。