发新话题
打印

关于 Linux 内存管理的学习方法

关于 Linux 内存管理的学习方法

  学习 Linux 内核,应该是首先建立清晰的概念,把握整体,然后才是深入细节。
内存管理看上去比较复杂,但我认为,掌握以下几个基本概念,在学习时,就能做到成竹在胸
欢迎补充、讨论!

1、内存管理的首要任务
   很简单,就是把可用的物理内存管理好。
   怎么管理?提供一套统一的接口,用于分配内存和释放内存。
   这套接口就是最基本的物理内存分配方式,采用的分配方法是伙伴策略。

   更高一级的内存分配策略
   基本的内存分配策略,可以避免外部因素导致的分片(外分片?)
   为了避免因为小于 1 page 的请求导致的分片(内分片),又在基本分配基础之上,采用了 SLAB 分配策略。当然,也可以采用其它的分配策略。

   记住,无论是内核代码,还是用户空间代码,都必须首先申请内存,然后才能使用。
   而无论什么分配方式,最终都是由基本的内存分配器负责分配分配内存。


2、理解 x86 的映射机制
   我们想直接访问一个物理内存的地址,如果那样,没有逻辑地址、虚拟地址、物理地址、段、页。。。的概念,世界多美好,
   但是,现实是残酷的。 X86 ,或者说现代的处理器,不允许你直接访问物理内存。(所有讲 Linux 操作系统的书都解释了原因)。
   我们必须使用逻辑地址,通过段映射,页映射,才能访问到物理内存。

   如何理解段映射和页映射????
   段映射和页映射,是 CPU 干的事情。内核所能做的事情,就是根据可用的物理内存,配置好页目录表、页表,然后告诉 CPU。
   对于同样一块物理内存,内核有内核的映射方式,每个进程有自己的映射方式。(正因为如此,才能在进程之间共享内存;也才能使得内核能访问进程的内存)
   内核对所有的物理内存(896M 以内)都进行了映射;但是映射并不表示分配!!!内核需要内存的时候,也得先申请,后使用。
   进程则只对必须使用的内存进行映射,并在需要的时候动态建立新的映射关系。

3、从用户空间进入内核空间,以及从内核空间返回用户空间时,页目录表、页表是如何发生切换的

在这三个概念基础之上,我们进一步可以理解:

4、进程空间如何管理内存
    进程虽然理论上拥有 3G 空间,但实际只使用很少的内存,因此进程是动态的建立映射关系的。
    此外,进程采用“内存区间”来管理属于自己的内存。
    当需要内存的时候,
    首先建立一个“内存区间”(线性地址)
    然后通过内存分配器,申请一块物理内存。
    最后,在“内存区间”与物理内存之间建立映射关系
嗯,看了LZ的言论,发现我还停留在3的阶段,要学的东西太多了。
Only the paranoid survive.
头脑中始终清醒的有这些基本概念,那么就可以进一步深入去学习伙伴策略、 SLAB 分配器、进程的“内存区间”,页目录表、页表的管理方式等等实现细节。而不至于被逻辑地址、线性地址(虚拟地址)、物理地址、内核空间、用户空间这些概念折腾的头晕脑张

我喜欢的学习方法是首先提出一系列问题,然后带着这些问题一个一个去书中,代码中求解。
其实,更高级的方法,应该是首先自己思考如何解决问题,然后去求证,而不是求解。当然,这可能就是最高境界了
正在学习linux内核的内存管理,小有收获!呵呵
初学者,发现还有好多东西要学
我想问个问题,用户空间访问内存和内核访问物理内存的不同在哪里?是不是用户空间通过分页机制,而内核通过映射(偏移PAGE_OFFSET)来访问物理内存?
答复楼上的问题, 我的理解是, OS不能直接访问内存, 只能通过CPU的MMU(通过地址映射)来访问内存, 因此只有 CR3 中和页表中存放的是物理地址, 其余代码中出现的地址都是线性地址. PAGE_OFFSET的使用, 我想只是为了算出物理地址, 然后就马上把这个地址赋值给 CR3 或页表, 不会直接使用这个地址的.
请版主看看我分析得是否正确?
发新话题