linux分段和分页机制其实很简单

       前面我们讲了linux操作系统在保护模式下的一些情况,在保护模式下段寄存器存放的不再是段地址,而是段选择符,用来索引段描述符。接下来我们来说一说一个逻辑地址如何使如何转换成线性地址的。
       为此我画了一张图,如下:
linux分段和分页机制其实很简单_第1张图片
       首先,逻辑地址是由段地址和偏移量组成,当系统想要访问某一个段时,会将相应的段选择符装入段寄存器。首先会检测TI的值,即我的段描述符在全局描述符表中,还是在局部描述符表中。知道了描述符表的位置,接下来就要在表中找描述符了,怎么找呢?首先每个段描述符表占8个字节,因此我们的段选择符需要x8,然后加上段描述符表的首地址,就可以得到段描述符的地址,进而得到段首地址,最后加上偏移地址,就得到了线性地址。
       另外要提一句,为了减少对内存的访问,x86处理器提供了一种非编程的寄存器,供段寄存器使用,当段寄存器中放入段选择符时,会将该选择符索引的段描述符放入该寄存器,这样如果待会访问的是同一个段,那么就不会去访问内存了,加速了对段的访问。只有当段寄存器中的值更新时,非编程寄存器中的值才会被改变。

linux中的分段机制
       终于要开始讲分段机制了,前边为什么啰嗦了那么多,就是为了给linux分段和分页机制做铺垫。以前我也看了很多关于linux分段和分页的文章,就是不明白其中的奥秘,后来才发现,原来内存寻址是你学习中无法绕过的东西。明白了内存寻址的原理,其实分段和分页机制就很简单了。但前提是前面的几篇文章需要看明白原理,其实没那么难,多看几遍就可以明白。
        在讲linux分段前,我们再来看下,什么是分段,分段其实就是将虚拟地址空间划分的手段,使得每一个进程的虚拟地址相互不干扰。通过分段机制,实现从逻辑地址到线性地址的转。x86其实是要使用分段机制的,但linux并没有全部的使用分段机制,或者说它很巧妙的使用了分段机制。
       运行在linux用户态的进程都使用相同的段来对指令和数据进行寻址。同样的,运行在内核态的所有linux进程,都使用相同的段对指令和数据寻址,分别是内核代码段和内核数据段。下面显示了这四个重要段的段描述符字段的值:
linux分段和分页机制其实很简单_第2张图片
       从表格中我们可以知道,这四个段的首地址均是0,也就是说,逻辑地址+段首地址=线性地址 这个公式里面的段首地址为0,也就意味着在linux中,逻辑地址=线性地址,这就是linux的分段技术。
其实相比分段技术,linux似乎更钟情于分页技术。

linux中的分页机制
       前面我们知道,分页其实是x86操作系统的一个硬件,叫分页单元,它的作用是将线性地址转换成物理地址。对于物理内存,分页单元把它分为固定长度的页框(page frame),每一个页框包含一个页(page)。对于虚拟地址空间,也把它分为一个个的页。为了访问每一个物理页,需要有一个页表,记录每个物理页的起始地址,简单说通过页表就可以将一个虚拟内存中的页与具体的物理页一一对应起来。虚拟地址可以分为两部分,页号和页内偏移,页号为页表的索引,得到页的基地址后,加上偏移地址就可以得到具体的物理地址。
       我们以32位环境为例,虚拟地址空间为4G,一般一页为4KB,这样4G内存可以分为1M个页,由于每个页表项需要4个字节来描述,因此一共需要4M的存储空间,因为每个进程都有自己的页表,如果有100个进程就需要400M的存储空间,这是不可能忍受的。我们可以试着将页表再分页,4G的空间需要4M的页表,4M的页表可以再分成1K个(4K)页,这1K个页也需要一个页表进行管理,成为页目录表,这个页目录表中有1K个项,每项4个字节,页目录表的大小为4K。页目录有1K项,用10位就可以访问页目录的哪一项。这一项是对应4K大小的页表项,因为一个页表项占4个字节,也就是1K个页表项,再用10位就可以访问页表项的某一项,页表项中的一项对应一个物理页,页的大小为4K,因此用12位就可以得到一个页的任何一个位置。这样加起来共32位。即虚拟地址的大小:用高10位定位页目录项中的一项,用中间10位定位页表中的某一项,再用12位定位页中的某一具体位置。
       如果这样的话,映射4GB的地址空间岂不是需要4M+4K的内存了?其实我们不会给一个进程一下子分配那么多内存。假设我们给进程分配1个物理内存页。假如只有1级页表,那我们也要完整的1M个页表共4M内存。如果使用2级页表,我们只要分配完整的页目录共计4k内存空间,我们只会使用页目录中的一项,这一项对应4K页表空间,也就是1k个页表项,再把这4K的页表分配出来就可以了。
       对于64位的操作系统,一般使用4级页表,分别是全局页目录项(PGD)、上层页目录项(PUD)、中间页目录项(PMD)、页表项(PTE)。

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