void *vmalloc(unsigned long size)用于分配一段虚拟地址联系的内存,注意这里只保证虚拟地址连续,
不能保证物理地址连续.
其源码分析如下:
void *vmalloc(unsigned long size)
{
return __vmalloc_node_flags(size, NUMA_NO_NODE,
GFP_KERNEL);
}
添加flags后调用__vmalloc_node_flags
static inline void *__vmalloc_node_flags(unsigned long size,
int node, gfp_t flags)
{
return __vmalloc_node(size, 1, flags, PAGE_KERNEL,
node, __builtin_return_address(0));
}
这里__builtin_return_address(0)保存的是__vmalloc_node_flags的地址
static void *__vmalloc_node(unsigned long size, unsigned long align,
gfp_t gfp_mask, pgprot_t prot,
int node, const void *caller)
{
return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
gfp_mask, prot, 0, node, caller);
}
从这里可以知道虚拟地址在VMALLOC_START~VMALLOC_END 之间
void *__vmalloc_node_range(unsigned long size, unsigned long align,
unsigned long start, unsigned long end, gfp_t gfp_mask,
pgprot_t prot, unsigned long vm_flags, int node,
const void *caller)
{
struct vm_struct *area;
void *addr;
unsigned long real_size = size;
#从这里可以知道vmalloc 申请的虚拟地址也是页page 对齐的
size = PAGE_ALIGN(size);
#size 为零或者size 超过最大的size ,则退出,从这里知道最大的size 等于totalram_pages
if (!size || (size >> PAGE_SHIFT) > totalram_pages)
goto fail;
#申请一个struct vm_struct *area的机构体内存
area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
vm_flags, start, end, node, gfp_mask, caller);
if (!area)
goto fail;
#申请虚拟连续的内存
addr = __vmalloc_area_node(area, gfp_mask, prot, node);
if (!addr)
return NULL;
/*
* In this function, newly allocated vm_struct has VM_UNINITIALIZED
* flag. It means that vm_struct is not fully initialized.
* Now, it is fully initialized, so remove this flag here.
*/
#清除VM_UNINITIALIZED 标志
clear_vm_uninitialized_flag(area);
#用于检测vmalloc 内存泄漏
kmemleak_vmalloc(area, size, gfp_mask);
#返回申请到大小为size的虚拟地址
return addr;
fail:
#失败的话,打印log,并返回null地址
warn_alloc(gfp_mask, NULL,
"vmalloc: allocation failure: %lu bytes", real_size);
return NULL;
}
内存管理API之vmalloc
最新推荐文章于 2023-05-25 14:08:36 发布