Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2931530
  • 博文数量: 401
  • 博客积分: 12926
  • 博客等级: 上将
  • 技术积分: 4588
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-22 14:51
文章分类

全部博文(401)

文章存档

2015年(16)

2014年(4)

2013年(12)

2012年(82)

2011年(98)

2010年(112)

2009年(77)

分类: LINUX

2010-07-30 16:33:45

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



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

先说明图中符号的含义:
PAGE_OFFSET:0XC0000000,即3GB
high_memory:这个变量的字面含义是高端内存,到底什么是高端内存,Linux内核规定,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()都是在内核代码中用来分配内存的函数,但二者有何区别?
   从前面的介绍已经看出,这两个函数所分配的内存都处于内核空间,即从3GB4GB;但位置不同,kmalloc()分配的内存处于3GBhigh_memory之间,这一段内核空间与物理内存的映射一一对应,而vmalloc()分配的内存在VMALLOC_START4GB之间,这一段非连续内存区映射到物理内存也可能是非连续的。

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


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


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


char *buf;


buf = vmalloc16*PAGE_SIZE;  /*获得16*/


if !buf


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


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


vfreebuf);







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