内存管理-80-dma-buf-1-调试-1-文件节点
基于 Linux-6.1
一、文件节点
1. /sys/kernel/dmabuf/buffers
dma-buf-sysfs-stats.c 中有注释: 当启用 CONFIG_DMABUF_SYSFS_STATS 后,/sys/kernel/dma-buf/buffers 接口会暴露出所有 DMA-BUF 的信息。该接口暴露了以下统计项:
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
/sys/kernel/dmabuf/buffers/<inode_number>/size
该接口中的信息还可用于推导按每个导出者(exporter)划分的统计数据。可以在发生错误或其他重要事件时收集该接口的数据,以提供 DMA-BUF 使用情况的快照。也可以通过遥测(telemetry)定期收集,以监控各项指标。
有关该接口的详细文档,见 Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers。
1.1 exporter_name
TODO
1.2 size
TODO
1.3 工具脚本-按size降序
#!/system/bin/sh # dmabuf_top.sh - list /sys/kernel/dmabuf/buffers entries sorted by size desc # # Usage (on device): # sh /data/local/tmp/dmabuf_top.sh [DIR] [EXPORTER_SUBSTR] # Defaults: # DIR = /sys/kernel/dmabuf/buffers # EXPORTER_SUBSTR = (empty, no filter) # # Note: directory name is the dma-buf file's inode number, not a pid. size attribute is bytes (kernel: dma_buf->size). DIR=${1:-/sys/kernel/dmabuf/buffers} PAT=${2:-} if [ ! -d "$DIR" ]; then echo "no such dir: $DIR" >&2 exit 1 fi for d in "$DIR"/*; do [ -d "$d" ] || continue size=$(cat "$d/size" 2>/dev/null) || continue exp=$(cat "$d/exporter_name" 2>/dev/null) [ -n "$size" ] || continue printf '%s %s %s\n' "$size" "${exp:-<unknown>}" "${d##*/}" done | sort -rn | awk -v pat="$PAT" ' pat != "" && index($2, pat) == 0 { next } { printf "%14s B %9.2f MiB %-18s ino=%s\n", $1, $1 / 1048576, $2, $3 tot += $1 n++ } END { printf "----\n%d buffers, total %.2f MiB (%.0f B)\n", n, tot / 1048576, tot } '
(1) 用法
sh dmabuf_top.sh # 全部 sh dmabuf_top.sh /sys/kernel/dmabuf/buffers qcom_hgsl # 只看 HGSL,参数大小写敏感 sh dmabuf_top.sh /sys/kernel/dmabuf/buffers qcom # 所有 qcom 系列
(2) dump出来内容如:
/data/local/tmp # ./dmabuf_top.sh 75235328 B 71.75 MiB qcom_hgsl ino=2110 26542080 B 25.31 MiB qcom,system ino=45 516096 B 0.49 MiB qcom,qseecom ino=33 131072 B 0.12 MiB qcom,system-uncached ino=35 ... 4096 B 0.00 MiB msm_hab ino=118 ---- 1379 buffers, total 3311.08 MiB (3471921152 B)
1.4 工具脚本-对应到pid
自带的 dmabuf_dump 工具更好用。
(1) 脚本代码
#!/system/bin/sh # dmabuf_ino_pids.sh - map /sys/kernel/dmabuf/buffers/<ino> to the pids that mmap it # # Usage: # sh dmabuf_ino_pids.sh [BUFFERS_DIR] [EXPORTER_SUBSTR] # Defaults: # BUFFERS_DIR = /sys/kernel/dmabuf/buffers # EXPORTER_SUBSTR = (empty, no filter) # Env: # PROCFS=/proc (for local testing) # TMPDIR=/data/local/tmp (needs a writable dir) # # The sysfs dir name is the dma-buf file's inode number (dmabuf specific, # globally unique per boot: drivers/dma-buf/dma-buf.c dma_buf_getfile()). # A process that mmaps the buffer has the same inode in /proc/<pid>/maps, # with the pathname starting with "/dmabuf". DIR=${1:-/sys/kernel/dmabuf/buffers} PAT=${2:-} PROC=${PROCFS:-/proc} TMP=${TMPDIR:-/data/local/tmp} INO=$TMP/.dmabuf_ino.$$ PSL=$TMP/.dmabuf_ps.$$ for d in "$DIR"/*; do [ -d "$d" ] || continue printf '%s %s %s\n' "${d##*/}" "$(cat "$d/size" 2>/dev/null)" \ "$(cat "$d/exporter_name" 2>/dev/null)" done > "$INO" ps -A -o PID,NAME > "$PSL" 2>/dev/null awk -v pat="$PAT" ' function hx(h, i, c, v) { v = 0 for (i = 1; i <= length(h); i++) { c = tolower(substr(h, i, 1)) v = v * 16 + index("0123456789abcdef", c) - 1 } return v } FILENAME == ARGV[1] { sz[$1] = $2; ex[$1] = $3; next } FILENAME == ARGV[2] { comm[$1] = $2; next } $6 ~ /^\/dmabuf/ && ($5 in sz) { if (pat != "" && index(ex[$5], pat) == 0) next n = split(FILENAME, p, "/") pid = p[n - 1] r = $1 i = index(r, "-") kb = (hx(substr(r, i + 1)) - hx(substr(r, 1, i - 1))) / 1024 k = $5 SUBSEP pid if (!(k in mkb)) pk[$5] = pk[$5] " " k mkb[k] += kb nmap[k]++ } END { cnt = 0 for (d in sz) if (pat == "" || index(ex[d], pat)) ord[++cnt] = d for (i = 2; i <= cnt; i++) { v = ord[i]; j = i - 1 while (j >= 1 && sz[ord[j]] + 0 < sz[v] + 0) { ord[j + 1] = ord[j]; j-- } ord[j + 1] = v } print "== mapped (ino -> pids) ==" for (i = 1; i <= cnt; i++) { d = ord[i] if (!(d in pk)) continue printf "ino=%-8s %10.2f MiB %-14s\n", d, sz[d] / 1048576, ex[d] n = split(pk[d], ks, " ") for (j = 1; j <= n; j++) { split(ks[j], a, SUBSEP) printf " pid=%-6s %-18s %d VMA %.2f MiB\n", a[2], (a[2] in comm ? comm[a[2]] : "?"), nmap[ks[j]], mkb[ks[j]] / 1024 } } print "== no mapping found (fd-only, or already freed) ==" for (i = 1; i <= cnt; i++) { d = ord[i] if (d in pk) continue printf "ino=%-8s %10.2f MiB %-14s\n", d, sz[d] / 1048576, ex[d] } } ' "$INO" "$PSL" "$PROC"/[0-9]*/maps 2>/dev/null rm -f "$INO" "$PSL"
(2) 执行结果
/data/local/tmp # sh dmabuf_ino_pids.sh == mapped (ino -> pids) == ino=2110 71.75 MiB qcom_hgsl pid=3837 com.sam.Unity 1 VMA 71.75 MiB ... ino=2204 0.03 MiB qcom,system //共享的 pid=1034 vendor.display.composer-service 1 VMA 0.03 MiB pid=1085 surfaceflinger 1 VMA 0.03 MiB pid=3511 com.sam.island 1 VMA 0.03 MiB ... == no mapping found (fd-only, or already freed) == ino=36 25.31 MiB qcom,system
2. /sys/kernel/debug/dma_buf/bufinfo
提供了系统中所有 DMA-BUF 的概览。但是,由于在生产环境中挂载 debugfs 并不安全,因此可以使用 procfs 和 sysfs 来在生产系统上收集 DMA-BUF 的统计信息。
/sys/kernel/debug/dma_buf # cat bufinfo Dma-buf Objects: size flags mode count exp_name ino name 00028672 00000002 00080007 00000003 qcom,system 00002528 qcom,system Attached Devices: Total 0 devices attached 00491520 00000002 00080007 00000004 qcom,system 00002527 qcom,system Attached Devices: hab-ogles Total 1 devices attached 00028672 00000002 00080007 00000003 qcom,system 00002526 qcom,system Attached Devices: ... ... 00032768 00000002 00080007 00000001 msm_hab 00000001 <none> Attached Devices: Total 0 devices attached
3. /sys/kernel/debug/dma_pools
/sys/kernel/debug/dma_pools # ls -l -r-------- 1 root root 0 1970-01-01 01:00 pool_size_dma //cat 0 -r-------- 1 root root 0 1970-01-01 01:00 pool_size_dma32 //cat 2097152 -r-------- 1 root root 0 1970-01-01 01:00 pool_size_kernel //cat 2097152
4. /sys/kernel/debug/dmaengine/summary
/sys/kernel/debug/dmaengine # ls -l -r--r--r-- 1 root root 0 1970-01-01 01:00 summary
只读,cat出来是空。
5. /proc/<pid>/maps
包含已 mmap 的 dma_buf 信息:/proc/<pid>/maps 第 5 列就是 inode,第 6 列路径以 /dmabuf 开头(dma-buf.c:166-180);dumpsys 的 DMA-BUF mapped 正是扫这里(android_os_Debug.cpp:745-773)。
6. /proc/<pid>/fdinfo/<fd>
这里面有 size/count/exp_name(dma-buf.c:1188-1200),如:
# for F in `ls`; do echo --------F=$F---------; cat $F; done ... --------F=411--------- pos: 0 flags: 02000002 mnt_id: 8 ino: 2332 size: 28672 count: 9 exp_name: qcom,system name: qcom,system ...
6.1 工具脚本
反查某进程持有的 dma-buf fd,打印 ino / 大小 / exporter / fd / refs。
(1) 脚本内容
PID=${1:?usage: $0 PID}
P=${PROCFS:-/proc}/$PID
if [ ! -d "$P" ]; then
echo "no such pid: $PID" >&2
exit 1
fi
seen=" "
total=0
nbuf=0
nfds=0
for f in "$P"/fd/*; do
fd=${f##*/}
info="$P/fdinfo/$fd"
[ -r "$info" ] || continue
exp=$(sed -n 's/^exp_name:[[:space:]]*//p' "$info" 2>/dev/null)
[ -n "$exp" ] || continue
size=$(sed -n 's/^size:[[:space:]]*//p' "$info" 2>/dev/null)
refs=$(sed -n 's/^count:[[:space:]]*//p' "$info" 2>/dev/null)
ino=$(stat -L -c '%i' "$f" 2>/dev/null)
size=${size:-0}
key=${ino:-fd:$fd}
mb=$(( size / 1048576 ))
frac=$(( size % 1048576 * 100 / 1048576 ))
printf 'ino=%-8s %d.%02d MiB %-14s fd=%-4s refs=%-4s %s\n' \
"${ino:-?}" "$mb" "$frac" "$exp" "$fd" "${refs:-?}" "$(readlink "$f")"
case "$seen" in
*" $key "*) ;;
*) seen="$seen$key "
total=$(( total + size ))
nbuf=$(( nbuf + 1 )) ;;
esac
nfds=$(( nfds + 1 ))
done
echo "----"
tmb=$(( total / 1048576 ))
tfrac=$(( total % 1048576 * 100 / 1048576 ))
printf 'pid=%s: %d bufs / %d fds, total %d.%02d MiB (%s B)\n' "$PID" "$nbuf" "$nfds" "$tmb" "$tfrac" "$total"
(2) 执行结果
/data/local/tmp # sh dmabuf_pid_fds.sh 2645 ino=1603 0.17 MiB qcom,system fd=226 refs=2 /dmabuf:qcom,system ino=1604 0.02 MiB qcom,system fd=227 refs=3 /dmabuf:qcom,system ino=1605 0.17 MiB qcom,system fd=228 refs=2 /dmabuf:qcom,system ino=1606 0.02 MiB qcom,system fd=229 refs=3 /dmabuf:qcom,system ino=1603 0.17 MiB qcom,system fd=230 refs=2 /dmabuf:qcom,system ino=1604 0.02 MiB qcom,system fd=231 refs=3 /dmabuf:qcom,system ino=1607 0.17 MiB qcom,system fd=233 refs=2 /dmabuf:qcom,system ino=1608 0.02 MiB qcom,system fd=234 refs=3 /dmabuf:qcom,system ino=1605 0.17 MiB qcom,system fd=236 refs=2 /dmabuf:qcom,system ino=1606 0.02 MiB qcom,system fd=237 refs=3 /dmabuf:qcom,system ino=1607 0.17 MiB qcom,system fd=241 refs=2 /dmabuf:qcom,system ino=1608 0.02 MiB qcom,system fd=242 refs=3 /dmabuf:qcom,system ---- pid=2645: 6 bufs / 12 fds, total 0.62 MiB (651264 B)
posted on 2026-10-28 15:07 Hello-World3 阅读(2) 评论(0) 收藏 举报
浙公网安备 33010602011771号