首页 > 资讯列表 > 软件学院 >> 系统程序

Linux内核代码之初始化内核临时页表

系统程序 2014-12-12 14:18:04 转载来源: 网络整理/侵权必删

        漫长而黑暗的史前时代终于到了setup。在setup汇编函数中,linux通过设置cr0寄存器的PE位(从实模式切换到保护模式)完成了史前文明到现代文明的转变

  

      漫长而黑暗的史前时代终于到了setup。在setup汇编函数中,linux通过设置cr0寄存器的PE位(从实模式切换到保护模式)完成了史前文明到现代文明的转变。在setup时期,linux已经了解到世上可用的内存资源远远不止1MB。此时linux的欲望开始膨胀,最为满足它欲望的第一步,它开始抢占内存资源的前8MB。

  初始化临时内核页表是在startup_32汇编语言函数中完成的。在ULK所述中,假设内核能容纳于RAM的前8MB空间,然后对RAM的前8MB进行恒等映射(例如用户地址0x00003000映射物理地址0x00003000,0xc0003000映射到物理地址0x00003000),来初始化临时页全局目录swapper_pg_dir和相应的页表。映射8MB只需要填充swapper_pg_dir中第0项,1项,768项和769项。前两项是给用户线性地址映射,后两项给内核线性地址映射。用页全局目录里的两项就能对8MB映射的理由是2×1024(页表有1024项)×4K(一页的大小)=8M。实际上初始化内核页表来对RAM的前8MB映射不是个硬性的规定。这取决于你的内核的配置(我认为大多数情况下是对8MB映射)。在startup_32中可以看到,对多少内存进行映射是通过pg0动态判断的。

  linux/arch/i386/kernel/head.S

  page_pde_offset = (__PAGE_OFFSET >> 20);

  /*__PAGE_OFFSET是0xc0000000,内核线性空间的起始地址。

  page_pde_offset=0xc00(十进制为3072)*/

  movl $(pg0 - __PAGE_OFFSET), %edi

  /*pg0的线性地址可以在/boot/System.map文件中找到。我的Ubuntu8.04机器上是0xc04f4000。

  减去0xc0000000就是pg0的物理地址(004f4000),放入edi中。*/

  movl $(swapper_pg_dir - __PAGE_OFFSET), %edx

  /*swapper_pg_dir的线性地址也可以在/boot/System.map文件中找到。我机器上是0xc047d000。

  减去0xc0000000就是swapper_pg_dir的物理地址(0047d000),放入edx中。*/

  movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */

  /*页目录项和页表项的低12位是标志位,把标志位0x007放入eax中。*/

  10:

  leal 0x007(%edi),%ecx /* Create PDE entry */

  /*第一循环时把edi指向的pg0的物理地址加上0x007放入ecx中。

  第二次循环时把edi指向的物理地址0x4f5000加上0x007放入ecx中。*/

  movl %ecx,(%edx) /* Store identity PDE entry */

  /*第一次循环时把ecx中的内容放入swapper_pg_dir的第0项里。

  第二次循环时把ecx中的内容放入swapper_pg_dir的第1项里。*/

  movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */

  /*第一次循环时把ecx中的内容放入swapper_pg_dir的第768项里。因为前面算出page_pde_offset的值为3072,而swapper_pg_dir中每项是4个字节,所以3072/4=768。

  第二次循环时把ecx中的内容放入swapper_pg_dir的第769项里。*/

  addl $4,%edx

  /*第一次循环时,此时edx指向swapper_pg_dir的第1项。

  第二次循环时,此时edx指向swapper_pg_dir的第2项。*/

  movl $1024, %ecx

  /*为初始化1024个页表项设置计数*/

  11:

  stosl

  /*把eax中的内容放入edi指向的物理地址中,然后edi+4。*/

  addl $0x1000,%eax

  loop 11b

  /*跳到上面的11处循环。

  第一次执行1024次后,从pg0物理地址(0x4f4000)开始存放的是0x007,0x1007,0x2007,...,0x3ff007,也就是当前能够映射到物理地址从0x000到0x3fffff处。此时edi中的值为0x4f5000。

  第二次执行1024次后,从物理地址(0x4f5000)开始存放的是0x400007,0x401007,0x402007,...,7ff007,也就是当前能够映射到物理地址0x000到7fffff处,正好8MB。此时edi中的值为0x4f6000。*/

  leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp

  /*INIT_MAP_BEYOND_END的值为128k,在此文件中的一个宏定义。把edi指向的物理地址加上128k加上0x007放入edp中。*/

  cmpl %ebp,%eax

  /*在第一次循环中ebp中的值为0x515007,eax中的值为0x400007小于0x515007。当前所映射到的最大物理地址为0x3fffff没有包含0x515007,所以没有映射完。

  在第二次循环中ebp中的值为0x516007,eax中的值为0x800007大于0x516007。当前所映射到的最大物理地址为0x7fffff包含了0x516007,所以8MB物理地址映射完毕。*/

  jb 10b

  /*第一次循环做完时跳到上面的10处继续循环

  第二次循环做完时跳出循环。*/

  movl %edi,(init_pg_tables_end - __PAGE_OFFSET)

  /*最后把0x4f6000放入init_pg_tables_end 所表示的物理地址中。也在/boot/System.map中。*/

  此时的linux胃口越来越大,8MB的资源已不能满足它的胃口了。它的黑手开始慢慢伸向896MB以下的内存了。  

(责任编辑:admin)

标签: 内核 Linux 代码 初始化 临时 页表


声明:本文内容来源自网络,文字、图片等素材版权属于原作者,平台转载素材出于传递更多信息,文章内容仅供参考与学习,切勿作为商业目的使用。如果侵害了您的合法权益,请您及时与我们联系,我们会在第一时间进行处理!我们尊重版权,也致力于保护版权,站搜网感谢您的分享!

站长搜索

http://www.adminso.com

Copyright @ 2007~2024 All Rights Reserved.

Powered By 站长搜索

打开手机扫描上面的二维码打开手机版


使用手机软件扫描微信二维码

关注我们可获取更多热点资讯

站长搜索目录系统技术支持