内存管理API之__get_vm_area

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值