如何获得函数栈空间大小_[R] 如何用树展示linux C函数调用栈 - collapsibleTree

e4e3e3f5603e154bf91d568de5ea2241.png

效果如下:

7a764d7101f045c12d34ffa86eeac564.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 - 一款生成函数调用栈的命令行工具

举个例子:

a3ccaf632b68009c6e5e02a78930a9b2.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:

d48a8db65d59b2e9ddcbcbe55e69d7f0.png

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

xargs cflow -m vfs_open 2> /dev/null

用cflow -m vfs_open生成调用栈

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

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

956861260d38057968a5004caff2c753.png

至此,shell处理部分结束

2 R数据处理

2.1 加载YAML

0fa3cbb231340b0aacc408bf01219ac4.png
yaml::yaml.load_file('d:/linux-master/open.yaml')

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

2.2 YAML -> data.tree::Node

0d89a681848edb1deb1f83410203fed1.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
	)

85a774991ae156f5dd35b6009a198c2c.png

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

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


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

数据及可视化​zhuanlan.zhihu.com
674095e66151bf2a9ff2308e688fb286.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值