驱动中动态内存申请(request_mem_region)

    利用动态内存生气编写驱动,使得驱动的具有较强的移植性,内核中封装了一些函数以供驱动开发者使用,屏蔽了具体的细节。

1. 动态获取内存的函数  request_mem_region()

#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)   

 

  (1)  iomem_resource :

struct resource {
	resource_size_t start;
	resource_size_t end;
	const char *name;
	unsigned long flags;
	struct resource *parent, *sibling, *child;
};

start:申请地址起始地址

end:申请地址结束地址

name:申请内存名字

flags:内存的标识,IO或者中断等。

 

struct resource iomem_resource = {
	.name	= "PCI mem",
	.start	= 0,
	.end	= -1,
	.flags	= IORESOURCE_MEM,
};

 #define IORESOURCE_MEM        0x00000200

flag 表示资源的类型,Linux中将IO、中断等统称为资源。

对iomem_resource 的理解:这是一个root节点,挂载着接下来申请的存储空间。这应该是内核管理动态内存申请释放的一种方法,所有动态申请的内存都挂接在一个父亲(parent)下面,多个动态内存间又是兄弟关系(sibling)。正如结构体 resource中最后一行定义的那样,这可是一个庞大的亲戚关系网络,只要找到其中一个child或者sibling,就能揪出整个家族 ~-~

2.  动态内存王国的缔造者 —— __request_region() 函数

struct resource * __request_region(struct resource *parent,
				   resource_size_t start, resource_size_t n,
				   const char *name, int flags)
{
	DECLARE_WAITQUEUE(wait, current);
	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);

	if (!res)
		return NULL;

	res->name = name;
	res->start = start;
	res->end = start + n - 1;
	res->flags = IORESOURCE_BUSY;
	res->flags |= flags;

	write_lock(&resource_lock);

	for (;;) {
		struct resource *conflict;

		conflict = __request_resource(parent, res);
		if (!conflict)
			break;
		if (conflict != parent) {
			parent = conflict;
			if (!(conflict->flags & IORESOURCE_BUSY))
				continue;
		}
		if (conflict->flags & flags & IORESOURCE_MUXED) {
			add_wait_queue(&muxed_resource_wait, &wait);
			write_unlock(&resource_lock);
			set_current_state(TASK_UNINTERRUPTIBLE);
			schedule();
			remove_wait_queue(&muxed_resource_wait, &wait);
			write_lock(&resource_lock);
			continue;
		}
		/* Uhhuh, that didn't work out.. */
		kfree(res);
		res = NULL;
		break;
	}
	write_unlock(&resource_lock);
	return res;
}

该函数中重点是  __request_resource(parent, res) 函数,当返回值为空,则跳出整个for循环,且返回 res。那么 __request_resource(parent, res) 究竟做了什么,在什么条件下才能放回 NULL,进入 __request_resource(parent, res)  ,一探究竟。通过__request_resource()函数,同时也鉴定了将要申请的内存是不是数据这个大家庭的,是就收留并返回NULL。第30行的if是对 IORESOURCE_MUXED(software muxed)的处理。

(1) __request_resource 

static struct resource * __request_resource(struct resource *root, struct resource *new)
{
	resource_size_t start = new->start;
	resource_size_t end = new->end;
	struct resource *tmp, **p;

	if (end < start)
		return root;
	if (start < root->start)
		return root;
	if (end > root->end)
		return root;
	p = &root->child;
	for (;;) {
		tmp = *p;
		if (!tmp || tmp->start > end) {
			new->sibling = tmp;
			*p = new;
			new->parent = root;
			return NULL;
		}
		p = &tmp->sibling;
		if (tmp->end < start)
			continue;
		return tmp;
	}
}

  前面三个if都是在判断将要申请资源的合法性,若非法,则返回root即为__request_region() 中的parent。for循环中对新加入的资源做了”亲子鉴定“,鉴定的原则是 兄弟间内存区域不能重叠!

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值