内存管理之内存分配

连续分配方式

     连续分配方式指的是为一个用户程序划分为连续的内存空间。可以把连续分配方式进一步分为单一连续分配、固定分区分配、动态分区分配和可重定位分区分配四种方式。

1.单一连续分配

       在单道程序系统中,任何时刻只有一个用户程序驻留在内存。内存被划分两部分:系统区(供操作系统使用)和用户区(用来存储用户程序和数据)。

2.固定分区分配 

       单一连续分配只能存一个程序,为了能同时存储多个用户程序,将内存分为多个分区,每个分区的大小固定,这就是所谓的固定分区分配。这些分区大小在操作系统初始化的时候就确定了,每个分区只能存放一个用户程序。固定式分区可以两种方式:各分区大小相同和分区大小不同。为了对分区进行分配和管理,通常按照分区大小的排队,并为之建立一张分区使用表。当用户程序需要分配内存空间的时候,系统检索该表,从表中找到一个大小满足要求且没有被分配出去的分区,分配给用户程序。这个分配方式的缺点是会产生内碎片,因为分区固定,分配给用户的内存空间不是恰好匹配,这样就产生内碎片。

3.动态分区分配

      为了减少内碎片,同时提高系统的利用率,人们提出了动态分区的概念。所谓动态分区是指事先先划定分区的大小,根据进程的大小动态的为之分配内存。为了实现动态分配,系统中必须配置相应的数据结构,用来描述空闲分区和已分配分区,为分配提供依据。常用的数据结构:空闲分区表和空闲分区链(双向链表,每个分区的起始部分设置一些分区信息和前向指针,每个分区的尾部设有后向指针)。

      某个进程需要内存时,系统必须要找到能够满足需求的一个分区,通常满足需求的可能不止一个,具体分配哪一个由不同的分配策略来决定:

     (1)首次适应算法(first-fit):从链表头开始查找,分配找到的第一个满足要求的分区。缺点是低地址充分利用,高地址很空。随着作业的增多,地址留下很多碎片。

     (2)下次适应算法(next-fit):不是从头查找,而是从上次查找的地方继续往下查找。

     (3)最佳适应算法(best-fit):总是给内存请求者分配最适合它大小的空闲分区,提高内存利用率。实验表明,这种方法最差,因为会导致很多的内碎片。

     (4)最坏适应算法(worst-fit):对任何给定的请求都使用当前可用的最大分区。

4.可重定位分区分配

       这种分配方式在动态分区分配的基础上加上了内存紧凑技术。

       连续分配方式中要求作业存放在一个连续的内存空间中。当内存中没有足够大的空间满足用户的请求时,这时可内存中一些小的内存空间合并成一个大的空间,这种技术叫作内存紧凑技术。实现这种技术把已占有空间挪到一起,没被占有的碎片空间挪到一起组成一个大的空间,这样就能满足用户的请求。

       这种技术需要动态重定位技术配合,即一个作业装入内存后所有的地址仍然是相对地址,在执行时转换为绝对地址,即作业的地址可以在内存中随时移动。这样在内存的紧凑的时候只需要改变重定位寄存器能将作业的起始地址改变。


基本分页分配方式

       分页存储管理将作业的逻辑地址划分一系列同等大小的页,将各个页从0开始编码。同时将内存也划分同样大小的连续空间,称之为块或页框。只有内存中有足够多的页框就能够存下用户作业,各页框可以不相邻。页框的大小应该始终(512B-8KB)。

       分页系统中的地址结构由两部分组成:页号和页偏移量。

       在分页系统中,页的存放可以是连续的也可以是不连续的,这就增加了逻辑地址到物理地址的难度因为不连续。为此,系统为每个进程创建了一个页表,在逻辑空间中的每一页,依次在页表中有一个表项,记录了对应的物理块号。看下图:


注:上面的转换是由硬件完成的,由专用的寄存器 (页表寄存器),而加法只是一个拼接,高20位物理页号与低12位偏移量拼接成最后的物理地址。

       从上面的分析可以发现地址变换的第一步就是检索页表。为了实现快速检索页表,最好把页表放在寄存器中,每个表项用一个寄存器实现。如果每页的大小为4KB,则32位地址将有1M个页面,即有一个1M个页表项,每个页表项如果占1B,则页表将占用1MB。系统中设有一个页表寄存器,存储了页表的开始地址和页表长度。平时进程未执行的时候,页表的开始地址和页表的长度存放在PCB中,当进程运行时,将这两个数据导入到页表寄存器。

       由于页表时放在内存中的,那么访问一次数据需要两次访问内存,第一次访问页表,第二次找到对应的物理块号与偏移量拼接形成物理地址。 为了提高速率,在地址变化机构中增加一个TLB(所谓的快表),用来存放当前访问过页表项。给定一个地址首先在快表中查找,找不到才转向页表查找。

       由于页表占有1MB,且页表的空间是连续存储的,这显然是不对的。解决的办法是对把页表看出普通的文件,对页表再分页存储就形成了所谓的多级页表。但是随着页表的分页级数增加,访问内存的次数也就要增加,这样会增加系统的开销,所以慎重。下面是一个二级页表的图:


       另外,页面选择不易过大(内碎片严重),不易过小(访问内存的次数就增加了)。


基本分段分配方式

       分页存储管理可以实现内存利用率的提高,但是一个独立的逻辑段被离散的放在很多物理块中,很多时候程序员希望把一个程序按照它的逻辑结构存放。

       一个程序的逻辑段在程序运行过程中有的大小会发生变化,例如数据段和堆段。而有的逻辑段的大小运行过程中不发生变化,如代码段。在分页存储管理方式中,对于随时动态增大的段的存储管理是非常困难的,一旦涉及到段的增大涉及到重新分配物理块,那么就涉及增加页表的修改过程。(说简单点,分别建立来了数据段,代码段,堆栈段)

     分页系统中,过程被一个一个紧紧的存放在一起,中间没有空隙。这就导致修改一个过程的大小会影响到其他地的起始地址,进而需要修改所有调用被移动的进程,以使它们访问指向这些过程的新地址。同样,在分页系统中,一个逻辑段可能存放n个物理块中,如果几个程序共享这段代码,需要在每个程序填加相应的表项,增加开销。

       分段存储系统中,逻辑地址包括段号和段偏移量。


       分段系统中,系统为每个分段分配一个连续的分区,进程的各个段可以离散地装入内存中的不同的分区中。为了实现逻辑地址到物理地址的转换,在系统中为每个进程建立一个段表。(逻辑地址到物理地址转换跟分页系统一样,只不过查找的是段表)

       分段系统通过不同进程段表中的行指向同一段地址来实现代码的共享。(段的大小是不固定的)。


注:假若共享一个160K代码,如果有10个用户程序需要共享这段代码。在分页系统中,这个共享代码有40个页表项(假设每页大小4K),则每个用户程序需要添加40个页表项,则总共要添加40*10 = 400个表项。而如果是分段系统的话,只需要额外的添加10个段表项就行了。是不是节省了空间。


段页式分配方式

       在段页式存储管理中,用户地址空间被划分为多个段并每个段予一个段名,对每个段在划分为多个固定大小的页,页大小就是主存中物理块的大小。

       在段页式系统中,地址由段号、段内页号和页内地址。


       在段页系统中,为了将逻辑地址转换为物理地址,需要查找段表和段内页表。段表中存放的页表的起始地址和页表长度。在段内系统中为了获得一条指令或者数据,需要三次访问内存。为了提高执行速度,在地址变化机构中增加一个高速缓冲寄存器,每次访问它时,都续同时利用段号和页号去检索高速缓冲。找不到匹配项时,按照正常的段表-》页表顺序去查找。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值