分类: LINUX
2008-12-10 15:38:04
vmalloc和kmalloc的在逻辑地址上时连续的,他们的区别在于vmalloc在物理地址上并不时连续的,但是kmalloc在物理地址上页时连续的。Vmalloc分配分为两种模式,一种是没有MMU(memory management unit,内存管理模块)的vmalloc,比如在arm7上,另一种则是在有MMU上的vmalloc。
在没有MMU模块支持的cpu上,vmalloc则是调用的slab中的kmalloc实现的内存分配,其标志为(gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM
在有MMU模块的体系架构中的vmalloc(),则是通过__vmalloc_node()来分配连续逻辑内存
__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,int node, void *caller)的基本流程如下:
1、 错误处理,当待分配的大小为0,或者将size/页面大小 大于num_physpages时,返回空
2、 尝试调用__get_vm_area_node()获得虚拟内存空间的节点,失败则返回null
3、 返回__vmalloc_area_node(area, gfp_mask, prot, node, caller);的返回值
__vmalloc_area_node(area, gfp_mask, prot, node, caller)
1、 把nr_pages设置成vmalloc需要的线形地址的页面数量
2、 设置array_size成线形地址的页面所需要的指针空间的大小
3、 将nr_page交给area->nr_pages
4、 当array_size大于页面大小时,调用__vmalloc_node(array_size, gfp_mask | __GFP_ZERO,PAGE_KERNEL, node, caller) 分配空间给area->pages。否则,将kmalloc_node(array_size,(gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO,node)赋值给area->pages
5、 把caller的值传给area->caller
6、 如果area->pages分配时,移除area->addr中的地址,并且释放area,返回null
7、 遍历刚分配的页面,当node为负数时,采用alloc_page(gfp_mask)为page分配空间,或者,则利用alloc_pages_node(node, gfp_mask, 0)。分配失败时,将area->nr_pages的值设置成i,释放掉area->addr中地址的使用权,返回null.将area_page[i]设置成刚申请成功的内存页面。当map_vm_area(area, prot, &pages)成功映射,返回area->addr,否则释放掉area_addr,并返回空值。
在第七步可以知道,vmalloc在对内存进行分配的时候不是“慷慨”的一次性将内存给分配完,而是采用一个循环的方式,多次调用alloc_page()或者alloc_page_node对内存进行分配。这样或许可以更加充分的利用内存,一些零碎的小内存单元可能被利用,但是在速度上就相对于kmalloc的速度要慢不少。Kmalloc针对内存紧张的小内存单元页有相应的slob的分配方式,甚至在一些不支持MMU的设备上vmalloc等同于kmalloc。所以我个人认为在实际内核编码过程中,更多的使用kmalloc会好些。