<ins id='b3pk8'></ins><dl id='b3pk8'></dl>
<i id='b3pk8'></i>
    1. <fieldset id='b3pk8'></fieldset>

    2. <tr id='b3pk8'><strong id='b3pk8'></strong><small id='b3pk8'></small><button id='b3pk8'></button><li id='b3pk8'><noscript id='b3pk8'><big id='b3pk8'></big><dt id='b3pk8'></dt></noscript></li></tr><ol id='b3pk8'><table id='b3pk8'><blockquote id='b3pk8'><tbody id='b3pk8'></tbody></blockquote></table></ol><u id='b3pk8'></u><kbd id='b3pk8'><kbd id='b3pk8'></kbd></kbd>

      <code id='b3pk8'><strong id='b3pk8'></strong></code>
    3. <i id='b3pk8'><div id='b3pk8'><ins id='b3pk8'></ins></div></i><acronym id='b3pk8'><em id='b3pk8'></em><td id='b3pk8'><div id='b3pk8'></div></td></acronym><address id='b3pk8'><big id='b3pk8'><big id='b3pk8'></big><legend id='b3pk8'></legend></big></address>
      <span id='b3pk8'></span>

          详解Linux系统内存寻址的分页机制

          • 时间:
          • 浏览:13
          • 来源:124软件资讯网

              分页机制在段机制之后举行  ,以完成线性—物理地址的转换历程  。段机制把逻辑地址转换为线性地址  ,分页机制进一步把该线性地址再转换为物理地址 。

              硬件中的分页

              分页机制由CR0中的PG位启用  。如PG=1  ,启用分页机制  ,并使用本节要形貌的机制  ,把线性地址转换为物理地址 。如PG=0 ,禁用分页机制  ,直接把段机制发生的线性地址看成物理地址使用 。分页机制治理的工具是牢固巨细的存储块  ,称之为页 (page)  。分页机制把整个线性地址空间及整个物理地址空间都看成由页组成  ,在线性地址空间中的任何一页  ,可以映射为物理地址空间中的任何一页(我们把物理空间中的一页叫做一个页面或页框(page frame))  。

              80386 使用4K字节巨细的页  。每一页都有4K字节长  ,并在4K字节的界限上对齐  ,即每一页的起始地址都能被4K整除  。因此 ,80386把4G字节的线性地址空间  ,划分为1G个页面 ,每页有4K字节巨细 。分页机制通过把线性地址空间中的页  ,重新定位到物理地址空间来举行治理  ,由于每个页面的整个4K字节作为一个单元举行映射  ,而且每个页面都对齐4K字节的界限  ,因此  ,线性地址的低12位经由分页机制直接地作为物理地址的低12位使用  。

              为什么使用两级页表

              假设每个历程都占用了4G的线性地址空间  ,页表共含1M个表项  ,每个表项占4个字节 ,那么每个历程的页表要占有4M的内存空间  。为了节约页表占用的空间 ,我们使用两级页表  。每个历程都市被分配一个页目录  ,可是只有被现实使用页表才会被分配到内存内里  。一级页表需要一次分配所有页表空间  ,两级页表则可以在需要的时间再分配页表空间  。

              两级页表结构

              两级表结构的第一级称为页目录  ,存储在一个4K字节的页面中  。页目录表共有1K个表项  ,每个表项为4个字节 ,并指向第二级表  。线性地址的最高10位(即位31~位32)用来发生第一级的索引 ,由索引获得的表项中 ,指定并选择了1K个二级表中的一个表  。

              两级表结构的第二级称为页表 ,也恰好存储在一个4K字节的页面中 ,包罗1K个字节的表项  ,每个表项包罗一个页的物理基地址  。第二级页表由线性地址的中心10 位(即位21~位12)举行索引  ,以获得包罗页的物理地址的页表项  ,这个物理地址的高20位与线性地址的低12位形成了最后的物理地址  ,也就是页转化历程输出的物理地址 。

              页目录项

              第31~12位是20位页表地址 ,由于页表地址的低12位总为0 ,以是用高20位指出32位页表地址就可以了  。因此  ,一个页目录最多包罗1024个页表地址  。

              第0位是存在位 ,若是P=1  ,表现页表地址指向的该页在内存中  ,若是P=0  ,表现不在内存中 。

              第1位是读/写位  ,第2位是用户/治理员位  ,这两位为页目录项提供硬件掩护  。当特权级为3的历程要想会见页面时  ,需要通过页掩护检查  ,而特权级为0的历程就可以绕过页掩护  。

              第3位是PWT(Page Write-Through)位 ,表现是否接纳写透方式  ,写透方式就是既写内存(RAM)也写高速缓存,该位为1表现接纳写透方式

              第4位是PCD(Page Cache Disable)位  ,表现是否启用高速缓存,该位为1表现启用高速缓存  。

              第5位是会见位  ,当对页目录项举行会见时  ,A位=1 。

              第7位是Page Size标志  ,只适用于页目录项  。若是置为1 ,页目录项指的是4MB的页面  ,请看后面的扩展分页 。

              第9~11位由操作系统专用  ,Linux也没有做特殊之用  。

              页面项

              80386的每个页目录项指向一个页表 ,页表最多含有1024个页面项 ,每项4个字节  ,包罗页面的起始地址和有关该页面的信息  。页面的起始地址也是4K的整数倍  ,以是页面的低12位也留作它用  。

              第31~12位是20位物理页面地址 ,除第6位外第0~5位及9~11位的用途和页目录项一样  ,第6位是页面项独占的  ,当对涉及的页面举行写操作时 ,D位被置1 。

              4GB的内存只有一个页目录  ,它最多有1024个页目录项  ,每个页目录项又含有1024个页面项  ,因此  ,内存一共可以分成1024×1024=1M个页面  。由于每个页面为4K个字节  ,以是  ,存储器的巨细正好最多为4GB  。

              线性地址到物理地址的转换

              32位线性地址到物理地址的转换

              1.CR3包罗着页目录的起始地址  ,用32位线性地址的最高10位A31~A22作为页目录的页目录项的索引  ,将它乘以4  ,与CR3中的页目录的起始地址相加  ,形成响应页表的地址  。

              2.从指定的地址中取出32位页目录项  ,它的低12位为0  ,这32位是页表的起始地址 。用32位线性地址中的A21~A12位作为页表中的页面的索引 ,将它乘以4  ,与页表的起始地址相加  ,形成32位页面地址  。

              3.将A11~A0作为相对于页面地址的偏移量  ,与32位页面地址相加 ,形成32位物理地址  。

              扩展分页

              从飞跃处置惩罚器最先  ,Intel微处置惩罚器引进了扩展分页  ,它允许页的巨细为4MB  。

              在扩展分页的情形下,分页机制把32位线性地址分成两个域:最高10位的目录域和其余22位的偏移量 。

              页面高速缓存

              由于在分页情形下 ,每次存储器会见都要存取两级页表  ,这就大大降低了会见速率 。以是 ,为了提高速率 ,在386中设置一个最近存取页面的高速缓存硬件机制  ,它 自动保持32项处置惩罚器最近使用的页面地址 ,因此 ,可以笼罩128K字节的存储器地址 。当举行存储器会见时  ,先检查要会见的页面是否在高速缓存中  ,若是在  , 就不必经由两级会见了  ,若是不在  ,再举行两级会见  。平均来说  ,页面高速缓存约莫有98%的掷中率  ,也就是说每次会见存储器时  ,只有2%的情形必须会见两级分页机构 。这就大大加速了速率  。

              Linux中的分页机制

              Linux使用了一个适合32位和64位系统的分页机制 。

              页全局目录

              页顶级目录

              页中心目录

              页表

              页全局目录包罗若干页上级目录的地址  ,页上级目录又依次包罗若干页中心目录的地址  ,而页中心目录又包罗若干页表的地址  。每一个页表项指向一个页框  。线性地址因此被分成五个部门  。图中没有显示位数  ,由于每一部门的巨细与详细的盘算机系统结构有关 。

              对于没有启用物理地址扩展的32位系统  ,两级页表已经足够了  。从本质上说  ,Linux通过使“页上级目录”位和“页中心目录”位全为0  ,彻底作废了页上级目录和页中心目录字段  。不外  ,页上级目录和页中心目录在指针序列中的位置被保留  ,以便同样的代码在32位系统和64位系统下都能使用  。内核为页上级目录和页中心目录保留了一个位置 ,这是通过把它们的页目录项数设置为1  ,并把这两个目录项映射到页全局目录的一个合适的目录项而实现的  。

              启用了物理地址扩展的32 位系统使用了三级页表  。Linux的页全局目录对应80×86 的页目录指针表(PDPT)  ,作废了页上级目录  ,页中心目录对应80×86的页目录 ,Linux的页表对应80×86的页表  。

              最后  ,64位系统使用三级照旧四级分页取决于硬件对线性地址的位的划分  。

              总结

              这里我们不讨论代码实现  ,只关注原理  。从上面的讨论可以看到分页机制主要依赖硬件的实现  。Linux接纳的四级页表只是为了最大化兼容差别的硬件实现  ,单就IA32架构的CPU来说  ,就有多种分页实现  ,通例分页机制  ,PAE机制等 。

              我们虽然讨论的是Linux的分页机制 ,现实上我们用了大部门篇幅来讨论Intel CPU的分页机制实现 。由于Linux的分页机制是建设在硬件基础之上的  ,差别的平台需要有差别的实现 。Linux在软件层面结构的虚拟地址  ,最终照旧要通过MMU转换为物理地址  ,也就是说 ,不管Linux的分页机制是怎样实现的 ,CPU只根据它的分页实现来解读线性地址  ,以是Linux传给CPU的线性地址一定是知足硬件实现的  。例如说:Linux在32位CPU上  ,它的四级页表结构就会兼容到硬件的两级页表结构  。可见  ,Linux在软件层面上做了一层 抽象  ,用四级页表的方式兼容32位和64位CPU内存寻址的差别硬件实现  。