vmalloc 和 kmalloc 的详解

 琢磨了很久也参考了很多资料,发现很多都说的有点含糊,在这里先介绍一下Linux中对实际内存的一个分配,Linux内核将实际内存(注意是实际内存,这里暂且考虑不大于1G的内存)分为三个区段:可用于DMA的内存、常规内存以及高端内存。这里只介绍一下高端内存与地段内存。

       高端内存是指物理地址大于 896M 的内存。对于这样的内存,无法在“内核直接映射空间”进行映射。并没有和内核地址空间建立一一对应的关系(即虚拟地址=物理地址+PAGE_OFFSET这样的关系),所以不能使用get_free_pages()这样的页分配器进行内存的分配,而必须使用alloc_pages()这样的伙伴系统算法的接口得到struct *page结构,然后将其映射到内核地址空间,注意这个时候映射后的地址并非和物理地址相差PAGE_OFFSET.

   

     再来看看kmalloc(),kmalloc‍()是内核中最常见的内存分配方式,它最终调用伙伴系统的__get_free_pages()函数分配,(也就是说,对于分配高端内存来说,不能用kmalloc函数来进行分配)。根据传递给这个函数的flags参数,决定这个函数的分配适合什么场合,如果标志是GFP_KERNEL则仅仅可以用于进程上下文中,如果标志GFP_ATOMIC则可以用于中断上下文或者持有锁的代码段中。

kmalloc返回的线形地址是直接映射的,而且用连续物理页满足分配请求,且内置了最大请求数(2**5=32页)。

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

     总结一下:kmalloc()与kfree()对应,可以分配连续的物理内存

vmalloc()与vfree()对应,可以分配连续的虚拟内存,但是物理内存不一定连续,适用于分配大量内存

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

char *buf;

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

if(!buf)

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

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

vfree(buf);

你可能感兴趣的:(linux,算法,struct,linux内核)