Linux下的内存管理

来源:互联网 发布:数据库创建表 编辑:程序博客网 时间:2024/05/19 06:38

对于 Linux下的内存管理,首先从《Linux内核设计与实现》书上的说起。在书里面开篇就开始讲页面管理及其数据结构,这似乎与我们常常听到的段页式管理有所不同。其实,所谓的段页式管理是针对硬件的x86的,x86的系统为了保持与老版本系统的兼容性,采用了段页两级目录管理内存,可参看转载的上一篇文章了解这种管理机制。而事实上,即便Linux在x86平台上也并没是实现真正的段页式管理,所有的段地址最终都映射为0。因此,Linux真正实现的只是页面管理。

 

那么页面管理到底管理啥东西呢,我认为,简单讲,其实就是页面的申请,分配,使用和释放。在Linux系统中,页面是内存分配的最基本单位,如何理解呢?举个例子,我们常用malloc分配动态内存,最少甚至可以申请1个字节,看上去内存分配的单位是字节。实际的过程是这样的,malloc之类的库函数并不会直接从底层硬件层获取内存,而是查询页面占用状态,页面占用分为数据占满,部分空闲,空闲页面3种。malloc总是先在部分空闲的页面中获取内存,如果没有了部分空闲的页面,则从空闲页面获取,如果连空闲页面也没有,那么真正的页面分配就开始了。通过函数alloc_page()就能获取真正的物理内存(获取页面内存)。

 

从上面的例子也可以看出,页面管理是多么有必要(否则谁会知道你这个页面空闲,谁能知道你是第几个)。下面的数据结构介绍了一部分重要成员:

struct page

{

unsigned long  flags;     //表明 脏内存, 可否睡眠,所处空间

struct address_space mapping;  //用于跟文件一一对应的,它与下面的index一起就具体指定了文件内地址。具体参看分割线下的解释

unsigned long index;    //页面数据在文件中的偏移量,当页面内容被换出时,则指向页面去向(目前不是很明白)。

unsigned long ;

}

系统的每个物理页面都有一个page结构,在系统初始化阶段,就为每个物理页面建立了该结构,其存储方式是mem_map数组,数组的下标就是内存在物理页面中的序号。

 

根据体系结构的不同,页面是分区的,还是以x86为例,CPU的DMA方式只能访问前16MB地址空间,而整个CPU能访问到的内存空间也只有896MB,对于高于896MB的空间(高端地址),都是通过映射(可访问的模拟地址->高端物理地址)的方式访问的。

 

内存管理需要经常性的申请,释放内存,这给系统造成较大开销。因此,内存管理采用了类似于Cache的技术,称为slab分配器。简单讲,就是对于待释放的内存并不真正释放(只是做个标记),当下一次有相同类型的内存申请时,直接把这个内存给他并修改标志就可以了。这种方式对于系统中经常调用的一些结构,如task_struct等非常的有用。

 

=================================分割线========================================

address_space是用来描述文件的(交换区也用它)
一般一个数据文件在我们的印象中是一个连续的字节映象。但是这只是一个逻辑上的概念,而:
在内存中,这个文件很可能不是连续的,而是被分割成页,页内是连续的,但是页之间却不一定连续。在外设中,这个文件同样不一定连续。它的粒度相对于内存中就更小了,是一个个的block,而不是页(block小于等于page) 。这样,我们实际上有3个映象:
逻辑映象(供用户使用)
内存映象
外设映象
它们之间构成一一映射。一个address_space就是用来管理一个文件的这些映象。page->mapping如果不为空的话,说明它是一个文件的页,也就是该页在内存映象中。并且mapping指向对应的address_space 相关处理主要集中在filemap.c中,mapping的初始化在下面函数中完成:

add_page_to_inode_queue
这个函数将一个页加到一个文件的内存映象中。交换区也用一个address_space来管理。
---------------------------

参考文献:

http://blog.csdn.net/lne818/archive/2006/08/01/1006744.aspx