免费注册 查看新帖 |

Chinaunix

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

Linux内存:内存管理的实质 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-05-19 21:04 |显示全部楼层 |倒序浏览
1. 内核初始化:

    * 内核建立好内核页目录页表数据库,假设物理内存大小为len,则建立了[3G--3G+len]::[0--len]这样的虚地址vaddr和物理地址paddr的线性对应关系;
    * 内核建立一个page数组,page数组和物理页面系列完全是线性对应,page用来管理该物理页面状态,每个物理页面的虚地址保存在page->virtual中;
    * 内核建立好一个free_list,将没有使用的物理页面对应的page放入其中,已经使用的就不用放入了;

2. 内核模块申请内存vaddr = get_free_pages(mask,order):

    * 内存管理模块从free_list找到一个page,将page->virtual作为返回值,该返回值就是对应物理页面的虚地址;
    * 将page从free_list中脱离;
    * 模块使用该虚拟地址操作对应的物理内存;

3. 内核模块使用vaddr,例如执行指令mov(eax, vaddr):

    * CPU获得vaddr这个虚地址,利用建立好的页目录页表数据库,找到其对应的物理内存地址;
    * 将eax的内容写入vaddr对应的物理内存地址内;

4. 内核模块释放内存free_pages(vaddr,order):

    * 依据vaddr找到对应的page;
    * 将该page加入到free_list中;

5. 用户进程申请内存vaddr = malloc(size):

    * 内存管理模块从用户进程内存空间(0--3G)中找到一块还没使用的空间vm_area_struct(start--end);
    * 随后将其插入到task->mm->mmap链表中;

6. 用户进程写入vaddr(0-3G),例如执行指令mov(eax, vaddr):

    * CPU获得vaddr这个虚地址,该虚地址应该已经由glibc库设置好了,一定在3G一下的某个区域,根据CR3寄存器指向的current->pgd查当前进程的页目录页表数据库,发现该vaddr对应的页目录表项为0,故产生异常;
    * 在异常处理中,发现该vaddr对应的vm_area_struct已经存在,为vaddr对应的页目录表项分配一个页表;
    * 随后从free_list找到一个page,将该page对应的物理页面物理首地址赋给vaddr对应的页表表项,很明显,此时的vaddr和paddr不是线性对应关系了;
    * 将page从free_list中脱离;
    * 异常处理返回;
    * CPU重新执行刚刚发生异常的指令mov(eax, vaddr);
    * CPU获得vaddr这个虚地址,根据CR3寄存器指向的current->pgd,利用建立好的页目录页表数据库,找到其对应的物理内存地址;
    * 将eax的内容写入vaddr对应的物理内存地址内;  

7. 用户进程释放内存vaddr,free(vaddr):

    * 找到该vaddr所在的vm_area_struct;
    * 找到vm_area_struct:start--end对应的所有页目录页表项,清空对应的所有页表项;
    * 释放这些页表项指向物理页面所对应的page,并将这些page加入到free_list队列中;
    * 有必要还会清空一些页目录表项,并释放这些页目录表项指向的页表;
    * 从task->mm->mmap链中删除该vm_area_struct并释放掉;

综合说明:

    * 可用物理内存就是free_list中各page对应的物理内存;
    * 页目录页表数据库的主要目的是为CPU访问物理内存时转换vaddr-->paddr使用,分配以及释放内存时不会用到,但是需要内核内存管理系统在合适时机为CPU建立好该库;
    * 对于用户进程在6中获得的物理页面,有两个页表项对应,一个就是内核页目录页表数据库的某个pte[i ],一个就是当前进程内核页目录页表数据库的某个 pte[j],但是只有一个page和其对应。如果此时调度到其他进程,其他进程申请并访问某个内存,则不会涉及到该物理页面,因为其分配时首先要从 free_list中找一个page,而该物理页面对应的page已经从free_list中脱离出来了,因此不存在该物理页面被其他进程改写操作的情况。内核中通过get_free_pages等方式获取内存时,也不会涉及到该物理页面,原理同前所述。

评分

参与人数 1可用积分 +15 收起 理由
yuhuohu + 15 我很赞同

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2008-05-19 23:32 |显示全部楼层
原帖由 zx_wing 于 2008-5-19 23:20 发表
再顶一个,希望LZ能细化一下

老弟,要细化就失去该篇文档的意义了
花了大概一年看Linux内存管理,其涉及到的概念、数据结构、算法都非常多,每一部分都可以详细写出一篇文档,做的笔记好几万字,但总感觉应该用简短的几句话描述出内存管理的实质,试图总结过好几次,没成功。在上个星期,彻底静下心来花了几天时间,总结出这篇文档,来尽可能的清晰描绘出Linux内存管理的实质,希望有所帮助。

论坛徽章:
0
3 [报告]
发表于 2008-05-20 00:43 |显示全部楼层
原帖由 zx_wing 于 2008-5-20 00:33 发表

佩服佩服,我现在也在艰难的学习中。
内存一直不敢碰。我建议LZ慢慢写,一点点的理清楚,对自己有利,对别人也有利。
还有就是可以升级到2.6内核哈,现在2.4有点过时了。例如新的slab也出来了。

内存管理俺看的是2.6的,呵呵

论坛徽章:
0
4 [报告]
发表于 2008-05-20 00:57 |显示全部楼层
原帖由 zx_wing 于 2008-5-20 00:48 发表

