linux 程序分析方法

1. 背景

现实中,我们需要学习已有的软件构造方法,或维护旧的软件,或添加新功能,亦或优化性能,

这时面对的代码都不是自己所写,那如何才能快速知道这个代码库干了什么,源文件如何组织,模块间如何交互?

2. 程序的运转

a)应用程序:一般是一个语法树结构,树的叶子结点或是简单的操作(+、-、=等),或是系统调用(read、write、sleep),

树根一般是main;如果有多线程/进程,那就会产生多颗树;在出现递归调用时,也会出现环路。

b)内核:内核是应用与硬件间的中间层,交互方法就是软中断和硬中断;

应用使用int指令触发系统调用,设备使用irq中断触发事件通知,内核使用in/out指令读写设备;

所以,内核一般有两部分组成:初始化流程(注册各种中断处理器),中断处理流程(各种中断响应例程);

最后,对于中断是自动切换上下文(寄存器状态),对于多任务执行则需要调度(哪些线程挂起,哪些线程运行)。

c)不论应用还是内核,一个执行流都是一颗树,树中的结点对应某个函数,这些函数都是可以读写全局变量和自己的局部变量。

3. 分析方法

所有程序都有启动流程,对于内核还有中断响应流程,数据是按需创建的,关键在于流程的把握。

流程包含了结点(函数)和结点间的关系(调用和被调),是一个有向图;

流入该结点的边说明了其用途,流出该结点的边说明了其实现方法。

这里介绍一种自动从源码生成流程图的工具:callgraph

该工具自动识别函数调用关系,并输出有向图,然后可以使用graphviz的dot命令生成可视化图表

保存格式可为pdf、png、svg等。

4. 示例分析

下面以linux-0.11的代码分析为例:

$ git clone https://github.com/gnprice/callgraph.git

下载后需要修改print_dot,以免无法显示:

