本文共 1556 字,大约阅读时间需要 5 分钟。
struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,unsigned long start, unsigned long end)用于查找从start开始到end结束的线性地址区域,并从该区域中穿件size 字节大小的内核虚拟区间.其源码分析如下:struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, unsigned long start, unsigned long end){ #第二个形参表示1个字节对齐,同时这里通过__builtin_return_address(0) 来得到调用__get_vm_area的函数指针。 #这样可以很容易通过printf的%pF 来打印这个指针对应的symbol return __get_vm_area_node(size, 1, flags, start, end, NUMA_NO_NODE, GFP_KERNEL, __builtin_return_address(0));}static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long align, unsigned long flags, unsigned long start, unsigned long end, int node, gfp_t gfp_mask, const void *caller){ struct vmap_area *va; struct vm_struct *area; #不能在中断函数中调用这个函数 BUG_ON(in_interrupt()); #可见虽然指定1个byte对齐,但是这里其实还是按page size 对齐的. size = PAGE_ALIGN(size); #这里用unlikely修饰说明size 为0 是小概率事件. if (unlikely(!size)) return NULL; # 如果是io 空间的话,需要指定一个align if (flags & VM_IOREMAP) align = 1ul << clamp_t(int, get_count_order_long(size), PAGE_SHIFT, IOREMAP_MAX_ORDER); #申请一个struct vm_struct *area; 最后将这个结构体返回给用户,说明kernel中用这个 #结构体表示一段虚拟空间 area = kzalloc_node(sizeof(*area), gfp_mask & GFP_RECLAIM_MASK, node); if (unlikely(!area)) return NULL; #flags中没有包含VM_NO_GUARD的话。申请的size上在增加一个page size if (!(flags & VM_NO_GUARD)) size += PAGE_SIZE; #真正申请一段struct vmap_area *va; va = alloc_vmap_area(size, align, start, end, node, gfp_mask); if (IS_ERR(va)) { kfree(area); return NULL; } #将va的值赋值给area setup_vmalloc_vm(area, va, flags, caller); return area;}
转载地址:http://qgjmi.baihongyu.com/