虚存与主存的地址映射方法详解

为最近在写系统命令的时候,经常会出现段错误。但是段错误的提示信息一般情况下是比较少的,所以断错误并不是很好找。前几天从网上查询了关于段错误的一些资料,发现一般段错误基本都是与内存有关,比如有:访问不存在的内存地址,访问只读的内存地址,以及访问被系统保护的内存地址通过dmesg命令可以查看发生段错误的程序名称、引起段错误发生的内存地址、指令指针地址、堆栈指针地址、错误代码、错误原因等。所以我打算将存储之间的映射这一块的知识作以较为详细的说明,会用我自己的理解来说的明白些。


      先说说虚存与内存的映射,因为一般情况下,我们写的代码都是在虚存上,但是当代码需要运行的时候就必须将其装入内存,所以就必须将虚存的地址以一定的规则转换成实地址。

        虚存的地址变换,分三种:段式,页式,段页式。 很明显,有段页式,说明段式和页式各有优缺点。

        一. 段式

             段式虚拟存储器,当我们编写程序的时候,一般会把程序分成段,常见的有数据段DS,代码段CS,附加段ES和堆栈段SS。这些段的长度都是不一的。多用户虚地址是由用户号U,段号S,和段内偏移地址D组成的。虚地址和实地址之间是通过段表(存放于主存储器)来映像的,CPU中会有一个段表基址寄存器,段表记录:段号,段长,起始地址。从基址寄存器能够直接读出段表的起始地址。通过用户号U查找到对应的基址寄存器,基址寄存器的起始地址加上虚地址的段号,就能找到段表地址,然后如果所访问的段在内存中,则从段表中给出的起始地址,加上虚地址的偏移量,则就得到实地址。(计算两次)

       模块化性能好,便于链接和调度,但地址变换花费时间长,内存利用率低(段大小不一,会浪费空间)。

       虚存与主存的地址映射方法详解_第1张图片

      二. 页式

           用户虚地址由:用户号U,虚页号P,和页内偏移地址D组成。因为页的大小都是固定的,所以这儿只需要进行一次运算,和段表相对,页表用来记录页号和主存页号,CPU中的基址寄存器存放页表的基地址,和段表一样,用户号U会通过基址寄存器找到页表起始地址,起始地址与虚页号相加,再与偏移地址拼接就得到实地址,因为页的大小是一样的,所以它在虚地址中某一页的偏移量和主存中某一页的偏移量是一样的。(计算一次)

       主存利用率高,只有最后一页会存在浪费的情况。管理也容易。模块化性能不好(因为有可能一个程序的某一段会被分在好几页上)

虚存与主存的地址映射方法详解_第2张图片

     三. 段页式。

           对用户用段式管理,对内存用分页式管理。段表记录:页表长度和页表地址。虚地址由:用户号U,段号S,虚页号P,页内偏移D组成。先通过U在段表基址寄存器中找到段表基地址,然后和段号S相加,得到页表起始地址和页表长度,通过页表找到主存实页号再与偏移量拼接,得到实地址。(页表的长度就是页表数)


虚存与主存的地址映射方法详解_第3张图片

     如果要访问的地址不在内存中,就会需要调入一页或一段到主存中。


你可能感兴趣的:(内存)