Chinaunix首页 | 论坛 | 博客
  • 博客访问: 946936
  • 博文数量: 104
  • 博客积分: 1919
  • 博客等级: 上尉
  • 技术积分: 1910
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-21 16:33
文章分类
文章存档

2016年(4)

2015年(1)

2014年(6)

2013年(16)

2012年(27)

2011年(49)

2010年(1)

分类: LINUX

2013-11-12 11:28:59

从前一讲我们知道,内核空间为3GB~4GB,这1GB的空间分为如下几部分,如图1所示:

            图1   从PAGE_OFFSET开始的1GB地址空间  


先说明图中符号的含义:

PAGE_OFFSET:0XC0000000,即3GB

high_memory:这个变量的字面含义是高端内存,到底什么是高端内存,内核规定,RAM的前896为所谓的低端内存,而896~1GB共128MB为高端内存。如果你的内存是512M,那么high_memory是多少?是3GB+512,也就是说,物理地址x<=896M,就有内核地址0xc0000000+x,否则,high_memory=0xc0000000+896M 
或者说high_memory最大值为0xc0000000+896M ,实际值为0xc0000000+x

在源代码中函数mem_init中,有这样一行:

high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
其中,max_low_pfn为物理内存的最大页数。

所以在图中,PAGE_OFFSET到high_memory 之间就是所谓的物理内存映射。只有这一段之间,物理地址与虚地址之间是简单的线性关系。

还要说明的是,要在这段内存分配内存,则调用kmalloc()函数。反过来说,通过kmalloc()分配的内存,其物理页是连续的。


VMALLOC_START:非连续区的的起始地址。

VMALLOC_END:非连续区的的末尾地址

在非连续区中,物理内存映射的末端与第一个VMalloc之间有一个8MB的安全区,目的是为了“捕获”对内存的越界访问。处于同样的理由,插入其他4KB的安全区来隔离非连续区。


非连续区的分配调用VMalloc()函数。


vmalloc()与kmalloc()都是在内核代码中用来分配内存的函数,但二者有何区别?

  从前面的介绍已经看出,这两个函数所分配的内存都处于内核空间,即从3GB~4GB;但位置不同,kmalloc()分配的内存处于3GB~high_memory之间,这一段内核空间与物理内存的映射一一对应,而vmalloc()分配的内存在VMALLOC_START~4GB之间,这一段非连续内存区映射到物理内存也可能是非连续的。

   vmalloc()工作方式与kmalloc()类似,其主要差别在于前者分配的物理地址无需连续,而后者确保页在物理上是连续的(虚地址自然也是连续的)。

尽管仅仅在某些情况下才需要物理上连续的内存块,但是,很多内核代码都调用kmalloc(),而不是用vmalloc()获得内存。这主要是出于性能的考虑。vmalloc()函数为了把物理上不连续的页面转换为虚拟地址空间上连续的页,必须专门建立页表项。还有,通过vmalloc()获得的页必须一个一个的进行映射(因为它们物理上不是连续的),这就会导致比直接内存映射大得多的缓冲区刷新。因为这些原因,vmalloc()仅在绝对必要时才会使用——典型的就是为了获得大块内存时,例如,当模块被动态插入到内核中时,就把模块装载到由vmalloc()分配的内存上。

vmalloc()函数用起来比较简单:

char *buf;

buf = vmalloc(16*PAGE_SIZE); /*获得16页*/

if(!buf)

    /*错误!不能分配内存*/

在使用完分配的内存之后,一定要释放它:

vfree(buf);

转:http://blog.chinaunix.net/u1/49221/showart_1097264.html

阅读(2340) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~