上面存储管理里说的动态分配策略都是存储在连续的物理内存中,这有几个缺点:分配给程序的物理内存必须连续,存在内存碎片,内存利用率低等缺点,所以为了提高内存利用率和管理的灵活性,就需要提出非连续内存分配的办法,最终能给达到使得一个程序可以使用非连续的物理地址空间,共享代码和数据,支持动态加载和动态链接。一个进程有不同的块组成,如代码段,堆栈段等,这些在进程的逻辑地址空间上是连续存储的,使用段式和页式存储管理的方式实现其在物理地址空间上的非连续存储。
段式存储管理:段是指访问方式和存储数据等属性相同的一段地址空间,对应着一个连续的内存快,进程逻辑地址空间由若干个段组成。使用段式存储管理时,一个段的逻辑地址由断号和段内偏移表示。Cpu根据段号在段表中找到那一项,查出段基址和段长度,然后判断合法性,若合法,就在分成大小相同的内存块的物理内存中根据段基址和段内偏移找到所需要的数据。
页式存储管理:在物理地址空间中,将内存分为大小相同的页帧,简称为“帧”,每一块的大小为2的n次方;在逻辑地址空间中,将空间分为大小相同的页面,简称为“页”。由页面到页帧的转换就是逻辑地址到物理地址的转换。它们之间的映射由页表来管理。
物理内存中,根据帧号和帧内偏移可定位到实际的物理地址。进程逻辑地址空间中,一个页由页号和页内偏移组成,页内偏移和帧内偏移相同。由页号可以在页表中找到物理地址空间中的页帧号,取得帧号后,可如上继续定位到具体的物理地址。
每一个页面都会对应一个页表项,随着进程运行状态而动态变化。页表的基址存储在页表基址寄存器中。虽然页表进一步优化了段式存储的非连续存储的特性,但也存在性能问题,如访问一个内存单元需要进行两次访问,页表占用的内存大小也造成资源的占用。所以提出了基于缓存的快表和间接访问的多级页表来优化这些问题。
快表是用cpu中的高速缓存将近期访问的页表项缓存进去,比如执行两条连续的指令,通过页表找到第一条指令的页表项后缓存到cpu中,之后执行第二条指令可快速通过已缓存的页表项找到其物理页号。
多级页表是将逻辑地址的页号分成若干级,可减少每级页表的长度。但是在大地址空间的系统中,多级页表会变得十分繁琐,此时提出了反置页表,其将页表与物理地址空间的大小相对应,与逻辑地址空间无关。每一个帧与一个页寄存器关联,在页寄存器中搜索逻辑地址的页号。具体步骤是:对cpu生成的逻辑地址进行hash变换后,在快表中查找对应的页表项,有冲突时解决冲突。
段式与页式各有优势,可将段式与页式结合起来,比如会在两个进程共享同一个数据段时会用到段式与页式的结合,实现进程间的段共享。