分类: LINUX
2011-12-03 23:34:54
内核中常用的内存分配函数有:kmalloc, __get_free_pages, vmalloc, alloc_pages, page_address
kmalloc:分配基于slab机制,但受限于slab一次最大分配的内存上限为128KB,最小为32或64字节。该函数返回的是虚拟地址,在3GB~high_memory的内核空间中,即NORMAL和DMA区(另外还有个是HIGH),因此要取得相应的物理地址,只需要减去PAGE_OFFSET即可,因此分配的时候,不需要设置页表,效率高。kmalloc分配的内存,在物理和虚拟空间上是连续的,有可能被阻塞,不能用在原子上下文中。
vmalloc:返回的也是虚拟地址,在 VMALLOC_START~4GB内核空间中。保证的是在虚拟地址空间上的连续,一般作为交换区、模块的分配。vmalloc 中调用了 kmalloc (GFP—KERNEL),因此也不能应用于原子上下文。vmalloc使用的正确场合是分配一大块,连续的,只在软件中存在的,用于缓冲的内存区域。不能在微处理器之外使用。Vmalloc能分配的大小相对较大。
举个例子:
内核空间中,从3G到vmalloc_start这段地址是物理内存映射区域(该区域中包括了内核镜像、物理页框表mem_map等等),好比我们使 用的 VMware虚拟系统内存是160M,那么3G~3G+160M这片内存就应当映射物理内存。在物理内存映射区之后,就是vmalloc区域。对于 160M的系统而言,vmalloc_start位置应在3G+160M邻近(在物理内存映射区与vmalloc_start期间还存在一个8M的gap 来避免跃界),vmalloc_end的位置濒临4G(最后地位系统会保存一片128k大小的区域用于专用页面映射)
要获得物理连续的大块内存,可以考虑直接分配页:
__get_free_page:返回的是页的虚拟地址,所在空间跟kmalloc一样,但是能获得更多连续的物理内存(<4M)。该函数是基于alloc_pages分配的。alloc_pages返回的是页描述符的虚拟地址,可以通过page_address将页描述符的地址,转换为页的地址。__get_free_page相当于这两者的封装。
page_address:该函数进行转换的时候,要分清是lowmem还是higtmem。如果是前者,直接__va(page_to_pfn(page) << PAGE_SHIFT),若是后者,需要在page_address_htable映射表中查找。
参考资料:
1http://blog.csdn.net/tigerjb/article/details/6412881
2http://blog.csdn.net/cnctloveyu/article/details/4256446
3http://blog.chinaunix.net/space.php?uid=20583479&do=blog&id=1920147