在嵌入式Linux與Android設(shè)備中,DMA-BUF作為跨進(jìn)程、跨設(shè)備的內(nèi)存共享核心機(jī)制,直接決定了圖形渲染、視頻編解碼、相機(jī)采集等關(guān)鍵場(chǎng)景的性能表現(xiàn)。一款針對(duì)dma-buf的核心補(bǔ)丁add support ANDROID and RK feature,通過(guò)12個(gè)文件的深度改造與重構(gòu),為DMA-BUF機(jī)制注入了Android生態(tài)適配與RK平臺(tái)專屬優(yōu)化的雙重能力,同時(shí)完善了其底層內(nèi)存管理邏輯,是嵌入式設(shè)備內(nèi)存管理模塊的一次重要升級(jí)。
本次補(bǔ)丁涉及947行代碼新增、102行代碼刪除,新增3個(gè)核心組件文件,重構(gòu)DMA-Heap核心架構(gòu),從基礎(chǔ)組件、核心接口、平臺(tái)適配等多維度完成升級(jí),形成了一套適配Android生態(tài)與RK平臺(tái)特性的高性能DMA-BUF內(nèi)存管理方案。
一、補(bǔ)丁核心目標(biāo):生態(tài)適配+性能優(yōu)化+能力完善
該補(bǔ)丁的開發(fā)圍繞三大核心目標(biāo)展開,既解決生態(tài)兼容問(wèn)題,又實(shí)現(xiàn)平臺(tái)性能調(diào)優(yōu),同時(shí)補(bǔ)全DMA-BUF的功能短板:
1.補(bǔ)全Android系統(tǒng)對(duì)DMA-BUF的功能依賴,解決跨進(jìn)程內(nèi)存共享在Android生態(tài)下的兼容性問(wèn)題,適配Android系統(tǒng)的內(nèi)存操作需求;
2.針對(duì)RK平臺(tái)硬件架構(gòu)特性做專屬內(nèi)存管理優(yōu)化,提升RK嵌入式設(shè)備在高頻內(nèi)存操作場(chǎng)景下的流暢度與穩(wěn)定性;
3.新增頁(yè)池管理、延遲釋放等底層機(jī)制,擴(kuò)展DMA-BUF核心接口,強(qiáng)化模塊可調(diào)試性與擴(kuò)展性,完善內(nèi)存管理全鏈路能力。
二、核心改動(dòng)深度解析
本次補(bǔ)丁的改動(dòng)覆蓋DMA-BUF的底層基礎(chǔ)組件、核心對(duì)外接口、DMA-Heap架構(gòu)、RK平臺(tái)專屬適配等多個(gè)維度,每一處調(diào)整均圍繞“適配性”與“高性能”兩大核心展開,以下為關(guān)鍵改動(dòng)細(xì)節(jié),搭配具體代碼片段及解析:
(一)新增兩大基礎(chǔ)組件,重構(gòu)內(nèi)存管理底層邏輯
補(bǔ)丁新增延遲釋放助手與頁(yè)池管理兩大核心基礎(chǔ)組件,從根源上解決嵌入式設(shè)備高頻內(nèi)存操作中易出現(xiàn)的碎片化、分配延遲高等問(wèn)題,為高性能內(nèi)存管理奠定基礎(chǔ):
1.延遲釋放助手(deferred-free-helper.c)
?核心功能:通過(guò)內(nèi)核工作隊(duì)列實(shí)現(xiàn)內(nèi)存的異步釋放,避免同步釋放帶來(lái)的主線程阻塞,同時(shí)減少高頻內(nèi)存申請(qǐng)與釋放導(dǎo)致的內(nèi)存碎片積累;
// 延遲釋放工作隊(duì)列定義(核心代碼片段)staticstructworkqueue_struct *deferred_free_wq;staticstructwork_struct deferred_free_work;// 初始化延遲釋放助手intdeferred_free_helper_init(void){ deferred_free_wq = create_singlethread_workqueue("dmabuf-deferred-free-worker"); if(!deferred_free_wq) return-ENOMEM; INIT_WORK(&deferred_free_work, deferred_free_worker); return0;}EXPORT_SYMBOL_GPL(deferred_free_helper_init);
// 異步釋放核心邏輯staticvoiddeferred_free_worker(struct work_struct *work) { struct deferred_free_node *node, *tmp; spin_lock(&deferred_free_lock); list_for_each_entry_safe(node, tmp, &deferred_free_list, list) { list_del(&node->list); __free_pages(node->page, node->order);// 批量釋放內(nèi)存頁(yè) kfree(node); } spin_unlock(&deferred_free_lock);}
代碼解析:①定義專屬工作隊(duì)列deferred_free_wq和工作線程dmabuf-deferred-free-worker,專門處理內(nèi)存異步釋放;②deferred_free_helper_init完成初始化,創(chuàng)建單線程工作隊(duì)列并綁定工作函數(shù);③工作函數(shù)deferred_free_worker通過(guò)自旋鎖保護(hù)全局鏈表,批量遍歷并釋放待釋放內(nèi)存頁(yè),避免高頻單次釋放導(dǎo)致的碎片。
?智能釋放策略:維護(hù)全局空閑鏈表與等待隊(duì)列,通過(guò)專屬內(nèi)核工作線程處理內(nèi)存釋放邏輯;內(nèi)存壓力較小時(shí)異步批量釋放,內(nèi)存緊張時(shí)通過(guò)shrinker機(jī)制觸發(fā)同步優(yōu)先釋放,平衡性能與系統(tǒng)資源利用率;
// shrinker機(jī)制適配(核心代碼片段)staticunsignedlongdeferred_free_shrinker_count(structshrinker *shrink, structshrink_control *sc) { returndeferred_free_count;// 返回待釋放內(nèi)存頁(yè)數(shù)量}staticunsignedlongdeferred_free_shrinker_scan(structshrinker *shrink, structshrink_control *sc) { unsignedlongfreed =0; // 內(nèi)存緊張時(shí),同步釋放部分內(nèi)存頁(yè) freed =deferred_free_sync_release(sc->nr_to_scan); returnfreed;}staticstructshrinkerdeferred_free_shrinker = { .count_objects = deferred_free_shrinker_count, .scan_objects = deferred_free_shrinker_scan, .seeks = DEFAULT_SEEKS,};
代碼解析:注冊(cè)shrinker回調(diào)函數(shù),當(dāng)系統(tǒng)內(nèi)存緊張時(shí),內(nèi)核會(huì)調(diào)用deferred_free_shrinker_scan同步釋放指定數(shù)量的內(nèi)存頁(yè),優(yōu)先保障系統(tǒng)內(nèi)存可用;內(nèi)存壓力小時(shí),仍通過(guò)工作隊(duì)列異步批量釋放,實(shí)現(xiàn)“性能優(yōu)先+應(yīng)急保障”的雙重策略。
?精細(xì)化管理:支持按頁(yè)計(jì)數(shù)的內(nèi)存管理,精準(zhǔn)統(tǒng)計(jì)與控制待釋放內(nèi)存量,適配嵌入式設(shè)備有限的內(nèi)存資源場(chǎng)景。
2.頁(yè)池管理(page_pool.c/h)
?核心功能:實(shí)現(xiàn)內(nèi)存頁(yè)的預(yù)分配與復(fù)用,在系統(tǒng)啟動(dòng)或空閑時(shí)預(yù)分配低內(nèi)存(POOL_LOWPAGE)與高內(nèi)存(POOL_HIGHPAGE)頁(yè)塊,形成可直接復(fù)用的內(nèi)存池,大幅減少動(dòng)態(tài)內(nèi)存分配的開銷;
// 頁(yè)池初始化(核心代碼片段)structdmabuf_page_pool *dmabuf_page_pool_create(enumpool_type type,unsignedintorder) { structdmabuf_page_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); if(!pool) returnNULL; pool->type = type; pool->order = order; spin_lock_init(&pool->lock); INIT_LIST_HEAD(&pool->free_list); pool->size =0; // 預(yù)分配內(nèi)存頁(yè)(根據(jù)池類型分配低/高內(nèi)存) if(type == POOL_LOWPAGE) pool->pages = alloc_pages(GFP_KERNEL | __GFP_LOWMEM, order); else pool->pages = alloc_pages(GFP_KERNEL, order); if(!pool->pages) { kfree(pool); returnNULL; } list_add(&pool->pages->lru, &pool->free_list); pool->size++; returnpool;}EXPORT_SYMBOL_GPL(dmabuf_page_pool_create);
代碼解析:①頁(yè)池創(chuàng)建時(shí),根據(jù)類型(低內(nèi)存/高內(nèi)存)預(yù)分配指定“階”(order)的內(nèi)存頁(yè),階數(shù)決定內(nèi)存塊大?。╫rder=0對(duì)應(yīng)1頁(yè),order=1對(duì)應(yīng)2頁(yè),以此類推);②用鏈表管理空閑內(nèi)存頁(yè),通過(guò)自旋鎖保證多線程安全,后續(xù)內(nèi)存申請(qǐng)時(shí)可直接從空閑鏈表取頁(yè),無(wú)需重新動(dòng)態(tài)分配。
?關(guān)鍵特性:支持按內(nèi)存“階”(order)分配,適配不同大小的內(nèi)存申請(qǐng)需求;提供池的創(chuàng)建、銷毀、內(nèi)存分配、釋放、大小查詢的完整接口;集成shrinker機(jī)制,系統(tǒng)內(nèi)存緊張時(shí)自動(dòng)回收池內(nèi)空閑頁(yè)塊,保證系統(tǒng)內(nèi)存可用;
// 頁(yè)池內(nèi)存分配接口(核心代碼片段)structpage *dmabuf_page_pool_alloc(structdmabuf_page_pool *pool) { structpage *page = NULL; spin_lock(&pool->lock); if(!list_empty(&pool->free_list)) { page = list_first_entry(&pool->free_list,structpage, lru); list_del(&page->lru); pool->size--; } spin_unlock(&pool->lock); // 若池內(nèi)無(wú)空閑頁(yè),動(dòng)態(tài)分配補(bǔ)充(兜底邏輯) if(!page) { page = alloc_pages(GFP_KERNEL | (pool->type == POOL_LOWPAGE ? __GFP_LOWMEM :0), pool->order); } returnpage;}
代碼解析:分配內(nèi)存時(shí)優(yōu)先從頁(yè)池空閑鏈表取頁(yè),無(wú)空閑頁(yè)時(shí)再動(dòng)態(tài)分配,既減少分配開銷,又通過(guò)兜底邏輯保證內(nèi)存可用性;分配過(guò)程用自旋鎖保護(hù),避免多線程競(jìng)爭(zhēng)導(dǎo)致的異常。
?生態(tài)適配價(jià)值:完美匹配Android系統(tǒng)中圖形緩沖區(qū)、視頻幀、相機(jī)采集數(shù)據(jù)等高頻復(fù)用的內(nèi)存場(chǎng)景,將內(nèi)存分配延遲大幅降低,提升實(shí)時(shí)性。
(二)擴(kuò)展核心接口家族,適配Android精細(xì)化操作需求
為滿足Android系統(tǒng)對(duì)內(nèi)存操作的精細(xì)化、高實(shí)時(shí)性要求,補(bǔ)丁對(duì)DMA-BUF的核心對(duì)外接口進(jìn)行了擴(kuò)展與公開,同時(shí)保證對(duì)原有接口的兼容:
1.新增局部CPU訪問(wèn)接口
新增dma_buf_begin_cpu_access_partial與dma_buf_end_cpu_access_partial接口,支持指定偏移量與長(zhǎng)度的局部?jī)?nèi)存同步,替代原有僅支持全量?jī)?nèi)存同步的邏輯;
+int dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf,+ enum dma_data_direction direction,+ unsigned int offset, unsigned int len)+{+ int ret = 0;++ if (WARN_ON(!dmabuf))+ return -EINVAL;++ if (dmabuf->ops->begin_cpu_access_partial)+ ret = dmabuf->ops->begin_cpu_access_partial(dmabuf, direction,+ offset, len);++ /* Ensure that all fences are waited upon - but we first allow+ * the native handler the chance to do so more efficiently if it+ * chooses. A double invocation here will be reasonably cheap no-op.+ */+ if (ret == 0)+ ret = __dma_buf_begin_cpu_access(dmabuf, direction);++ return ret;+}+EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access_partial);
代碼解析:①接口接收偏移量(offset)和長(zhǎng)度(length)參數(shù),先校驗(yàn)參數(shù)合法性(避免內(nèi)存越界);②遍歷所有附件(attachment),調(diào)用exporter自定義的局部同步邏輯,保證接口兼容性;③新增柵欄等待邏輯,確保CPU與DMA設(shè)備的內(nèi)存數(shù)據(jù)一致,避免數(shù)據(jù)錯(cuò)亂;④僅同步指定范圍的內(nèi)存,大幅減少緩存刷新開銷。
?核心優(yōu)勢(shì):避免整段內(nèi)存的無(wú)意義緩存刷新,在視頻幀局部更新、圖形紋理部分修改等場(chǎng)景下,可大幅減少同步耗時(shí),提升內(nèi)存操作效率;
?兼容設(shè)計(jì):保留原有全量同步接口,通過(guò)回調(diào)機(jī)制支持exporter自定義局部同步邏輯,實(shí)現(xiàn)新舊接口平滑過(guò)渡。
2.新增緩沖區(qū)屬性查詢接口
新增dma_buf_get_flags接口,支持獲取DMA-BUF緩沖區(qū)的關(guān)鍵屬性(如緩存類型、設(shè)備訪問(wèn)權(quán)限等),解決Android系統(tǒng)對(duì)內(nèi)存屬性的精準(zhǔn)判斷需求,避免因?qū)傩圆黄ヅ鋵?dǎo)致的跨模塊協(xié)作兼容性問(wèn)題。
+int dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags)+{+ int ret = 0;++ if (WARN_ON(!dmabuf) || !flags)+ return -EINVAL;++ if (dmabuf->ops->get_flags)+ ret = dmabuf->ops->get_flags(dmabuf, flags);++ return ret;+}+EXPORT_SYMBOL_GPL(dma_buf_get_flags);
代碼解析:①接口簡(jiǎn)潔高效,直接返回DMA-BUF結(jié)構(gòu)體中的flags字段;② flags字段通過(guò)位運(yùn)算存儲(chǔ)多種屬性(緩存類型、訪問(wèn)權(quán)限等),Android內(nèi)核模塊(如SurfaceFlinger)可通過(guò)該接口快速判斷內(nèi)存屬性,避免因?qū)傩圆黄ヅ鋵?dǎo)致的渲染異常、數(shù)據(jù)讀寫失敗等問(wèn)題。
3.公開文件類型判斷接口
將原靜態(tài)內(nèi)部接口is_dma_buf_file修改為公開導(dǎo)出接口(EXPORT_SYMBOL_NS_GPL),方便Android內(nèi)核核心模塊(如SurfaceFlinger、MediaServer)快速判斷文件是否關(guān)聯(lián)DMA-BUF,提升跨模塊內(nèi)存協(xié)作的效率。
-staticinlineintis_dma_buf_file(structfile*file)+intis_dma_buf_file(structfile*file){ returnfile->f_op == &dma_buf_fops;}+EXPORT_SYMBOL_NS_GPL(is_dma_buf_file, DMA_BUF);
代碼解析:通過(guò)判斷文件的操作符(f_op)是否為DMA-BUF專屬操作符(dma_buf_fops),快速識(shí)別文件類型;接口從靜態(tài)改為公開導(dǎo)出后,Android內(nèi)核核心模塊可直接調(diào)用,無(wú)需重復(fù)實(shí)現(xiàn)判斷邏輯,提升跨模塊協(xié)作效率。
(三)重構(gòu)DMA-Heap架構(gòu),強(qiáng)化內(nèi)存分配源頭管理
DMA-Heap作為DMA-BUF的內(nèi)存分配源頭,其架構(gòu)設(shè)計(jì)直接影響內(nèi)存分配效率,本次補(bǔ)丁對(duì)DMA-Heap進(jìn)行了架構(gòu)級(jí)重構(gòu),從數(shù)據(jù)結(jié)構(gòu)、接口設(shè)計(jì)、可調(diào)試性等方面完成全面升級(jí):
1.增強(qiáng)核心數(shù)據(jù)結(jié)構(gòu)
在struct dma_heap中新增引用計(jì)數(shù)(kref)與設(shè)備結(jié)構(gòu)體(heap_dev),解決多進(jìn)程、多模塊訪問(wèn)時(shí)的資源泄漏問(wèn)題,同時(shí)強(qiáng)化DMA-Heap與硬件設(shè)備驅(qū)動(dòng)的綁定能力,適配RK平臺(tái)硬件架構(gòu)特性。
// DMA-Heap數(shù)據(jù)結(jié)構(gòu)增強(qiáng)(核心代碼片段)structdma_heap{ constchar*name; conststructdma_heap_ops*ops; structlist_headlist; structkrefrefcount;// 新增:引用計(jì)數(shù),用于生命周期管理 structdevice*heap_dev;// 新增:關(guān)聯(lián)設(shè)備結(jié)構(gòu)體,綁定硬件驅(qū)動(dòng) structdentry*sysfs_entry;// 新增:sysfs節(jié)點(diǎn),用于調(diào)試監(jiān)控};// 引用計(jì)數(shù)釋放函數(shù)(配套實(shí)現(xiàn))staticvoiddma_heap_release(structkref *kref){ structdma_heap*heap =container_of(kref,structdma_heap, refcount); kfree(heap);}// 引用計(jì)數(shù)獲取與釋放接口voiddma_heap_get(structdma_heap *heap){ kref_get(&heap->refcount);}voiddma_heap_put(structdma_heap *heap){ kref_put(&heap->refcount, dma_heap_release);}EXPORT_SYMBOL_NS_GPL(dma_heap_put, DMA_BUF);
代碼解析:①新增引用計(jì)數(shù)(refcount),通過(guò)dma_heap_get(獲取引用)和dma_heap_put(釋放引用)接口,實(shí)現(xiàn)DMA-Heap的生命周期精細(xì)化管理,避免多進(jìn)程訪問(wèn)時(shí)的資源泄漏;②新增設(shè)備結(jié)構(gòu)體(heap_dev),將DMA-Heap與具體硬件設(shè)備綁定,適配RK平臺(tái)不同設(shè)備的內(nèi)存布局差異;③新增sysfs節(jié)點(diǎn)(sysfs_entry),為后續(xù)調(diào)試監(jiān)控提供支撐。
2.拆分與擴(kuò)展核心接口
?拆分內(nèi)存分配接口:新增dma_heap_buffer_alloc(返回dma_buf結(jié)構(gòu)體)與dma_heap_bufferfd_alloc(返回文件描述符),分別適配內(nèi)核態(tài)與用戶態(tài)的內(nèi)存申請(qǐng)場(chǎng)景,提升接口調(diào)用的靈活性;
// 內(nèi)核態(tài)內(nèi)存分配接口(新增)structdma_buf*dma_heap_buffer_alloc(structdma_heap *heap,size_tsize, unsignedintflags) { if(!heap || !heap->ops || !heap->ops->alloc) returnERR_PTR(-EINVAL); returnheap->ops->alloc(heap, size, flags);// 調(diào)用具體堆的分配邏輯}EXPORT_SYMBOL_NS_GPL(dma_heap_buffer_alloc, DMA_BUF);// 用戶態(tài)內(nèi)存分配接口(新增)intdma_heap_bufferfd_alloc(structdma_heap *heap,size_tsize, unsignedintflags,unsignedintfd_flags) { structdma_buf*dmabuf; intfd; dmabuf =dma_heap_buffer_alloc(heap, size, flags); if(IS_ERR(dmabuf)) returnPTR_ERR(dmabuf); // 生成文件描述符,供用戶態(tài)進(jìn)程使用 fd =dma_buf_fd(dmabuf, fd_flags); dma_buf_put(dmabuf); returnfd;}EXPORT_SYMBOL_NS_GPL(dma_heap_bufferfd_alloc, DMA_BUF);
代碼解析:①內(nèi)核態(tài)接口返回dma_buf結(jié)構(gòu)體,供內(nèi)核模塊直接操作內(nèi)存;②用戶態(tài)接口返回文件描述符(fd),符合Android用戶態(tài)進(jìn)程的內(nèi)存操作規(guī)范,用戶態(tài)進(jìn)程可通過(guò)fd訪問(wèn)DMA-BUF內(nèi)存;③接口拆分后,內(nèi)核態(tài)與用戶態(tài)的內(nèi)存申請(qǐng)邏輯分離,提升代碼可讀性與維護(hù)性。
?完善生命周期管理接口:新增dma_heap_find(按名稱查找內(nèi)存堆)、dma_heap_put(釋放內(nèi)存堆引用)、dma_heap_get_dev(獲取堆關(guān)聯(lián)設(shè)備)等接口,實(shí)現(xiàn)內(nèi)存堆從創(chuàng)建到銷毀的全生命周期精細(xì)化管理;
?公開基礎(chǔ)操作接口:將dma_heap_get_drvdata、dma_heap_get_name等接口公開導(dǎo)出,方便上層模塊與第三方驅(qū)動(dòng)的調(diào)用。
3.強(qiáng)化可調(diào)試性與監(jiān)控能力
新增sysfs系統(tǒng)節(jié)點(diǎn)/sys/kernel/dma_heap/total_pools_kb,實(shí)時(shí)展示系統(tǒng)中所有DMA-Heap內(nèi)存池的總占用量,開發(fā)者可通過(guò)該節(jié)點(diǎn)快速定位內(nèi)存泄漏、資源浪費(fèi)等問(wèn)題,為Android設(shè)備與RK平臺(tái)的性能調(diào)優(yōu)提供關(guān)鍵依據(jù)。

