在操作系统中,分段和分页是两种不同的内存管理技术,用于管理和分配进程的内存空间。它们的主要目标是提供对物理内存的有效和安全访问,但它们采用了不同的方法来实现这一目标。
大部分虚拟内存系统都会使用分页技术。分页技术把物理内存按照固定大小分为页面(一般是4KB)。通过分页,我们可以更细粒度的管理物理内存和虚拟空间的映射,也可以更高效的利用物理内存。对于一个64KB的虚拟地址和32KB的物理地址来说,如下图所示:
如果用户访问到的虚拟地址还没有分配物理地址,那么系统就会发生缺页中断。将需要访问的页面装载到页框中,修改MMU中的映射关系,重新返回。
对于虚拟地址和物理地址的映射关系的存储,我们一般是通过页表来完成的。页表中会记录虚拟地址的虚拟页号和偏移量,以及其对应的实际页框号。从数学角度说,页表是一个函数,它的参数是虚拟页号,结果是物理页框号。
同时,因为增加了页表的映射,中间就一定会有空间和时间的损耗,有两个问题:
1 . 虚拟地址到物理地址的映射需要时间,这个时候就需要引入快表 (TLB)加速页表的访问。
2 . 如果虚拟地址空间很大,页表也会很大,可能会浪费空间。假设64it的操作系统,虚拟地址的大小为2 ^ 64,如果每页是4KB,那么需要的记录数就是2^ 64/2^ 12=2^52项。同时,因为每个进程都有一个独立的虚拟地址,所以每个进程都有自己独立的页表,那么这种情况下,记录的项目就会变得非常多。
对于第二种情况,我们可以采用多级页表和倒排页表的方式来解决。
多级页表的核心就在于避免把所有的页表全部保存在内存中,如果是不需要的页表,就不会保留。倒排页表常用于64bit的计算机中,往往需要和TLB结合使用才可以。
有了分页之后,一个进程就可以享受很大的,独立的虚拟地址了。但是有一个问题我们没有考虑到,个进程中一定会包含代码,常量,以及代码在运行时所产生的变量。那么,用户的程序如何保证这些代码所在的空间不和代码运行时候的堆栈空间冲突呢?
如果我们知识简单的将虚拟内存按照一维的方式将空间分给这些堆栈,代码片段等,就很难保证空间的有效利用,如下图所示:
此时,我们发现,程序的堆栈空间已经用完了,但是代码段还有很多没有用。这个时候就需要程序手动管理这些一维空间,无疑的比较复杂且困难的。
所以就有了分段技术的产生。它可以让每个段独享一部分可以自然增长的空间,且和其他段相互隔离如下所示:
分页和分段在资源消耗方面有各自的特点,具体取决于使用场景和需求。
分段在某些方面可能更耗资源。例如,在分段系统中,程序员在编程和使用上有多方面的要求,而且存在外碎片问题,这可能导致性能损失。此外,分段中一个进程可占用多个“分区”,不要求一个进程占用的多个“分区”连续,这增加了管理的复杂性。
然而,分段克服了分页存在的问题,如数据结构的动态增长、动态链接、保护和共享等。因此,分段在某些方面可能更高效。
分页的优点在于没有外部碎片,最后一页可能有内碎片但不大。程序不必连续存放,便于改变程序占用空间大小。此外,分页可以缩短查找时间,提高访问速度。但分页可能会产生小的内碎片,且无论数据有多少,都只能按照页面大小分配,可能造成浪费。
综上所述,分段和分页各有优缺点,哪种更耗资源取决于具体的应用场景和需求。在实际使用中,它们通常会结合使用,以实现更好的内存管理功能。
分段和分页对性能的影响如下:
分段可以提高内存利用率,并方便实现信息的共享和保护。它允许程序按逻辑模块进行划分,方便了程序员的开发和使用。然而,分段也存在一些问题,如无法利用碎片、必须搬移内存等,这可能导致性能损失。
分页可以缓解内存压力,设计简单且效率高。它没有外部碎片,最后一页可能有内碎片但不大。程序不必连续存放,便于改变程序占用空间大小。此外,分页可以缩短查找时间,提高访问速度。但分页可能会产生小的内碎片,且无论数据有多少,都只能按照页面大小分配,可能造成浪费。
分段和分页各有优缺点,对性能的影响取决于具体的应用场景和需求。在实际使用中,它们通常会结合使用,以实现更好的内存管理功能。
分段和分页各有适用的场景:
分段适合于处理具有不同逻辑意义的程序,主要为了实现虚拟内存,获得更大的地址空间,从而使程序和数据可以被划分为逻辑上独立的地址空间,并有助于共享和保护。分段可以更好地实现共享,根据用户的需要划分,因此段对用户是可见的。
分页适合于处理大型程序,其中内存需求很高且需要随时调整内存大小的情况。分页是为了实现非连续分配,以便解决内存碎片问题,或者说分页是由于系统管理的需要,其对用户是透明的。
总的来说,分段和分页都是为了更好地管理内存和提高内存利用率,但它们的实现方式和主要目的有所不同。在实际使用中,它们通常会结合使用,以提供更好的内存管理功能。