驅動中動態內存申請(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循環中對新加入的資源做了”親子鑑定“,鑑定的原則是 兄弟間內存區域不能重疊!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章