Chinaunix首页 | 论坛 | 博客
  • 博客访问: 342618
  • 博文数量: 72
  • 博客积分: 2130
  • 博客等级: 大尉
  • 技术积分: 857
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-05 16:10
文章分类

全部博文(72)

文章存档

2010年(5)

2009年(14)

2008年(53)

分类: LINUX

2008-11-24 12:18:58

    linux内核采用页式存储管理,对于i386来说,linux采用了使段式映射的过程实际上不起什么作用(除特殊的VM86模式外)的方法。在elf格式的可执行代码中,ld总是从0x8000000开始安排程序的“代码段”。

    如果一个程序已经运行,整个映射机制都已经建立好,并且CPU正在执行main()中的“call 08048568”(假如)。

    首先是段式映射阶段:0x08048586是一个程序的入口,在执行的过程中是由CPU中的“指令计数器”EIP”指向的,所以在代码段中,故i386CPUCS的当前值来作为段式映射的选择码,即段描述符表中的下标,而CS(内核在建立一个进程时都要将段寄存器设置好)被设置为USER_CS(DS,ES,SS都被设置为USER_DS,即在Linux内核中堆栈段和数据段是不分的),

    而宏USER_CS被定义为0x23(USER_DS0x2B,KERNEL_CS0x10KERNEL_DS0x18),展开为:0000 0000 00100 0 11,即index=4,TI0RPL3TI都是0,全都使用GDT,在linux内核中基本不使用局部段描述表LDTLDT只是在VM86模式中才使用,初始的GDT0x23对应于0x00cffa000000ffff,转换为二进制为:K_CS

    0000 0000 1100 1111 1111 1010 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111

    每个段都是从0开始的整个4GB虚存空间,逻辑地址到线性地址的映射保持原值不变。

    然后是页式映射阶段:每个进程都有其自身的PGD,指向这个目录的指针保持在每个进程的mm_struct数据结构中,每当调度一个进程进入运行的时候,内核都要为即将运行的进程设置好控制寄存器CR3,而MMU的硬件则总是从CR3中取得指向当前页面目录的指针,不过,CPU在执行程序时使用的是虚存地址,而MMU硬件在进行映射时所用的则是物理地址。当我们在程序中要转移到地址0x08048568的时候,进程正在运行中,CR3早已设置好,指向我们这个进程的页面目录了,先将线性地址0x08048568按二进制展开:

    0000 1000 0000 0100 1000 0101 0110 1000,最高10位为0000 1000 00,即十进制32,所以i386CPU(确切地说是CPU中的MMU)就以32为下标去页面目录中找到其目录项,找到页面表后,CPU再来看线性地址中的中间10位,0x08048568的中间10位为000100100072,于是CPU就以此为下标在已经找到的页表中找到相应的表项,和目录项相似,当页面表项的P标志位为1时表示所映射的页面在内存中,32位的页面表项中的高20位指向一个物理内存页面,在后边添加120就得到这物理内存页面的起始地址,在其起始地址上加上线性地址的最低12位,如这里的0x568,就可以得到最终的物理内存地址了。

阅读(2195) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~