linux内核内存申请函数:devm_kzalloc函数的实现进行解析
設備注冊函數過程一般會用到內存申請,如上。下面我們參考資料分析一下過程。
///
前言
Linux Kernel devm_* API源碼分析
本文通過對devm_kzalloc函數的實現進行解析,幫助理解devm系列api的用法。
devm系列api的主要特別之處:
??? 使用devm系列申請到的資源可以由系統自動釋放,解放雙手
一、devm_kzalloc & devm_kfree代碼
struct devres {
??? struct devres_node????? node;
??? /* -- 3 pointers */
??? unsigned long long????? data[]; /* guarantee ull alignment */
};
struct devres_node {
??? struct list_head??????? entry;
??? dr_release_t??????????? release;
#ifdef CONFIG_DEBUG_DEVRES
??? const char????????? *name;
??? size_t????????????? size;
#endif
};
void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
{
??? struct devres *dr;
?
??? /* use raw alloc_dr for kmalloc caller tracing */
??? dr = alloc_dr(devm_kzalloc_release, size, gfp);
??? if (unlikely(!dr))
??????? return NULL;
?
??? set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
??? devres_add(dev, dr->data);
??? return dr->data;
}
static __always_inline struct devres * alloc_dr(dr_release_t release,
??????????????????????? size_t size, gfp_t gfp)
{
??? size_t tot_size = sizeof(struct devres) + size;
??? struct devres *dr;
?
??? dr = kmalloc_track_caller(tot_size, gfp);
??? if (unlikely(!dr))
??????? return NULL;
?
??? memset(dr, 0, tot_size);
??? INIT_LIST_HEAD(&dr->node.entry);
??? dr->node.release = release;
??? return dr;
}
/*alloc_dr函數負責分配內存,返回的devres就包含分配到的內存,通過devres.data來訪問即可.
devres_add(dev, dr->data);函數將數據與device進行綁定,實際調用add_dr,在這里將資源的節點頭添加到device的devres_head鏈表中*/
/**
?* devres_add - Register device resource
?* @dev: Device to add resource to
?* @res: Resource to register
?*
?* Register devres @res to @dev.? @res should have been allocated
?* using devres_alloc().? On driver detach, the associated release
?* function will be invoked and devres will be freed automatically.
?*/
void devres_add(struct device *dev, void *res)
{
?? ?struct devres *dr = container_of(res, struct devres, data);
?? ?unsigned long flags;
?? ?spin_lock_irqsave(&dev->devres_lock, flags);
?? ?add_dr(dev, &dr->node);
?? ?spin_unlock_irqrestore(&dev->devres_lock, flags);
}
static void add_dr(struct device *dev, struct devres_node *node)
{
??? devres_log(dev, node, "ADD");
??? BUG_ON(!list_empty(&node->entry));
??? list_add_tail(&node->entry, &dev->devres_head);
}
/*現在資源與dev的綁定已經完成,下面就找一找是如何釋放資源的.
device_release_driver -> devres_release_all->release_nodes*/
static int release_nodes(struct device *dev, struct list_head *first,
???????????? struct list_head *end, unsigned long flags)
??? __releases(&dev->devres_lock)
{
??? LIST_HEAD(todo);
??? int cnt;
??? struct devres *dr, *tmp;
?
??? cnt = remove_nodes(dev, first, end, &todo);
?
??? spin_unlock_irqrestore(&dev->devres_lock, flags);
?
??? /* Release.? Note that both devres and devres_group are
???? * handled as devres in the following loop.? This is safe.
???? */
??? list_for_each_entry_safe_reverse(dr, tmp, &todo, node.entry) {
??????? devres_log(dev, &dr->node, "REL");
??????? dr->node.release(dev, dr->data);
??????? kfree(dr);
??? }
?
??? return cnt;
}
?
二、資源釋放
kzalloc()實現了kmalloc()+memset()的功能,而 devm_kzalloc() 是具有資源管理的 kzalloc()。使用資源管理(resource-managed)函數分配的內存,是會與所屬設備相關聯。當設備從系統中分離或者設備驅動被卸載,該內存會被自動釋放。也可以通過devm_kfree()來釋放內存。
static inline void *kzalloc(size_t size, gfp_t flags)
{
?? ?return kmalloc(size, flags | __GFP_ZERO);
}
總結
以上是生活随笔為你收集整理的linux内核内存申请函数:devm_kzalloc函数的实现进行解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NC65 对上年度反结账,调整数据后重新
- 下一篇: linux 其他常用命令