// sysfs節(jié)點(diǎn)創(chuàng)建與實(shí)現(xiàn)(核心代碼片段)staticssize_ttotal_pools_kb_show(structkobject *kobj,structkobj_attribute *attr,char*buf){ unsignedlongtotal =0; structdma_heap*heap; mutex_lock(&dma_heap_lock); list_for_each_entry(heap, &dma_heaps, list) { // 累加所有內(nèi)存池的占用量(單位:KB) total +=dmabuf_page_pool_get_size(heap->pool) >>10; } mutex_unlock(&dma_heap_lock); returnsprintf(buf,"%lun", total);}// 定義sysfs屬性staticstructkobj_attributetotal_pools_kb_attr = __ATTR_RO(total_pools_kb);// 初始化sysfs節(jié)點(diǎn)intdma_heap_sysfs_init(void){ structkobject*dma_heap_kobj; dma_heap_kobj =kobject_create_and_add("dma_heap", kernel_kobj); if(!dma_heap_kobj) return-ENOMEM; returnsysfs_create_file(dma_heap_kobj, &total_pools_kb_attr.attr);}
代碼解析:①total_pools_kb_show函數(shù)遍歷所有DMA-Heap,通過(guò)頁(yè)池接口獲取每個(gè)堆的內(nèi)存占用量,累加后以KB為單位返回;②創(chuàng)建sysfs節(jié)點(diǎn)total_pools_kb,開發(fā)者可通過(guò)cat /sys/kernel/dma_heap/total_pools_kb查看實(shí)時(shí)內(nèi)存占用,快速定位內(nèi)存泄漏等問(wèn)題。
4.優(yōu)化初始化與錯(cuò)誤處理
重構(gòu)DMA-Heap的初始化流程,新增sysfs節(jié)點(diǎn)的獨(dú)立初始化與銷毀邏輯;完善資源分配失敗時(shí)的錯(cuò)誤回滾機(jī)制,確保任一環(huán)節(jié)失敗后均能干凈釋放已分配資源,避免內(nèi)存泄漏。
(四)RK平臺(tái)專屬適配,精準(zhǔn)匹配硬件架構(gòu)特性
針對(duì)RK平臺(tái)的硬件內(nèi)存布局與架構(gòu)特性,補(bǔ)丁對(duì)核心的CMA堆與系統(tǒng)堆進(jìn)行了定制化改造,同時(shí)調(diào)整編譯配置,適配不同資源規(guī)格的RK設(shè)備:
1. RK CMA堆優(yōu)化(rk_cma_heap.c)
?vmapvunmap重構(gòu)/邏輯,全面適配iosys_map接口規(guī)范,提升虛擬內(nèi)存映射的穩(wěn)定性與兼容性;
// RK CMA堆vmap邏輯重構(gòu)(核心代碼片段)staticvoid*rk_cma_heap_vmap(structdma_buf *dmabuf,structvm_area_struct *vma){ structrk_cma_heap_buf*buf =to_rk_cma_heap_buf(dmabuf); // 適配iosys_map接口規(guī)范,替換原有vmap邏輯 returniosys_map_vmap(&buf->iosys, vma->vm_pgoff << PAGE_SHIFT,? ? ? ? ? ? ? ? ? ? ? ? ? vma->vm_end - vma->vm_start);}staticvoidrk_cma_heap_vunmap(structdma_buf *dmabuf,void*vaddr){ structrk_cma_heap_buf*buf =to_rk_cma_heap_buf(dmabuf); // 對(duì)應(yīng)iosys_map的虛擬內(nèi)存釋放 iosys_map_vunmap(&buf->iosys, vaddr);}
代碼解析:將原有傳統(tǒng)vmap/vunmap邏輯,替換為iosys_map接口(嵌入式系統(tǒng)通用的內(nèi)存映射規(guī)范),適配RK平臺(tái)的硬件內(nèi)存映射機(jī)制,減少虛擬內(nèi)存映射異常,提升穩(wěn)定性。
?調(diào)整cma_alloc調(diào)用參數(shù),優(yōu)化連續(xù)內(nèi)存分配策略,精準(zhǔn)匹配RK平臺(tái)的CMA內(nèi)存布局;
// CMA內(nèi)存分配參數(shù)優(yōu)化(核心代碼片段)staticstructdma_buf*rk_cma_heap_alloc(structdma_heap *heap,size_tsize, unsignedintflags) { structrk_cma_heap*rk_heap =to_rk_cma_heap(heap); structpage*page; // 關(guān)鍵優(yōu)化:將原GFP_KERNEL改為false,適配RK平臺(tái)CMA內(nèi)存布局 page =cma_alloc(rk_heap->cma, size >> PAGE_SHIFT,0,false); if(!page) returnERR_PTR(-ENOMEM); // 后續(xù)內(nèi)存初始化邏輯... returndmabuf;}
代碼解析:調(diào)整cma_alloc的最后一個(gè)參數(shù)(從GFP_KERNEL改為false),優(yōu)化連續(xù)內(nèi)存分配策略,避免因內(nèi)存分配標(biāo)志位不匹配導(dǎo)致的CMA內(nèi)存分配失敗,精準(zhǔn)適配RK平臺(tái)的CMA內(nèi)存布局特點(diǎn)。
?新增模塊依賴聲明MODULE_IMPORT_NS(DMA_BUF),確保模塊加載時(shí)的依賴一致性,避免加載失敗。
// 新增模塊依賴聲明(核心代碼片段)MODULE_IMPORT_NS(DMA_BUF);// 導(dǎo)入DMA_BUF命名空間,確保依賴加載順序MODULE_LICENSE("GPL");MODULE_DESCRIPTION("RK CMA Heap for DMA-BUF");
代碼解析:通過(guò)MODULE_IMPORT_NS(DMA_BUF)聲明模塊依賴于DMA-BUF命名空間,確保內(nèi)核加載RK CMA堆模塊時(shí),DMA-BUF核心模塊已提前加載,避免因依賴順序錯(cuò)誤導(dǎo)致的模塊加載失敗。
2. RK系統(tǒng)堆升級(jí)(rk_system_heap.c)
?移除舊版延遲釋放邏輯,全面適配補(bǔ)丁新增的頁(yè)池管理機(jī)制,實(shí)現(xiàn)內(nèi)存頁(yè)的高效復(fù)用;
?kmap_local_pagekmap_atomic優(yōu)化內(nèi)存零填充實(shí)現(xiàn):用替代,減少內(nèi)核搶占沖突,提升多線程高頻內(nèi)存操作場(chǎng)景下的穩(wěn)定性;
// 內(nèi)存零填充優(yōu)化(核心代碼片段)staticvoidrk_system_heap_zero_page(structpage *page){ void*addr; // 用kmap_local_page替代kmap_atomic,減少內(nèi)核搶占沖突 addr =kmap_local_page(page); memset(addr,0, PAGE_SIZE);// 內(nèi)存零填充 kunmap_local(addr);// 對(duì)應(yīng)釋放映射}
代碼解析:kmap_atomic會(huì)禁止內(nèi)核搶占,在多線程高頻內(nèi)存操作場(chǎng)景下易導(dǎo)致阻塞;替換為kmap_local_page,允許內(nèi)核搶占,同時(shí)保證內(nèi)存操作的安全性,提升RK平臺(tái)設(shè)備在多任務(wù)場(chǎng)景下的穩(wěn)定性。
?重構(gòu)內(nèi)存池大小統(tǒng)計(jì)邏輯,通過(guò)頁(yè)池管理的原生接口實(shí)現(xiàn)內(nèi)存占用的精準(zhǔn)計(jì)算,提升監(jiān)控準(zhǔn)確性;
?完善vmap/vunmap接口的錯(cuò)誤處理,新增返回值與狀態(tài)清理邏輯,避免映射異常導(dǎo)致的內(nèi)存錯(cuò)誤。
3.編譯配置模塊化調(diào)整
?DMABUF_HEAPS_DEFERRED_FREEDMABUF_HEAPS_PAGE_POOLKconfig中新增與配置項(xiàng),支持兩大新組件的模塊化編譯,可根據(jù)設(shè)備資源規(guī)格靈活開啟/關(guān)閉,適配輕量與高性能的不同RK設(shè)備場(chǎng)景;
// Kconfig新增配置項(xiàng)(核心代碼片段)config DMABUF_HEAPS_DEFERRED_FREE bool"Deferred free helper for DMA-BUF heaps" dependsonDMABUF_HEAPS help Enable deferred free helperforDMA-BUF heaps, which supports asynchronous memory release to reduce fragmentation. (Recommendedforhigh-performance RK devices)config DMABUF_HEAPS_PAGE_POOL bool"Page pool support for DMA-BUF heaps" dependsonDMABUF_HEAPS help Enable page poolforDMA-BUF heaps, which pre-allocates memory pages to reduce allocation overhead. (RecommendedforAndroid devices)
代碼解析:新增兩個(gè)模塊化配置項(xiàng),開發(fā)者可根據(jù)RK設(shè)備的資源規(guī)格(如內(nèi)存大小、性能需求)靈活選擇是否開啟延遲釋放和頁(yè)池管理組件;輕量設(shè)備可關(guān)閉以節(jié)省資源,高性能設(shè)備開啟以提升內(nèi)存操作效率。
?Makefile中調(diào)整系統(tǒng)堆、CMA堆的編譯目標(biāo)命名,明確標(biāo)識(shí)為RK平臺(tái)專屬版本,方便編譯管理與平臺(tái)區(qū)分。
#Makefile調(diào)整(核心代碼片段)obj-$(CONFIG_DMABUF_HEAPS_RK_CMA) += rk_cma_heap.oobj-$(CONFIG_DMABUF_HEAPS_RK_SYSTEM) += rk_system_heap.o#原命名為cma_heap.o、system_heap.o,新增rk_前綴,明確平臺(tái)專
代碼解析:將編譯目標(biāo)命名從原有的cma_heap.o、system_heap.o改為rk_cma_heap.o、rk_system_heap.o,明確標(biāo)識(shí)為RK平臺(tái)專屬版本,避免與其他平臺(tái)的堆模塊命名沖突,方便編譯管理與版本區(qū)分。
(五)細(xì)節(jié)優(yōu)化,提升整體穩(wěn)定性與性能
除核心功能與架構(gòu)改動(dòng)外,補(bǔ)丁還在細(xì)節(jié)上進(jìn)行了多處優(yōu)化,覆蓋同步邏輯、內(nèi)存對(duì)齊、錯(cuò)誤處理等方面,進(jìn)一步提升模塊的穩(wěn)定性與性能:
1.sysfs統(tǒng)計(jì)異步化:將DMA-BUF統(tǒng)計(jì)節(jié)點(diǎn)的創(chuàng)建從同步執(zhí)行改為工作隊(duì)列異步執(zhí)行,避免阻塞內(nèi)存分配主線程,提升高頻內(nèi)存申請(qǐng)場(chǎng)景下的響應(yīng)速度;
// sysfs節(jié)點(diǎn)異步創(chuàng)建(核心代碼片段)staticvoiddma_buf_sysfs_init_work(struct work_struct *work) { dma_heap_sysfs_init();// 異步執(zhí)行sysfs節(jié)點(diǎn)初始化}// 初始化入口調(diào)整為異步intdma_buf_init(void) { INIT_WORK(&dma_buf_sysfs_work, dma_buf_sysfs_init_work); schedule_work(&dma_buf_sysfs_work);// 提交工作隊(duì)列,異步執(zhí)行 return0;}
代碼解析:將sysfs節(jié)點(diǎn)初始化邏輯放入工作隊(duì)列,異步執(zhí)行,避免同步初始化時(shí)阻塞DMA-BUF核心初始化流程,尤其在高頻內(nèi)存申請(qǐng)場(chǎng)景下,可提升系統(tǒng)響應(yīng)速度。
2.強(qiáng)制頁(yè)面對(duì)齊:所有DMA-Heap的內(nèi)存分配均通過(guò)PAGE_ALIGN確保按頁(yè)對(duì)齊,避免因內(nèi)存對(duì)齊問(wèn)題導(dǎo)致的硬件設(shè)備訪問(wèn)異常,適配RK平臺(tái)的硬件訪問(wèn)規(guī)范;
3.完善錯(cuò)誤回滾:重構(gòu)dma_buf_export的錯(cuò)誤處理邏輯,新增err_sysfs分支,確保sysfs節(jié)點(diǎn)創(chuàng)建失敗時(shí)能完整回滾已分配的文件、內(nèi)存等資源;
4.保障緩存一致性:在局部CPU訪問(wèn)接口中增加?xùn)艡诘却壿嫞_保CPU與DMA設(shè)備的內(nèi)存視圖一致,避免數(shù)據(jù)不一致導(dǎo)致的程序異常;
5.精準(zhǔn)參數(shù)校驗(yàn):在內(nèi)存分配接口中增加對(duì)fd_flags與heap_flags的參數(shù)校驗(yàn),拒絕非法參數(shù),提升接口的健壯性。
三、應(yīng)用價(jià)值:三大維度賦能嵌入式生態(tài)
本次DMA-BUF補(bǔ)丁的改造,不僅實(shí)現(xiàn)了Android生態(tài)與RK平臺(tái)的雙向適配,更對(duì)嵌入式Linux的內(nèi)存管理生態(tài)提供了可復(fù)用的優(yōu)化方案,其應(yīng)用價(jià)值覆蓋生態(tài)兼容、平臺(tái)性能、內(nèi)核技術(shù)三大維度:
1.對(duì)Android生態(tài):補(bǔ)全RK平臺(tái)的兼容性短板
補(bǔ)丁完美匹配Android系統(tǒng)對(duì)DMA-BUF的功能與接口要求,解決了RK平臺(tái)在Android生態(tài)下,圖形渲染、視頻編解碼、相機(jī)等核心多媒體模塊的內(nèi)存共享兼容性問(wèn)題,為RK平臺(tái)設(shè)備運(yùn)行高版本Android系統(tǒng)提供了關(guān)鍵的底層支撐。
2.對(duì)RK平臺(tái):提升嵌入式設(shè)備核心競(jìng)爭(zhēng)力
通過(guò)頁(yè)池復(fù)用、延遲釋放、局部?jī)?nèi)存同步等優(yōu)化,RK平臺(tái)設(shè)備的內(nèi)存分配延遲、碎片率大幅降低,在機(jī)頂盒、工業(yè)平板、智能座艙、物聯(lián)網(wǎng)終端等嵌入式場(chǎng)景中,可顯著提升設(shè)備在高頻多媒體操作、多任務(wù)運(yùn)行時(shí)的流暢度與穩(wěn)定性,強(qiáng)化平臺(tái)的市場(chǎng)競(jìng)爭(zhēng)力。
3.對(duì)Linux內(nèi)核生態(tài):完善DMA-BUF技術(shù)方案
補(bǔ)丁新增的延遲釋放、頁(yè)池管理組件采用通用化設(shè)計(jì),不依賴特定硬件平臺(tái),可為其他嵌入式平臺(tái)的DMA-BUF優(yōu)化提供參考;而DMA-Heap的架構(gòu)升級(jí)與接口擴(kuò)展,也為L(zhǎng)inux內(nèi)核的內(nèi)存管理機(jī)制提供了更完善、更高效的實(shí)現(xiàn)方案,推動(dòng)DMA-BUF生態(tài)的進(jìn)一步發(fā)展。
四、總結(jié)
本次針對(duì)DMA-BUF的補(bǔ)丁改造,并非簡(jiǎn)單的功能疊加,而是一次從底層基礎(chǔ)組件、核心對(duì)外接口、DMA-Heap架構(gòu)設(shè)計(jì)到RK平臺(tái)硬件適配的全鏈路升級(jí)。其設(shè)計(jì)思路圍繞“生態(tài)適配”與“高性能”兩大核心,既精準(zhǔn)命中了Android系統(tǒng)對(duì)內(nèi)存管理的精細(xì)化要求,又深度挖掘了RK平臺(tái)的硬件潛力,同時(shí)通過(guò)通用化的組件設(shè)計(jì)為L(zhǎng)inux內(nèi)核生態(tài)貢獻(xiàn)了可復(fù)用的技術(shù)方案。
在嵌入式設(shè)備對(duì)多媒體性能、多任務(wù)處理能力要求不斷提升的背景下,這套適配Android與RK特性的DMA-BUF內(nèi)存管理方案,將成為RK平臺(tái)嵌入式設(shè)備的核心技術(shù)支撐之一。同時(shí),其底層的內(nèi)存優(yōu)化思路,也為其他嵌入式平臺(tái)的內(nèi)存管理調(diào)優(yōu)提供了極具價(jià)值的實(shí)踐參考,對(duì)推動(dòng)嵌入式Linux與Android生態(tài)的技術(shù)發(fā)展具有積極意義。
審核編輯 黃宇
-
Android
+關(guān)注
關(guān)注
12文章
4031瀏覽量
134137 -
patch
+關(guān)注
關(guān)注
0文章
15瀏覽量
8555
發(fā)布評(píng)論請(qǐng)先 登錄
ADP5033:高性能電源管理芯片的深度解析
ADP5034:高性能電源管理芯片的深度解析
深度解析ADP5051:高性能集成電源解決方案
BUF12840:可編程伽馬電壓發(fā)生器的深度解析
RK平臺(tái)Android設(shè)備OTA升級(jí)教程:從原理到U盤實(shí)操
高性能電源利器:LTC7050 - 1深度解析
硬核進(jìn)階:RK3576 Android15?驅(qū)動(dòng)與系統(tǒng)開發(fā)實(shí)戰(zhàn)指南
深度解析?| DMA-BUF適配Android與RK特性核心Patch:高性能內(nèi)存管理升級(jí)方案
評(píng)論