linux打印调用栈 函数名_[R] 如何用树展示linux C函数调用栈 - collapsibleTree

3d193cf7ec3274e919f2cf4c96c26300.png

效果如下:

c1fe297cfbb7d5b8286260aada425ea9.png
linux C语言函数栈https://www.zhihu.com/video/1092149894495731712

此例展示的是linux最常用的系统调用 - open()的函数调用树

-----

推荐 linux C函数流程图 以及linux文件树

老白Walt:[R+bash] 5分钟内制作一张linux C函数流程图 - DiagrammeR

老白Walt:[R] 展示linux文件树 - collapsibleTree


1 获取数据

1.1 函数调用栈

cflow - 一款生成函数调用栈的命令行工具

举个例子:

dfac933af839fe808b8f29836acd2e1c.png
cflow

用法就是这样子:

cflow -m 函数名 文件名

直接输出调用栈,以缩进表示stack depth,赞!不过如果我将include/, block/, mm/目录的文件都加进来的话,这个stack会非常非常长,在shell下看会崩溃,因此这里要发挥R语言的优势

不过在进入R之前还有一个问题: 这个数据格式R语言可没有东东认得!经过一番搜寻发现一条可行的数据转换的path:

[shell] cflow -> grep/perl/sed -> .yaml -> [R] -> yaml::yaml.load_file -> data.tree::as.Node

最终可以转换为Node格式,就可以优雅地用collapsibleTree来展示了

而连接shell和R的东东就是YAML

注:cflow是有BUG的,并不是总能很好的解析函数,所以不能过度依赖

1.2 YAML

下面就是YAML的一种格式

a_nested_map:
    key: value
    another_key: Another Value
    another_nested_map:
        hello: hello

key: value而value也可以是多个key: value对

cflow的输出正好有缩进,我只需要把key: value给转换好即可

1.3 cflow -> YAML

find fs/*.* fs/notify include/linux/ -name '*.[ch]' | grep -Pv 'w*(?:pr_|print|trace|lock)' | xargs cflow -m vfs_open 2> /dev/null | sed -r '/^s*(pr_[^(]+|printk|ssize_t|loff_t)()/d' | perl -pe 's/^(s*)([^(]+)()(?:$|s+<.* at ([^>]+)>.*$)/12:n1    file: 3/' > open.yaml
find fs/*.* fs/sysfs fs/notify include/linux/ -name '*.[ch]' | grep -Pv 'w*(?:pr_|print|trace|lock)'

用find找fs和include下的.c和.h,再用grep过滤掉一些debug的文件

open()函数定义在fs/open.c:

f42f7d105679f26f306449caf4d3009f.png

不过因其定义是宏展开的,cflow还没有强大到可以捕获,因此这里跳到vfs_open()代替;另外静态工具对函数指针无计可施,因此调用栈还无法深入到具体的文件系统

xargs cflow -m vfs_open 2> /dev/null

用cflow -m vfs_open生成调用栈

628483f5a827cbc20b2814db00a66b6f.png
perl -pe 's/^(s*)([^(]+)()(?:$|s+<.* at ([^>]+)>.*$)/12:n1 file: 3/' > open.yaml

最后用perl将文本转换为YAML格式:

994bf432e483c0546e4ba413dbfa23c9.png

至此,shell处理部分结束

2 R数据处理

2.1 加载YAML

344e1fb9844022c4d3e5d5bb671542a5.png
yaml::yaml.load_file('d:/linux-master/open.yaml')

yaml包的yaml.load_file会将文件转为list

2.2 YAML -> data.tree::Node

637faa8ff24db501cbbccac82ec64ac8.png
data.tree::as.Node(ylst)

data.tree包的as.Node方法会将其转为Node class,它的功能是十分丰富的,有兴趣的可以移步到下面链接:

https://cran.r-project.org/web/packages/data.tree/vignettes/data.tree.html​cran.r-project.org

3 绘图

yaml::yaml.load_file('d:/linux-master/open.yaml') %>%
	data.tree::as.Node() %>%
	collapsibleTree::collapsibleTree(
		fill = 'orangered',
		root = 'vfs_open',
		width = 1850,
		height = 900,
		attribute = 'file',
		tooltip = T
	)

c958eac339d00f50b623f616a22d6f14.png

可喜的是鼠标移动到节点上,可以显示函数定义所在的文件和行数

啃linux源码终于不用在纸上画了


本专栏只生产干货,喜欢请关注:

数据及可视化​zhuanlan.zhihu.com
9cb28833a2dbc12ae73fe383e30bc950.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值