本文是极客笔记出品,基于Android 13源码分析dmabuf_dump工具如何工作的。
DmaBuffer
DmaBuffer结构体定义如下:
主要成员变量
-
name_ : 该dmabuf的name,如果读不到name,默认为 ‘<unknown>’
-
pids_: 有dup或map该dmabuf的pid 集合。
-
count_: fdinfo里面的count,目前看dambuf_dump并没有用。
-
size_: 该dmabuf占用的内存大小,单位是byte。
-
inode_: 该dmabuf的inode。
-
exporter_: 申请该dmabuf的name,如果读不到name,默认为'<unknown>’。
-
total_refs_: fdrefs 个数 + maprefs 个数,目前看dambuf_dump并没有用。
-
fdrefs_: 有open或dup该dmabuf的pid集合。注:一个pid对同一个dmabuf(inode)可能有多个reference。
-
maprefs_: 有map该dmabuf的pid集合。注:一个pid对同一个dmabuf(inode)可能有多个reference。
参考FD和Inode的关系:
dmabuf_dump
直接执行dmabuf_dump会dump 整个系统的dmabuf 信息,代码执行流程如下:
ReadDmaBufFdRefs
读取 /proc/<pid>/fdinfo/ 下面的所有fd,针对每个fd读取如下信息
- count
- exp_name,有exp_name则表示是 dmabuf 的file。
- name
- size
- ino:inode
如果是dmabuf file,但没有读到inode,则:
读取 /proc/<pid>/fdinfo/fd的stat,从里面去读取size和inode
struct stat sb;
if (stat(fd_path.c_str(), &sb) < 0) {
if (errno == ENOENT) {
continue;
}
PLOG(ERROR) << "Failed to stat: " << fd_path;
return false;
}
inode = sb.st_ino;
// If root, calculate size from the allocated blocks.
size = sb.st_blocks * 512;
最后,调用DmaBuffer的AddFdRef,添加到fdrefs_ map里面去。
ReadDmaBufMapRefs
读取/proc/<pid>/maps下面的信息,只处理name以 /dmabuf 开头的map(也就是dmabuf的map)。
注:如果从maps里面读到的inode不在fdrefs_ 里面,则会尝试到 /sys/kernel/dmabuf/buffers 里面去读该dmabuf的size,name,exp_name。 理论上不可能?
然后调用DmaBuffer的AddMapRef,添加到maprefs_ map里面去。
dmabuf_dump <pid>
流程跟dump 整個系统的dmabuf info类似,只是这里只dump指定pid的dmabuf info。
dmabuf_dump -a
以Table[buffer x process]方式呈现dmabuf info。
跟dmabuf_dump相比,只是打印DmaBuffer的方式不一样。
dmabuf_dump -b
Dmabuf Sysfs Stats统计,有三个相关类:
类 | 定义 | 作用 |
---|---|---|
DmabufSysfsStats | Dmabuf sysfs 统计信息每一块Dmabuf信息exporter信息总Dmabuf信息 | |
DmabufInfo | 统计一块Dmabuf 信息,包括inode、exporter name、size | |
DmabufTotal | 统计整个系统的Dmabuf信息,包括buffer总数、buffer总大小 |
代码流程: