利用動態內存生氣編寫驅動,使得驅動的具有較強的移植性,內核中封裝了一些函數以供驅動開發者使用,屏蔽了具體的細節。
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循環中對新加入的資源做了”親子鑑定“,鑑定的原則是 兄弟間內存區域不能重疊!