RK3588 Android12 DMABUF内存泄漏问题分析
RK3588 Android12 DMABUF内存泄漏问题分析
什么是DMABUF
DMABUF是多媒体设备之间共享内存的一种特定buffer结构,不同设备可以通过DMABUF的fd进行跨进程共享内存,实现零拷贝提高性能,支持异步访问降低模块耦合度。
问题描述
RK3588机器在线视频播放长时间拷机出现系统重启,log里面可以看到dma-buf内存分配失败,最后导致系统重启。
[05-15 04:55:46][64021.496139][ T6554] rk_vcodec: mpp_task_attach_fd:1696: can't import dma-buf 1
[05-15 04:55:46][64021.496144][ T6554] iep2_process_reg_fd:270: reg[044]: 00000401 failed
[05-15 04:55:46][64021.496149][ T6554] rk_vcodec: mpp_process_task_default:602: alloc_task failed.
[05-15 04:55:46][64021.496155][ T6554] rk_vcodec: mpp_wait_result_default:842: session 6553:531 pending list is empty!
[05-15 04:55:46][64021.496160][ T6554] rk_vcodec: mpp_msgs_wait:1549: session 531 wait result ret -5
[05-15 04:55:46][64021.499857][ T6554] mpp_dma_import_fd:198: dma_buf_get fd 16 failed(-22)
[05-15 04:55:46][64021.499870][ T6554] rk_vcodec: mpp_task_attach_fd:1696: can't import dma-buf 16
[05-15 04:55:46][64021.499876][ T6554] iep2_process_reg_fd:270: reg[044]: 00000410 failed
[05-15 04:55:46][64021.499881][ T6554] rk_vcodec: mpp_process_task_default:602: alloc_task failed.
[05-15 04:55:46][64021.499888][ T6554] rk_vcodec: mpp_wait_result_default:842: session 6553:531 pending list is empty!
[05-15 04:55:46][64021.499893][ T6554] rk_vcodec: mpp_msgs_wait:1549: session 531 wait result ret -5
结合log及现象看比较大可能是内存泄漏导致,于是按如下方法来确认并定位是哪里泄漏。
问题分析
/proc/rk_dmabuf/dev 这个节点里面会记录当前的dma的使用信息:
130|rk3588_s_evb7:/ # cat /proc/rk_dmabuf/dev
DMABUF NAME EXPORT SIZE:KiB AttachedDevices
ffffff8022507400 402-allocator@4. system-uncached 2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff8143313a00 402-allocator@4. system-uncached 2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff819883e200 474-c2@1.1-servi rockchipdrm 56 KiB fdc38100.rkvdec-core
ffffff819daddc00 402-allocator@4. system-uncached 2628 KiB display-subsystem fb000000.gpu
ffffff80364ec200 402-allocator@4. system-uncached 2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff819dac0400 402-allocator@4. system-uncached 2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff81032a1400 402-allocator@4. system-uncached 2628 KiB display-subsystem fb000000.gpu
ffffff8102c5a400 402-allocator@4. system-uncached 1260 KiB fdbb0000.iep fdc38100.rkvdec-core fb000000.gpu display-subsystem
ffffff8102c59800 402-allocator@4. system-uncached 1260 KiB fdbb0000.iep fb000000.gpu fdc38100.rkvdec-core display-subsystem
ffffff81049b9000 402-allocator@4. system-uncached 1260 KiB fdbb0000.iep fdc38100.rkvdec-core fb000000.gpu display-subsystem
ffffff800f84de00 402-allocator@4. system-uncached 1260 KiB fdc38100.rkvdec-core fb000000.gpu display-subsystem
ffffff800f84c400 402-allocator@4. system-uncached 1260 KiB fb000000.gpu fdc38100.rkvdec-core display-subsystem
每个1个小时(根据实际泄漏的速度可以适当增加减小)敲一下如下命令,保存当前dma-buf的信息
cat /proc/rk_dmabuf/dev > sdcard/time1.txt
一小时后
cat /proc/rk_dmabuf/dev > sdcard/time2.txt
然后使用比较工具对比看两个文件的差异,看是否有多出的dma-buf信息
对比发现ffffff81c260aa00 359-allocator@4. system-uncached 1740 KiB display-subsystem 这个一直在增加,通过 /sys/kernel/debug/dma_buf/bufinfo 输出的 dmabuf 的 inode 信息, 可以检索到哪些进程持有该 dmbuf 的 fd:
rk3588_s_evb7:/ # cat /sys/kernel/debug/dma_buf/bufinfo
Dma-buf Objects:
size flags mode count exp_name ino
01781760 00000002 00080007 00000004 system-uncached 00520340 359-allocator@4.0-s
Attached Devices:
display-subsystem
Total 1 devices attached
01781760 00000002 00080007 00000004 system-uncached 00520339 359-allocator@4.0-s
Attached Devices:
display-subsystem
Total 1 devices attached
01781760 00000002 00080007 00000004 system-uncached 00143207 359-allocator@4.0-s
Attached Devices:
display-subsystem
Total 1 devices attached
01290240 00000002 00080007 00000004 system-uncached 00177498 359-allocator@4.0-s
Attached Devices:
display-subsystem
Total 1 devices attached
上面是 cat /sys/kernel/debug/dma_buf/bufinfo 的输出, 520339是某个 dmabuf 的 inode 的 i_ino 成员, 下面是在 lsof 的输出中检索到的该 iino , 即对应的进程以 fd 持有对对应 dmabuf 的引用. 一个 dmabuf 可能被多个 进程 这样引用:
rk3588s_s:/ # lsof | grep 520339
c2@1.1-service 426 mediacodec 235u 0000 0,8 0t0 520339 /dmabuf:359-allocator@4.0-s
rk3588s_s:/ #
rk3588s_s:/ #
rk3588s_s:/ # lsof | grep 143207
c2@1.1-service 426 mediacodec 117u 0000 0,8 0t0 143207 /dmabuf:359-allocator@4.0-s
rk3588s_s:/ #
rk3588s_s:/ # lsof | grep 177498
c2@1.1-service 426 mediacodec 89u 0000 0,8 0t0 177498 /dmabuf:359-allocator@4.0-s
通过上面命令可以看到这个dma-buf的持有者是进程号:426的mediacodec进程,通过ls /proc/426/fd 可以看到有多个dma-buf的fd没有释放,这样就可以确认是mediacodec内有dma-buf没有释放,存在泄漏的问题,再找对应的模块负责人进行具体分析定位。