骁龙芯片Android平台NDK开发如何使用DMA-BUF实现跨设备共享内存
NDK 接入 DMA-Buf Heap 实现跨 CPU/GPU/DSP 共享内存操作步骤
DMA-Buf Heap 从 Android 12(API 31)开始提供稳定 NDK 接口,低版本系统需做兼容回退。已下载 AOSP 源码的前提下,按以下步骤操作即可完成接入:
提取依赖文件
- 头文件:从 AOSP 源码
system/memory/libdmabufheap/include/路径下找到dmabufheap.h,复制到 NDK 项目的自定义头文件目录(比如app/src/main/cpp/include/)。如果要适配 API 31 以下版本,同步提取system/memory/libdmabufheap/include/uapi/linux/dma-heap.h内核头文件放到同目录下的uapi子目录。 - 库文件:两种方案二选一
- 动态库方案:根据目标ABI(arm64-v8a、armeabi-v7a、x86_64等),从AOSP编译产物
out/target/product/<对应目标设备>/system/lib64/、system/lib/路径下取出libdmabufheap.so,放到项目对应ABI的jniLibs目录。注意不同厂商系统的libdmabufheap可能存在定制差异,兼容性一般。 - 源码集成方案:直接把AOSP中
system/memory/libdmabufheap/下的所有源码文件(dmabufheap.c、dma_heap.c等)复制到项目的cpp源码目录参与编译,不需要依赖系统库,兼容性最好,优先推荐这种方式。
- 动态库方案:根据目标ABI(arm64-v8a、armeabi-v7a、x86_64等),从AOSP编译产物
配置编译规则
CMake 构建配置
如果用源码集成,直接把拷贝过来的libdmabufheap源文件加到target的源文件列表,再添加头文件搜索路径即可:
# 添加头文件搜索路径 include_directories(${CMAKE_SOURCE_DIR}/include) add_library(your-native-lib SHARED your-native-code.cpp # 拷过来的libdmabufheap源码 dmabufheap/dmabufheap.c dmabufheap/dma_heap.c ) # 链接依赖,dma-buf操作本身只需要基础libc,不需要额外系统库 target_link_libraries(your-native-lib log android)
如果用预编译动态库方案,添加IMPORTED库配置即可:
add_library(dmabufheap SHARED IMPORTED) set_target_properties(dmabufheap PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libdmabufheap.so) target_link_libraries(your-native-lib dmabufheap log android)
ndk-build 构建配置
源码集成方案在Android.mk中添加以下配置:
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include LOCAL_SRC_FILES += dmabufheap/dmabufheap.c dmabufheap/dma_heap.c LOCAL_LDLIBS += -llog -landroid
动态库方案额外添加链接路径即可:
LOCAL_LDFLAGS += -L$(LOCAL_PATH)/jniLibs/$(TARGET_ARCH_ABI) -ldmabufheap
功能验证与适配注意事项
- 编译验证:在原生代码中添加
#include "dmabufheap.h",执行编译如果没有头文件找不到、链接符号缺失的报错,说明配置正常。 - 基础功能测试:调用
DmabufHeapAlloc()接口分配内存,优先选择system或system-uncached类型的heap(这类heap分配的内存支持CPU/GPU/DSP全硬件单元访问,不要选gpu、vpu这类设备专属heap),拿到dma-buf fd后先做CPU侧mmap读写测试,确认内存分配正常。 - 跨设备共享要点:
- 跨进程/跨硬件模块传递dma-buf时,必须用
dup()复制fd后再传递,不能直接传递原始fd值 - 跨单元访问必须处理缓存一致性:CPU写完数据要给GPU/DSP读取前,执行缓存flush操作;GPU/DSP写完数据要给CPU读取前,执行缓存invalidate操作,避免读到脏数据
- 部分旧设备的DSP/GPU驱动不支持直接导入dma-buf fd,API 30及以下版本需要回退到ION接口分配共享内存,接口逻辑和DMA-Buf Heap基本一致,同样返回可跨设备共享的fd。
- 跨进程/跨硬件模块传递dma-buf时,必须用
常见问题处理
- 运行时提示找不到
libdmabufheap.so:直接改用源码集成方案,把libdmabufheap编译进自己的原生库即可,不需要依赖系统动态库。 - 分配内存返回失败:先检查当前应用是否有内存分配权限,部分设备对system heap的分配大小有限制,大内存分配可以尝试用
system-uncachedheap。 - GPU/DSP无法访问分配的内存:确认分配的heap类型不是设备专属heap,同时检查对应硬件驱动的导入接口是否要求特定的内存对齐参数,按要求调整分配时的对齐配置即可。
内容的提问来源于stack exchange,提问作者Mohammad Hassan Sadeghein
相关产品推荐
相关产品推荐

