免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 10287 | 回复: 8
打印 上一主题 下一主题

[原创]Linux内存管理图解(2)线性地址转物理地址 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-23 22:38 |只看该作者 |倒序浏览
Linux内存管理图解
作者:wdy

二、线性地址转物理地址

前面说了Linux中逻辑地址等于线性地址,那么线性地址怎么对应到物理地址呢?这个大家都知道,那就是通过分页机制,具体的说,就是通过页表查找来对应物理地址。

分页是CPU提供的一种机制,Linux只是根据这种机制的规则,利用它实现了内存管理。

分页的基本原理是把线性地址分成固定长度的单元,称为页(page)。页内部连续的线性地址映射到连续的物理地址中。X86每页为4KB(为简化分析,我们不考虑扩展分页的情况)。为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table),页表存放在内存中。

在保护模式下,控制寄存器CR0的最高位PG位控制着分页管理机制是否生效,如果PG=1,分页机制生效,需通过页表查找才能把线性地址转换物理地址。如果PG=0,则分页机制无效,线性地址就直接作为物理地址。

为了实现每个任务的平坦的虚拟内存和相互隔离,每个任务都有自己的页目录表和页表。

为了节约页表占用的内存空间,x86将线性地址通过页目录表和页表两级查找转换成物理地址。

32位的线性地址被分成3个部分:

最高10位 Directory 页目录表偏移量,中间10位 Table是页表偏移量,最低12位Offset是物理页内的字节偏移量。

页目录表的大小为4KB(刚好是一个页的大小),包含1024项,每个项4字节(32位),表项里存储的内容就是页表的物理地址(因为物理页地址4k字节对齐,物理地址低12位总是0,所以表项里的最低12字节记录了一些其他信息,这里做简化分析)。如果页目录表中的页表尚未分配,则物理地址填0。

页表的大小也是4k,同样包含1024项,每个项4字节,内容为最终物理页的物理内存起始地址。



每个活动的任务,必须要先分配给它一个页目录表,并把页目录表的物理地址存入cr3寄存器。页表可以提前分配好,也可以在用到的时候再分配。

还是以 mov    0x80495b0, %eax  中的地址为例分析一下线性地址转物理地址的过程。

前面说到Linux中逻辑地址等于线性地址,那么我们要转换的线性地址就是0x80495b0。转换的过程是由CPU自动完成的,Linux所要做的就是准备好转换所需的页目录表和页表(假设已经准备好,给页目录表和页表分配物理内存的过程很复杂,后文再分析)。

内核先将当前任务的页目录表的物理地址填入cr3寄存器。

线性地址 0x80495b0 转换成二进制后是 0000 1000 0000 0100 1001 0101 1011 0000,最高10位0000 1000 00的十进制是32,CPU查看页目录表第32项,里面存放的是页表的物理地址。线性地址中间10位00 0100 1001 的十进制是73,页表的第73项存储的是最终物理页的物理起始地址。物理页基地址加上线性地址中最低12位的偏移量,CPU就找到了线性地址最终对应的物理内存单元。

我们知道Linux中用户进程线性地址能寻址的范围是0 - 3G,那么是不是需要提前先把这3G虚拟内存的页表都建立好呢?一般情况下,物理内存是远远小于3G的,加上同时有很多进程都在运行,根本无法给每个进程提前建立3G的线性地址页表。Linux利用CPU的一个机制解决了这个问题。进程创建后我们可以给页目录表的表项值都填0,CPU在查找页表时,如果表项的内容为0,则会引发一个缺页异常,进程暂停执行,Linux内核这时候可以通过一系列复杂的算法给分配一个物理页,并把物理页的地址填入表项中,进程再恢复执行。当然进程在这个过程中是被蒙蔽的,它自己的感觉还是正常访问到了物理内存。

怎样防止进程访问不属于自己的线性地址(如内核空间)或无效的地址呢?内核里记录着每个进程能访问的线性地址范围(进程的vm_area_struct 线性区链表和红黑树里存放着),在引发缺页异常的时候,如果内核检查到引发缺页的线性地址不在进程的线性地址范围内,就发出SIGSEGV信号,进程结束,我们将看到程序员最讨厌看到的Segmentation fault。

[ 本帖最后由 Aryang 于 2008-11-23 22:40 编辑 ]

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2008-11-24 09:48 |只看该作者
顶一下。有时间好好拜读。

论坛徽章:
0
3 [报告]
发表于 2011-06-10 17:35 |只看该作者
不错,简明易懂

论坛徽章:
0
4 [报告]
发表于 2011-06-10 21:39 |只看该作者
简单的顶一下。。。。。。。

论坛徽章:
0
5 [报告]
发表于 2011-06-12 22:35 |只看该作者
mips 64体系结构下, 内核中使用数据(alloc_page, kmalloc,kmem_cache_alloc接口)都是通过xphys段直接扩展,不经过tlb映射,  由于是64位,所以所有的物理内存都可以访问,
   vmalloc接口是经过tlb映射的到xkseg,所有的内核公用一个这么一个映射表。

   用户模式下每个进程有一个自己的tlb映射表。


原则上讲 内核应该可以使用所有的内存,但是32位模式下出现了问题,x86为例, 内核约定使用c000 0000   ---  ffff ffff  的虚拟地址, 内核一般只做线性映射,映射对应0--1G的物理地址空间, 内核如何使用vmalloc使用> 1G的内存空间high_mem呢 ? 怎么每次每人写内存这一块的都不解释这个 ? 这个是为什么? 老是页表,目录表的,这个大家还是比较好懂。
      
     我猜测,要么从0--1g里面挖一块空间出来做vmalloc映射,但不是线性的,可重复的,要么从用户空间挖一块出来,   哥懒得看代码了, 谁出来解释一下。

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
6 [报告]
发表于 2011-06-12 23:37 |只看该作者
内核1G虚拟地址空间里只有前896M是线性映射的,剩余的一段有好几种用途,其中就包括vmalloc。每本书里都讲了这个吧。。。。。

论坛徽章:
0
7 [报告]
发表于 2011-06-13 09:57 |只看该作者
本帖最后由 zhanglong71 于 2011-06-13 10:08 编辑

"如果内核检查到引发缺页的线性地址不在进程的线性地址范围内,就发出SIGSEGV信号,进程结束"
------------------------------------------------ 
    
  push或pusha指令在进程的用户态栈上的操作的地址,可能不在任何线性区。
  x86平台下,栈是向下生长的,其VM_GROWSDOWN标志被设置,通过vm_start减小而生长。这种线性区的边界并没有限定用户栈的当前大小。线性区是以页为单位分配的,而栈的大小不是以页为单位分配。

  在缺页的处理过程中,允许栈的空间扩展到线性区以下的32字节。此32字节是由pusha指令入栈的寄存器个数决定的(好象是8个通用寄存器吧)。

论坛徽章:
0
8 [报告]
发表于 2011-06-13 12:13 |只看该作者
内核1G虚拟地址空间里只有前896M是线性映射的,剩余的一段有好几种用途,其中就包括vmalloc。每本书里都讲了 ...
tempname2 发表于 2011-06-12 23:37


仅仅896M~1G被内核自由的用作vmalloc,设备资源映射等用途,这个之前我也有困惑,后来还是tmepnameXX帮助。不过感觉还是太少了。
我记得tmepnameXX之前有个帖子分析,896M虽被内核映射了,但并未据为己有。用户态依旧可申请。以后应该实现vmalloc也可以就好了

论坛徽章:
0
9 [报告]
发表于 2011-10-09 00:12 |只看该作者
mark
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP