免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 瀚海书香
打印 上一主题 下一主题

linux内存管理讨论——欢迎大家围观! [复制链接]

论坛徽章:
0
1 [报告]
发表于 2012-03-28 21:24 |显示全部楼层
我讲一讲自己在学习过程中遇到的不解之处,及各个概念的高度总结。好吧,其实是前几天发现包破了。。。。

1.内核是否有独立的地址空间。
X86上的Linux内核没有独立的地址空间。作为对比,DEC-11上的Unix V6内核有独立的地址空间,一旦进入内核态,页表自动切换。这样操纵用户态时就可跳出三界外。现在几乎没有操作系统这样做。根据某部FreeBSD著作所讲,内核态常做的一件事就是从、向用户空间搬、传数据。内核与用户态进程不在一个地址空间,则需要额外的指令在两个地址空间里传数据。

但这确实是一种设计,有其历史渊源。



2.内核态内存的映射。
X86上Linux内核之内核态虚拟地址,大部分固定地与低端物理内存一一映射。这样做的理由,一来是想更容易地访问物理内存,二来方便使用动态申请到的内存。DEC-11上的Unix V6内核就算有自己独立的地址空间,其大部分映射也是与物理内存一一对应的---在内核眼中,大部分虚拟地址与物理地址都是一样。

Linux上则仅仅有个差值。



3.896M与高端内存
X86上Linux内核与进程共用地址空间,另外,内核所有的地址空间被设计成与内存固定映射。结果是:内核拥有的地址空间很小(因为用户态占了大部分);能灵活使用的虚拟地址不多(因为大部分要与物理内存做一一对应的关联)。于是,内核能使用物理内存的大小被其狭小的虚拟地址空间所限制了。即便有再多的物理内存,内核已没有多余的虚拟地址与之映射,从而无法访问。

所以,896M用于与物理内存建立一一对应关系,剩余的虚拟地址空间,分时映射没能被896M覆盖到的物理内存,这部分物理内存就是高端内存。内核自己申请动态内存时,通常只在这896M以内申请,免得为了使用还得建立映射关系。其内部大量cache都在这一区域内,所以这块内存比较宝贵。用户虚拟地址空间可以随意设置,给用户态分配内存时,优先从高端内存取(如果有的话)。


4.映射与使用
内核映射了低端896M物理内存,大部分动态内存都从这里获得。但这并不是说这些内存就属于内核了,用户态不能用了。动态内存的使用要由mm子系统来协调,基本原理就是:分出去的内存不能再被分出去;收回来的内存可以被再分出去。动态内存的归属,最终由mm子系统来调度,申请到了再使用,这样才能保证秩序。分给用户态了,先建立映射,用户程序就可安心用了,即使内核可以直接访问这块内存,只要没有BUG,它都是很安全的。分给内核态了,直接使用即可--映射早已建立。

如果896M内的物理内存分给用户态,内核自然不能使用。而且与之关联的虚拟地址段也不能另作他用。可惜了。


5.虚拟地址空间
虚拟地址空间也是资源。于用户态而言,典型的例子是在扩展地址空间之时:需要找到一块没用的地址空间。必需得记录哪些地址空间被用了,哪些没有被用。分配虚拟地址空间与分配物理内存其实是一样的道理,只不过物理内存是全局的,需要用更精妙的算法来分配。Linux虚拟地址空间似使用first fit----沿途看看有没有合适的地址段,第一个找到的就是。其实Unix V6就是这么分配物理内存的。

有数据结构描述用户态地址空间段,内核怎么管理自己的虚拟地址空间呢?是什么决定其动态申请内存时获得内存的位置?由于大部分虚拟地址空间都与物理内存一一对应,两者完全可以合二为一:管理虚拟内存段就是管理物理内存。申请的虚拟地址的情况取决于申请到物理内存的情况。

高端分时复用的那一块虚拟地址空间,面临的需求和解决方案,与用户态一样。


6.Buddy System
管理物理内存最基本的要求:判断一块内存单位是否被使。只记录这一个信息的话,一个bit足矣。于是可以用一个bitmap描述当前物理内存的使用情况。实际上,一块内存单位的属性远不止是否被使用,其复杂程序需要用一个结构体来描述。下一步是考虑分配内存的策略。Buddy System就是策略的一种。其原理,至少从表面上看起来,并不复杂。它主要为了解决外部碎片:系统中有足够量的内存满足需要,但是这些内存散乱在各地,无法作为整体来使用。


7. Slab
现代操作系统通常以页作为物理内存单位,这是分配与回收的最小单位。分配一页给一页你,分配几byte还是得给一页你。如果分出去的内存大部分没有被使用,那就太可惜了。一个频繁分配小内存的代码段,可能会先分配几页,然后自己内部管理这些内存,通过某种方法一点点满足小内存分配的需要。slab就是提取出来,专门做这种事的代码。它并不在乎底层用的是何种内存分配方式,它只在乎地层提供的分配与释放的接口,然后向上层提供分配小块内存的接口。之前向底层要的物理内快完了,它会负责再要一点;之前从底层拿的内存多了用不完,它会择时还回去。它默默地做着这些脏活,留给上层一个功能简单明了的接口。


8.mmap与虚拟地址空间
以前看APUE,以为mmap是个trick十足的系统调用。后来才明白,如果不理解内核的cache系统,mmap的作用很难理解。在内核里,带mmap字样的函数更让人觉得trick:它们用来分配用户态的虚拟地址空间。这似乎偏离了mmap的初始意图。

初始的时候,虚拟地址空间的样子由可执行文件,比如ELF,来决定。如果地址空间与文件映射,就叫有名映射(好吧,好像没有这种叫法);如果纯粹扩展一段地址空间,比如从用户态上去理解malloc的语义,就叫匿名映射,虽然看不出来整个过程哪里跟映射有关了。于是,用户态的地址空间就这么一点一点被有名映射,无名映射筑起来了。


评分

参与人数 1可用积分 +10 收起 理由
瀚海书香 + 10 赞一个!

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP