Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2093522
  • 博文数量: 361
  • 博客积分: 10828
  • 博客等级: 上将
  • 技术积分: 4161
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-20 14:34
文章分类

全部博文(361)

文章存档

2011年(132)

2010年(229)

分类: LINUX

2010-02-27 09:54:22

从前一讲我们知道,内核空间为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);

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