~/projects/callgraph
[master]$ git diff
diff --git a/callgraph b/callgraph
index e771dce..a79fcd8 100755
--- a/callgraph
+++ b/callgraph
@@ -67,12 +67,12 @@ def print_dot(refs, nonstatic):
     size = (scale[0] * 11 - 1, scale[1] * 8.5 - 1) # inches; letter, 1" margins
     print ‘strict digraph calls {‘
     print ‘  rankdir=LR;‘
-    print ‘  size="%f,%f";‘ % size
-    print ‘  ratio=fill;‘
-    print ‘  rotate=90;‘
+#    print ‘  size="%f,%f";‘ % size
+#    print ‘  ratio=fill;‘
+#    print ‘  rotate=90;‘
     print ‘  center=1;‘
-    print ‘  margin=0;‘
-    print ‘  page="8.5,11";‘
+#    print ‘  margin=0;‘
+#    print ‘  page="8.5,11";‘
     funs = set(refs.keys())
     for f, calls in sorted(refs.iteritems()):
         shape = ‘box‘ if f in nonstatic else ‘plaintext‘

$ curl -O https://www.kernel.org/pub/linux/kernel/Historic/old-versions/linux-0.11.tar.gz

$ tar -xf linux-0.11.tar.gz

$ cd linux-0.11/init

~/projects/linux-0.11/init

$ cat main.c | ~/projects/callgraph/callgraph | dot -Tpng > main.png

单文件init/main.c调用图如下:

整个kernel 子目录的调用图:

$ find kernel -type f -name "*.c" -o -name "*.h" | xargs cat | ~/projects/callgraph/callgraph | dot -Tpng > kernel.png

时间: 2024-10-11 06:22:08

linux 程序分析方法的相关文章

linux程序分析工具介绍(一)—-”/proc”

写在最前面:在开始本文之前,笔者认为先有必要介绍一下linux下的man,如果读者手头用linux系统,直接在终端输入man man便可以看到详细的说明,我在这里简单的总结一下,man命令是用来查看linux下各种命令.工具等的用户手册(manual)的.一种比较常用的用法是"man n field",这里的n是要查找的手册了类型,field是关键字.在这里介绍一下n: 0 /usr/include下的头文件 1 可执行程序和shell命令 2 系统调用 3 系统库函数 4 /dev下

linux程序分析工具介绍(三)——sar

本文要介绍的sar,是linux下用来分析系统本身运行情况的非常有用的工具.我们知道,程序在操作系统上要运行,要关注的点不外乎内存,CPU和IO(包括磁盘IO和网络IO).我们的应用程序在操作系统中运行前,我们需要了解系统当前的内存,cpu和IO的使用状况,还需要明白我们的应用程序运行时自身所需要的内存,cpu和IO资源的情况.只有操作系统剩余的内存,cpu和IO资源能够满足应用程序所需要的,才能保证应用程序在操作系统中正常的运行.sar就是用来帮助我们了解操作系统当前内存,cpu和IO等资源的

linux程序分析工具介绍(二)—-ldd,nm

本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析程序运行时需要依赖的动态库的工具:nm是用来查看指定程序中的符号表相关内容的工具.下面通过例子,分别来介绍一下这两个工具: 1. ldd, 先看下面的例子, 用ldd查看cs程序所依赖的动态库: [email protected]:~/Public$ ldd cs linux-gate.so.1 => (0xffffe000) libz.so.1 => /lib/libz.so.1 (0xb7f8c000)

Linux内核分析方法谈

本文来自 http://blog.csdn.net/ouyang_linux007/article/details/7422346 Linux的最大的好处之一就是它的源码公开.同时,公开的核心源码也吸引着无数的电脑爱好者和程序员:他们把解读和分析Linux的核心源码作为自己的最大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的最大目标. Linux内核源码是很具吸引力的,特别是当你弄懂了一个分析了好久都没搞懂的问题:或者是被你修改过了的内核,顺利通过编译,一切运行正常的时

Linux程序分析工具:ldd和nm

ldd和nm是Linux下两个非常实用的程序分析工具.其中,ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具. 1 ldd 格式:ldd [options] file    功能:列出file运行所需的共享库 参数: -d    执行重定位并报告所有丢失的函数 -r    执行对函数和对象的重定位并报告丢失的任何函数或对象 首先,ldd不是一个可执行程序,而是一个shell脚本.ldd能够显示可执行模块的dependency,其原理是通过设置一系列

如何运行linux程序

导读 搞懂linux程序如何运行是一件重要的事情,这是为我们进一步发展打下了坚实基础的一步.本文将通过实例来详细地讲解如何运行linux程序.希望对于大家理解有帮助. 首先,我们从一个十分简单的例子test.sh开始吧: #!/bin/sh #this is a test. cd /tmp echo "hello,this is a test" 这是一个十分简单的程序,但是运行结果可能会让你吃惊哦! 这个时候,我们发现程序运行之后,并没有改变当前目录.(黑人问号???) 别着急,我们先

Linux内核源码分析方法

  一.内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径.我们都知道,想成为优秀的程序员,需要大量的实践和代码的编写.编程固然重要,但是往往只编程的人很容易把自己局限在自己的知识领域内.如果要扩展自己知识的广度,我们需要多接触其他人编写的代码,尤其是水平比我们更高的人编写的代码.通过这种途径,我们可以跳出自己知识圈的束缚,进入他人的知识圈,了解更多甚至我们一

嵌入式linux应用程序调试方法

嵌入式linux应用程序调试方法 四 内存工具 17 4.1 MEMWATCH 17 4.2 YAMD 22 4.3 Electric Fence 24 五 C/C++代码覆盖.性能profiling工具 24 5.1 用gcov来测试代码覆盖率 25 5.2 使用gprof来优化你的C/C++程序 35 四 内存工具 您肯定不想陷入类似在几千次调用之后发生分配溢出这样的情形. 许多小组花了许许多多时间来跟踪稀奇古怪的内存错误问题.应用程序在有的开发工作站上能运行,但在新的产品工作站上,这个应用

转: 关于Linux常用的二进制文件分析方法

当你在unix下拿到一个二进制文件但不知道它是什么的时候,可以通过以下方法得到一此提示 1. 最首先应该尝试strings命令,比如拿到一个叫cr1的二进制文件,可以: $ strings cr1 | more 里面可能会有一些对于这个cr1的描述,这些信息都是编译之后在程序中留下的一些文本性的说明,所以可能会告诉你这个文件是什么. 比如有输出: $ strings cr1 | more %s %s %s%s%s -> %s%s%s (%.*s) Version: 2.3 Usage: dsni