那LZ可以先选一个最熟悉的部分,写个特详细的,写完一个是一个。
我感觉现在好多同志都是基本原理知道,实现细节不清楚(我就是这样的
急切需要一个详细的文档来梳理

PS:成都今晚又要大震,电 ...

啊?可怜的孩子,早点休息啊!老弟的学习精神让人敬佩!
其实我也是源码和ULK结合看的,呵呵

[ 本帖最后由 frank_seng 于 2008-5-20 10:41 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2008-05-20 22:41 |显示全部楼层
原帖由 hlidea 于 2008-5-20 13:29 发表
frank_seng真是超级牛人,linuxforum上这个id也是你吧,还有个stephenseng的博客不会也是你的吧?
最喜欢这种站在一定高度概括全局的文章,要看代码的话,直接上情景分析好了
那三个zone没提到?不会2.6去掉了吧

hlidea兄猜的都是对的,火眼金星啊。另外zone还在,这里为了问题简单化把chap/zone/slab等统统忽略不提了。承蒙hlidea夸奖!

[ 本帖最后由 frank_seng 于 2008-5-20 22:48 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2008-05-20 22:44 |显示全部楼层
原帖由 W.Z.T 于 2008-5-20 21:36 发表
1. 内核初始化:

    * 内核建立好内核页目录页表数据库,假设物理内存大小为len,则建立了[3G--3G+len]::[0--len]这样的虚地址vaddr和物理地址paddr的线性对应关系;

这个len好象不是指的物理内存大小吧

该len为BIOS检测出的所有内存大小的总和,包括挂在总线上的RAM/ROM等等。BIOS检测后会以e820表项的形式存储起来,Linux内核启动后会读取这些e820表项的内容,得出系统中存在的RAM/ROM的分布及其总和,因此这里的物理内存不能仅仅理解成我们通常意义上的内存条RAM。

论坛徽章:
0
7 [报告]
发表于 2008-05-20 22:46 |显示全部楼层
原帖由 jgq516 于 2008-5-20 22:05 发表
"内核建立好内核页目录页表数据库,假设物理内存大小为len,则建立了[3G--3G+len]::[0--len]这样的虚地址vaddr和物理地址paddr的线性对应关系."
用户空间的虚拟地址(0——3G)和物理内存的对应关系是怎样的? ...

用户空间的虚拟地址是在使用时圈定的,并不是线性映射关系,请看上文中的5和6:
......
5. 用户进程申请内存vaddr = malloc(size):

    * 内存管理模块从用户进程内存空间(0--3G)中找到一块还没使用的空间vm_area_struct(start--end);
    * 随后将其插入到task->mm->mmap链表中;

6. 用户进程写入vaddr(0-3G),例如执行指令mov(eax, vaddr):

    * CPU获得vaddr这个虚地址,该虚地址应该已经由glibc库设置好了,一定在3G一下的某个区域,根据CR3寄存器指向的current->pgd查当前进程的页目录页表数据库,发现该vaddr对应的页目录表项为0,故产生异常;
    * 在异常处理中,发现该vaddr对应的vm_area_struct已经存在,为vaddr对应的页目录表项分配一个页表;
    * 随后从free_list找到一个page,将该page对应的物理页面物理首地址赋给vaddr对应的页表表项,很明显,此时的vaddr和paddr不是线性对应关系了;
    * 将page从free_list中脱离;
    * 异常处理返回;
    * CPU重新执行刚刚发生异常的指令mov(eax, vaddr);
    * CPU获得vaddr这个虚地址,根据CR3寄存器指向的current->pgd,利用建立好的页目录页表数据库,找到其对应的物理内存地址;
    * 将eax的内容写入vaddr对应的物理内存地址内;  
......

论坛徽章:
0
8 [报告]
发表于 2008-05-20 22:47 |显示全部楼层
原帖由 zx_wing 于 2008-5-20 14:45 发表

《情景分析》?有这么好吗,无数人奉为圣经。可能因为我比较反感源码注释的书。
个人认为除了ULK,其它讲内核的书都不如何。ULK就是概括性最好的书籍。
可惜的是,ULK站的高度太高,很难顾全很多地方,并且 ...

说心里话,情景分析还是很不错的!只是相对2.6来说略微过时了点。呵呵

论坛徽章:
0
9 [报告]
发表于 2008-05-20 23:17 |显示全部楼层
原帖由 zx_wing 于 2008-5-20 22:57 发表
问个问题
>>页目录页表数据库的主要目的是为CPU访问物理内存时转换vaddr-->paddr使用,分配以及释>>放内存时不会用到,但是需要内核内存管理系统在合适时机为CPU建立好该库;
释放的时候不会改页表?虽然我可 ...

呵呵,你指的是什么安全机制呢?

论坛徽章:
0
10 [报告]
发表于 2008-05-21 00:00 |显示全部楼层
原帖由 zx_wing 于 2008-5-20 23:27 发表

举个例子:
进程1申请了一块内存,对应物理页面A,页表中包含到页面A的映射。当该内存被free了过后,页表里的该映射仍然存在。
此时,进程2申请了一块内存,正好也被分配到了页面A。
x86是硬件查页表,当在 ...

哦,呵呵,关于“分配释放时不会用到”,这里解释下,在vaddr->paddr映射时,会用到某某页表表项值。在分配和释放时,会设置某某页表表项值,但并不是用这个页表表项值来做什么事情。前者(红色)是使用它,后者(蓝色)是设置其属性。

在释放时,如果对应的物理页面不再需要时,会清除掉对应的页表表项值的,但并没有用到该页表表项做什么事情,因此说没有用到它,之所以这么表达,就是为了试图揭露页表表项值的作用加本质。

[ 本帖最后由 frank_seng 于 2008-5-21 00:04 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP