文章目录
- 3.1_9 基本分段存储管理
- (一)分段
- (二)段表
- (三)地址变换
- (四)分段、分页管理的对比
- 总结
3.1_9 基本分段存储管理
(一)分段
进程的地址空间:按照程序自身的逻辑关系划分为若干个段,每个段都有一个段名(在低级语言,如汇编语言中,程序员使用段名来编程),每段从0开始编址。
内存分配规则:以段为单位进行分配,每个段在内存中占据连续空间,但各段之间可以不相邻。
由于分段存储管理当中,是按照逻辑功能模块划分,因此用户编程会更加方便、程序的可读性会更高。
在采用了分段之后,逻辑地址结构就变成了如下形式。
分段系统的逻辑地址结构由段号(段名)和段内地址(段内偏移量)所组成,如:
段号的位数决定了每个进程最多可以分几个段。
段内地址位数决定了每个段的最大长度是多少。
在上述例子中,若系统是按字节寻址的,则:
段号占16位,因此在该系统中,每个进程最多有 2 16 = 64 K 2^{16}=64K 216=64K个段。
段内地址占16位(不要忘了系统是按字节编址的),因此每个段的最大长度是 2 16 = 64 K B 2^{16}=64KB 216=64KB。
(二)段表
程序分多个段,各段离散地装入内存,为了保证程序能正常运行,就必须能从物理内存中找到各个逻辑段的存放位置。为此,需为每个进程建立一张段映射表,简称“段表”。
与“页表”原理一样,只不过段表是记录了各个逻辑段到实际的物理内存存放位置之间的映射关系。
1.每个段对应一个段表项,其中记录了该段在内存中的起始位置(又称“基址”)和段的长度。
在分页存储管理中,每个页面的长度肯定都是一样的,所以页长是不需要显式记录的。但是在分段存储管理当中,段的长度是需要这样显式地记录在段表当中的。
2.各个段表项的长度是相同的。例如:某系统按字节寻址,采用分段存储管理,逻辑地址结构为(段号16位, 段内地址16位)
,因此用16位即可表示最大段长。物理内存大小为4GB(可用32位表示整个物理内存地址空间)。因此,可以让每个段表项占16+32=48位,即6B。由于段表项长度相同,因此段号可以是隐含的,不占存储空间。若段表存放的起始地址为M,则K号段对应的段表项存放的地址为M + K*6
。
(三)地址变换
在内存的系统区当中,存放着很多用于管理系统软硬件资源的结构,包括进程控制块PCB。当一个进程要上处理机运行之前,进程切换相关的内核程序会把进程运行环境给恢复。——其中就包括一个很重要的硬件寄存器当中的数据的恢复,这个寄存器叫做段表寄存器,用于存放这个进程对应的段表在内存中的起始地址,还有这个进程的段表长度。——因此,段表的起始地址、段表长度这两个信息,在进程还没有上处理机运行的时候,是存放在进程PCB当中的。当进程上处理机运行的时候,这两个信息会被放到段表寄存器中,段表寄存器是很快的。
当获取段表始址、段表长度之后,就能知道段表具体存放在内存当中的什么地方。
接下来,在进程运行的过程中,避免不了地要访问一些逻辑地址。
第一步,对于一个给定的逻辑地址A,系统会从中截取得到段号S和段内地址W。
第二步,知道了段号之后,需要用段号和段表长度进行一个对比,来判断一下段号是否产生了越界,如果
段号 ≥ 段表长度
的话,就会产生越界中断;如果没有产生中断的话,就会继续执行下去。(需要注意的是:段表长度至少是1;而段号是从0开始的。所以当S = M
的时候,也是会引起越界中断的)第三步,根据段表始址和段号,就能找到段号对应的段表项。(由于段表项的长度是相同的,因此,通过
段表始址F + 段号S * 段表项长度
即可得到段号对应的段表项在内存当中的位置)就可以读出这个段表项的内容。第四步,在找到段号对应的段表项之后,系统还会用逻辑地址当中的
段内地址W
,与段表项当中的段长C
进行比较,看看要访问的段内地址是否超过了这个段的最大段长。若W ≥ C
,则产生越界中断,否则继续执行。(注:这一步也是它与页式存储管理区别最大的一步,在页式管理当中,每个页面的页长肯定都是一样的,所以系统并不需要检查页内偏移量是否超过页面长度。但是在分段管理方式中又不同,各个段的长度不一样,所以一定需要对段内地址进行一个越界的检查)第五步,由于我们找到了目标段的段表项,所以我们就知道目标段存放在内存的什么地方。我们根据这个段的基址b(即这个段在内存当中的起始地址),再加上在该段内部要访问的段内地址W,就可以计算得到我们最终想要的物理地址了。
(四)分段、分页管理的对比
页是信息的物理单位。分页的主要目的是为了实现离散分配,提高内存利用率。分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的。
段是信息的逻辑单位。分段的主要目的是更好地满足用户需求。一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式地给出段名。
页的大小固定且由系统决定。段的长度却不固定,取决于用户编写的程序。
从地址空间的角度来说:
分页的用户进程地址空间是一维的,程序员只需给出一个记忆符即可表示一个地址。
分段的用户进程地址空间是二维的,程序员在标识一个地址时,既要给出段名,也要给出段内地址。
除了上面所说的这些不同之外:
分段比分页更容易实现信息的共享和保护。
由于各个段是一个独立的逻辑。因此,若某个段的逻辑功能可以被其他进程拿去使用的话,这个段就可以被共享访问。
如何实现共享?
注意:不能被修改的代码称为纯代码或可重入代码(不属于临界资源),这样的代码是可以共享的。可修改的代码是不能共享的(比如,有一个代码段中有很多变量,各进程并发地同时访问可能造成数据不一致)
再来看一下,为什么在分页存储管理中不方便实现信息的共享(下图左)。对信息的保护也是类似的道理(下图右)。
访问一个逻辑地址需要几次访存?
分页(单级页表):第一次访存——查内存中的页表;第二次访存——访问目标内存单元。总共两次访存。
分段:第一次访存——查内存中的段表;第二次访存——访问目标内存单元。总共两次访存。
与分页系统类似,分段系统中也可以引入快表机构,将近期访问过的段表项放到快表中,这样可以少一次访存,加快地址变换速度。