浅析kmalloc、kfree和alloc_pages
文章来源:http://gliethttp.cublog.cn
1.kmalloc会从cache_sizes这个通用的cache上申请具体的slab对象,所以kmalloc的所能申请的内存大小:最小slab为32字节,最大slab对象为128k. static cache_sizes_t cache_sizes[] = { #if PAGE_SIZE == 4096 { 32, NULL, NULL}, #endif { 64, NULL, NULL}, { 128, NULL, NULL}, { 256, NULL, NULL}, { 512, NULL, NULL}, { 1024, NULL, NULL}, { 2048, NULL, NULL}, { 4096, NULL, NULL}, { 8192, NULL, NULL}, { 16384, NULL, NULL}, { 32768, NULL, NULL}, { 65536, NULL, NULL}, {131072, NULL, NULL}, { 0, NULL, NULL} }; kfree最终会调用__kmem_cache_free(),将当前内存归还到缓存cache_sizes相应slab上, 注意:并没有使用free_pages()->__free_pages_ok()将内存归还到Buddy伙伴算法管理的 zone->free_area[order]上,因为高速缓存上的slab对象,最后都会释放到相应高速缓存对应的slab的list链表中,这样才能提高常用内存的申请和释放速度,发挥slab的快速特性. 2.alloc_page()和alloc_pages()最终调用__alloc_pages(),使用Buddy伙伴算法,从 zone->free_area[order]或者拆分order+1之上的连续内存,申请若干页连续的物理内存. 在at91rm9200对应的linux2.4.19上,空闲页最大数组值默认为10,所以zone->free_pages[order]所能管理的最大连续物理 内存页上限值为2^9=512页,如果每页为4k的话,那么默认的linux系统所能申请到的最大连续物理内存为4k*512=2M字节。 3.如果需要申请2M以上的连续物理内存,怎么办,当前内核对应的方法只有一个:修改定制linux内核 定制方法1:使用static变量,申请自己需要的内存大小,如:static gliethttp_DMA[5M] 这种方法申请到的内存为静态内存,作为内核的数据部分, bootmem_init()初始化时, 会将内核code和data区域全部保护起来,进而在free_all_bootmem_node()释放内存到zone->free_area[order]时, 不至于将拷贝到内存中的linux内核code和data也释放到Buddy伙伴算法管理的zone->free_area[order]上, 所以linux内核的code和data不被作为内存管理空间.(gliethttp) 定制方法2:在mem_init()调用之前使用alloc_bootmem_pages()或者alloc_bootmem_low_pages()申请所需的连续大内存,如:5M; 这样mem_init()在调用free_all_bootmem_node()释放内存到zone->free_area[order]时,因为相应bitmap已经占用, 所以也不会将该5M内存空间释放到Buddy伙伴算法管理的zone->free_area[order]上,进而也就不会被内存管理单元 管理(gliethttp),当然cache缓存以及slab所使用到的内存最开始初始化时都是通过Buddy伙伴算法,从zone->free_area[order] 上申请到的,到2007/10/15日为止的所有linux内核,上面的这两个内存获取方法可以放心使用.(gliethttp)
|