Development Tools

Table of Contents

1 Cscope

Cscope is a developer's tool for browsing source code.

对于浏览源代码来说,在 Emacs 里面也有很多工具可用,比如自带的 etags 就不错,不过功能不如 Cscope 强大。 Cscope 并不像 etags 那样属于 Emacs , 它是一个独立的程序。它是一个具有完全 Unix 血统的程序,用于帮助开发人员浏览源代码。它最初(那还是 PDP-11 的时代)是由 Bell 实验室开发,并且多年以来一直是 AT&T Unix 商业发行版的一部分。它已经被用于管理超过两千万行代码的工程。在2000年4月,多亏了 Santa Cruz Operation, Inc. (SCO), Cscope 的源代码在 BSD license 下开放了源代码。

尽管Cscope最初是为C语言而设计的,但它也能很好地分析C++和Java源码。

参考:http://lifegoo.pluskid.org/wiki/EmacsCscope.html

1.1 Cscope基本使用

默认地,Cscope只分析当前目录下的C源码(.c和.h),lex源码(.l)和yacc源码(.y)。
如果想要分析c++源码或子目录中的源码,请手动把文件清单放入cscope.files中,Cscope会分析这个文件清单中的源码。

第一步:定制想要分析的文件
把想要分析的文件的清单放到文件cscope.files中。
在源代码目录中运行下面命令:

$ find . -name "*.[ch]" >cscope.files

如果待分析源码中还有cpp程序,可以用下面命令:

$ find . -name "*.[ch]" -o -name "*.cpp" >cscope.files

第二步:生成索引文件
运行下面命令:

$ cscope -b -q

-b Build the cross-reference only
-q 创建反向索引(可加速查找,会生成额外的文件cscope.in.out和cscope.po.out)
执行完上面命令,将生成 cscope.output,cscope.in.out和cscope.po.out

注:不手动生成索引文件,cscope也会自动生成索引文件cscope.output,但不会自动生成能加快查找速度的反向索引文件。

第三步:启动Cscope
直接执行cscope即可。
默认地,启动cscope时,会自动更新索引文件。用-d选项可以禁止其自动更新索引文件:

$ cscope -d

说明:要退出Cscope,请按Ctrl+d。

1.2 cscope-indexer

cscope-indexer 是一个shell脚本,用它可以方便地更新索引文件。cscope-indexer能自动处理C++文件。

如:对当前目录中所有文件(包括子目录)生成索引

$ /usr/bin/cscope-indexer -v -r
Creating list of files to index ...
Creating list of files to index ... done
Indexing files ...
Indexing files ... done

运行成功后,在当前目录下会生成cscope.files和cscope.out。

1.3 更快地查找函数定义或引用处

通常要查找一个函数的定义,首先启动cscope,再按1次Enter键,使光标位于"Find this global definition"处,然后输入函数名如fun1,再按Enter键。
其实,还有更简单的办法查找函数fun1的定义:

$ cscope -1 fun1

其中,数字1是指下面功能的索引号(第1个功能的索引号从数字0开始)。
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:
Find all function definitions:
Find all symbol assignments:

又如,要查找fun1的引用处("Find functions calling this function"功能的索引号为3),可以使用下面命令:

$ cscope -3 fun1

要在显示查找结果后直接退出,可以使用-L选项,如:

$ cscope -L -3 fun1

这样,不会进入到交互界面,返回查找结果后直接退出。

1.4 Emacs中使用Cscope

需要先安装cscope的emacs接口文件,在debian系统下,可用这样安装: apt-get install cscope-el ,安装完成后,在emacs启动文件中加上 (require 'xcscope) 即可。

在使用之前,cscope需要对代码进行索引。
在emacs中可以这样做:

C-c s a             设定初始化的目录,一般是你代码的根目录
C-s s I             对目录中的相关文件建立列表并进行索引

这是默认的用于查找的键绑定:

C-c s s         Find symbol.
C-c s d         Find global definition.
C-c s g         Find global definition (alternate binding).
C-c s G         Find global definition without prompting.
C-c s c         Find functions calling a function. (看看指定函数被哪些函数所调用)
C-c s C         Find called functions (list functions called
                from a function). (看看指定函数调用了哪些函数)
C-c s t         Find text string.
C-c s e         Find egrep pattern.
C-c s f         Find a file.
C-c s i         Find files #including a file. (看看指定的文件被哪些文件include).

下面是在搜索到的结果之间切换用的快捷键:

C-c s b         Display *cscope* buffer.
C-c s B         Auto display *cscope* buffer toggle.
C-c s n         Next symbol.
C-c s N         Next file.
C-c s p         Previous symbol.
C-c s P         Previous file.
C-c s u         Pop mark.

上面这些快捷键记不住没关系,菜单栏有一栏就是Cscope,这些命令在菜单里都有。

参考:http://www.caole.net/diary/emacs_write_cpp.html

1.5 GNU GLOBAL

GNU GLOBAL是一个类似cscope的工具,也能提供源文件之间的交叉索引。其独到之处在于,当你生成索引文件以后,再修改整个项目里的一个文件,然后增量索引的过程非常快。

参考:
http://www.gnu.org/software/global/globaldoc_toc.html
http://www.gnu.org/software/global/links.html
http://www.newsmth.net/nForum/#!article/VIM/61229

2 Eclipse

Eclipse is an integrated development environment (IDE). It contains a base workspace and an extensible plug-in system for customizing the environment.

2.1 常用快捷键

用快捷键 Ctrl+Shift+L 可以显示常用快捷键列表。

Table 1: Eclipse常用快捷键
功能 快捷键(Mac下请把Ctrl换为Command)
查找工程中的文件 Ctrl + Shift + R
查找函数或变量被引用的位置 Ctrl + Shift + G
查找函数调用关系 Ctrl + Alt + H
删除当前行 Ctrl + d
定位到最后编辑的地 Ctrl + q
切换不同的Editor Ctrl + PageUp/PageDown
转大写字母 Ctrl+Shift+Y
转小写字母 Ctrl+Shift+X

注:Ctrl + Shift + G和Ctrl + Alt + H都能找到当前函数被哪些函数调用了,只是展示形式不一样。

参考:
List of key bindings: http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.platform.doc.user/reference/ref-keybindings.htm
List of JDT key bindings: http://help.eclipse.org/kepler/index.jsp?topic=/org.eclipse.jdt.doc.user/reference/ref-keybindings.htm

2.1.1 当前文件/工程中查找关键字

点击菜单“Search” -> “File”,弹出对话框中的Scope一项中“Selected resource”和“Enclosing projectes”分别代表“当前文件”和“当前工程”。

这两个命令使用很频繁,建议分别为它们定制快捷键,这两项功能对应的“Command Name”分别为:Find Text in File/Find Text in Project。

2.2 调试Ant工程

如何导入Ant工程?办法是:点击“[File] -> [New] -> [Project…]”,选择"Java Project from Existing Ant Buildfile"

如何Debug Ant project?
参考:
http://stackoverflow.com/questions/2406825/how-to-debug-java-code-when-using-ant-script-in-eclipse
http://javarevisited.blogspot.jp/2011/02/how-to-setup-remote-debugging-in.html

1 Configure ant project.
Add following two lines into build.xml

     <jvmarg value="-Xdebug" />
     <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=4567" />

After your changes, the build.xml looks like:

    <java classname="xxxxxxx" fork="true">
     <jvmarg value="-Xdebug" />
     <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=4567" />

Note: make sure port 4567 is available in your machine. If it is occupied, please choose another one.

2 Configure remote debugging in Eclipse
Click [Run] -> [Debug Configurations…], new a Remote Java Application. Configure "Connection Properties"。

3 Enjoy debug.
Right click build.xml, Click [Run As] -> [Ant Build]
After it running, click menu [Run] -> [Debug Configurations…], click [Debug].

2.3 SQL Explorer

Eclipse SQL Explorer is a thin SQL client that allows you to query and browse any JDBC compliant database.

首次使用时,必须先进行JDBC驱动的配置,配置方法参考:Eclipse Sql Explorer - Driver Preferences。这里有使用SQL Explorer时的一些截图:Eclipse Sql Explorer - Random Screebnshots

如果要连接Oracle Database,可以在 Oracle Database 11g Release 2 JDBC Drivers 或者 Oracle Database 12.1.0.1 JDBC Driver & UCP Downloads 处下载对应的JDBC驱动。

2.3.1 安装SQL Explorer

Eclispe中安装SQL Explorer的步骤如下:点击“Help”菜单,打开“Install new software”窗口。在“Work with”中输入下面的URL:

http://eclipsesql.sourceforge.net/

等待片刻后,在列出的“SQL Explorer”中选择一个版本,点击“Next”即可安装。

安装成功后,在“Perspective”中可以找到“SQL Explorer”。

参考:
Install Eclipse and SQL Explorer on Ubuntu

2.4 Tips

2.4.1 指定启动时使用的jvm

在配置文件eclipse.ini中指定-vm为jvm位置即可。如:

-vm
/opt/sun-jdk-1.7.0/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.7

参考:https://wiki.eclipse.org/Eclipse.ini

2.4.2 设置proxy

Howh to configure Proxy Settings in Eclipse
(1) In Eclipse IDE, select "Window –> Preferences".
(2) Preferences box prompt out, choose "Network Connections".
(3) Select "Manual" from Action Provider drop down list.
(4) Select Http in the List and click "Edit" button.
(5) Fill in the proxy server host and port number, (fill in the username and password if any).

参考:http://www.mkyong.com/web-development/how-to-configure-proxy-settings-in-eclipse/

注意:如果代理无法工作,试一试只给http/https设置代理,清除socks的代理设置。
参考:http://stackoverflow.com/questions/17338212/eclipse-kepler-not-connecting-to-internet-via-proxy

2.4.3 启动时显示日志

eclipse启动有问题时,可以使用下面参数帮助定位问题:

$ eclipse -clean -debug -consolelog

2.4.4 格式化代码时只用空格

For CDT: Go to Window/Preference -> C/C++ -> Code Style -> Formatter -> New (create a new one because the built in profile can not be changed) -> MyProfile (choose one name for the profile) -> Indentation, Tab Policy –> Spaces only

参考:http://stackoverflow.com/questions/407929/how-do-i-change-eclipse-to-use-spaces-instead-of-tabs

2.4.5 临时禁止格式化Java代码中的注释

在Java中如果注释块以 /*- 开始,则Eclispe不会对其进行格式化。如:

/*-
 * Here is a block comment with some very special
 * formatting that I want indent(1) to ignore.
 *
 *    one
 *        two
 *            three
 */

参考:
https://stackoverflow.com/questions/1820908/how-to-turn-off-the-eclipse-code-formatter-for-certain-sections-of-java-code
http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-141999.html#680

2.4.6 保存文件时自动删除行尾空格

对正在编辑文件的所有行自动删除行尾空格:
"Preferences" -> "Java" -> "Editor" -> "Save Actions" -> check "Perform the selected actions on save" -> check "Additional actions" -> click "Configure.." -> go to "Code organizing" tab -> check "Remove trailing whitespace" -> select "All lines".

对正在编辑文件的当前行自动删除行尾空格:
"Preferences" -> "Java" -> "Editor" -> "Save Actions" -> check "Perform the selected actions on save" -> check "Format source code" -> select "Format edited lines".

参考:http://stackoverflow.com/questions/1043433/how-to-auto-remove-trailing-whitespace-in-eclipse

2.4.7 自动生成JUnit测试类

在类名上点右键 –> New –> Other
在新建对话框中,选择Java >> Junit >> Junit Test Case

参考:
Eclipse不可不知的用法之二:自动生成接口和JUnit测试类:http://www.blogjava.net/rongxh7/archive/2009/06/28/284438.html

2.4.8 让eclispe提示选择workspace

如果eclipse在启动时直接使用默认workspace,不提示workspace位置,可以通过下面方法让其重新提示。

Window > Preferences > General > Startup and Shutdown > Workspaces
Check Button: "Prompt for workspace on startup"

参考:
http://stackoverflow.com/questions/7058782/how-to-force-eclipse-to-ask-for-default-workspace

3 Electric Fence(可检测内存非法访问)

Electric Fence is a debugger that uses virtual memory hardware to detect illegal memory accesses. It can detect two common programming bugs: software that overruns or underruns the boundaries of a malloc() memory allocation, and software that touches a memory allocation that has been released by free().

原理:
Electric Fence利用底层硬件(CPU提供的虚拟内存管理)提供的机制,对内存区域进行保护。它使用的 mprotect 系统调用,当被保护的内存被修改时,程序会立即core掉,通过检查core文件的backtrace,就容易定位到问题代码。

3.1 安装Electric Fence

Electric Fence安装方式如下(以Ubuntu 14.04为例):

sudo apt-get install electric-fence

3.2 Electric Fence实例:检测内存越界

#include <stdio.h>
#include <malloc.h>

int main(void)
{
    int *a = (int*)malloc(2*sizeof(int));  /* 仅分配2个int的内存 */

    int i;
    for (i=0;i<=5;i++) {
        a[i] = i;
        printf("%d\n", a[i]);
    }

    free(a);
    return 0;
}

测试1(不用efence):

$ gcc -Wall -o test test.c && ./test
0
1
2
3
4
5

测试2(使用efence):
用electric-fence,需要在编译的时候链接efence库。

$ gcc -Wall -o test test.c -lefence && ./test

  Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
0
1
zsh: segmentation fault (core dumped)  ./test

4 free

free 命令用于显示系统中的内存使用情况。

实例:

$ free -m
             total       used       free     shared    buffers     cached
Mem:          1906       1072        834          0        109        502
-/+ buffers/cache:        461       1445
Swap:         1952          0       1952

说明1: -m 指定以MB为单位显示内存。
除表头外的第1行说明:
total:表示物理内存总量。
used:表示总计分配给缓存(包含buffers与cache)使用的数量,但其中可能部分缓存并未实际使用。
free:未被分配的内存。
shared:共享内存,一般系统不会用到,这里也不讨论。
buffers: 系统分配但未被使用的buffers数量。
cached: 系统分配但未被使用的cache数量。

除表头外的第2行说明(一般看这行就够了):
used:也就是第一行中的used-buffers-cached,它表示实际已使用的内存。即461=1072-109-502
free:未被使用的buffers与cache和未被分配的内存之和,这就是系统当前的可用内存。即1445=834+109+502

参考:http://www.linuxso.com/command/free.html

4.1 buffer与cache的区别

A buffer is something that has yet to be "written" to disk.
A cache is something that has been "read" from the disk and stored for later use.

Buffer is a region of memory used to temporarily hold data while it is being moved from one place to another. 
Cache is a temporary storage area where frequently accessed data can be stored for rapid access.

5 Fortify(Static Code Analysis)

Fortify 是著名的源码静态分析工具,它是商业软件。

Fortify会把源码转换为它自己理解的形式。

Fortify.png

Figure 1: Fortify工作过程

参考:
Static analysis tools for security: http://www.dwheeler.com/essays/static-analysis-tools.html
List of tools for static code analysis: https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis

5.1 Fortify基本用法

用工具 sourceanalyzer 可以生成FPR文件,详情可参考 sourceanalyzer -h
用工具 auditworkbench 可以打开FPR文件,它会启动图形界面,可方便地检查发现的问题。

以C代码为例,Fortify基本用法如下:

$ ./bin/sourceanalyzer -b my_test -clean
$ ./bin/sourceanalyzer -b my_test gcc -c 1.c
$ ./bin/sourceanalyzer -b my_test -scan -f my_test.fpr
$ ./bin/auditworkbench my_test.fpr

说明1:更多的实例可以参考Fortify自带的Sample。
说明2:如果想直接在控制台中查看发现的问题,生成text格式的报告即可(-f选项指定.txt后缀的文件即可),如:

$ ./bin/sourceanalyzer -b my_test -scan -f my_test.txt
$ cat my_test.txt

[/home/user1/test]

[EC15CFBDCBAB0F7CF4514CBFDAA662F3 : low : Dangerous Function : strcpy() : semantic ]
1.c(7) : strcpy()

[3A61B90FBDD7380464B7E456B2CD4D61 : high : Buffer Overflow : dataflow ]
1.c(7) :  ->strcpy(1)
    1.c(6) : <=> (path)
    1.c(6) : <- getenv(return)

[DB472DE24AFF49C6E5EED93B82D27A8F : high : Buffer Overflow : buffer ]
1.c(11) : strncat()
   Buffer Definition, buf2 1.c(9)
 Buffer Size: 8 bytes
 Write Length: 15 bytes
    [var 0] src.$strlen: 13

[7382E26AD11C9FA80B70DEF9C4FA4D16 : medium : Missing Check against Null : controlflow ]

    1.c(6) : start -> allocated : path = getenv(...) : getenv may return NULL
    1.c(7) : allocated -> used : path : path used without null check

注:生成上面报告的测试程序的内容如下:

/* file 1.c */
#include<string.h>

int
main() {
  char buf1[1024] = "";
  char * path = getenv("PATH");
  strcpy(buf1, path);

  char buf2[8] = "abcd";
  char *src = "1234567890abc";
  strncat(buf2, src, 10);

  return 0;
}

5.1.1 和make集成

方法一:使用Fortify Touchless Build Adapter,用法如下:

$ ./bin/sourceanalyzer -b my_test touchless make

方法二:修改makefile文件

CC=sourceanalyzer -b my_test gcc
CXX=sourceanalyzer -b my_test g++
AR=sourceanalyzer -b my_test ar

参考:Fortify SCA User Guide

5.2 Tips

5.2.1 找不到rules files

可能提示下面错误:

[error]: No rules files found
[warning]: No rules files found

执行rules更新程序即可。

$ ls Core/config/rules
README.TXT

$ ./bin/rulepkupdate      # 在新版fortify中改名成了 ./bin/fortifyupdate

$ ls Core/config/rules
core_abap.bin          core_java.bin        extended_content.bin
core_abap_preview.bin  core_javascript.bin  extended_cpp.bin
core_actionscript.bin  core_objc.bin        extended_dotnet.bin
core_android.bin       core_php.bin         extended_java.bin
core_annotations.bin   core_python.bin      extended_jsp.bin
core_cfml.bin          core_ruby.bin        extended_sql.bin
core_cobol.bin         core_sql.bin         README.TXT
core_cpp.bin           core_vb.bin          rp.update.properties
core_dotnet.bin        extended_config.bin

参考:http://stackoverflow.com/questions/18209159/fortify-error-no-rules-file-found

6 gprof(性能分析工具)

gprof 是一个性能分析工具。

下面演示一个简单的使用实例:
第1步,用gcc -pg 选项编译程序。

$ gcc -ggdb3 -pg 1.c -o 1

第2步,执行编译好的程序(注意会在当前文件夹中生成文件gmon.out)

$ ./1

第3步,用gprof生成报告

$ gprof 1 gmon.out >output.txt

参考:http://web.eecs.umich.edu/~sugih/pointers/gprof_quick.html

7 indent

indent is a Unix utility that reformats C and C++ code in a user-defined indent style and coding style.

$ indent -gnu 1.c -o 1_gnu.c          # 变成gnu风格
$ indent -kr -i8 1.c -o 1_kernel.c    # 变成K&R风格

gnu风格:http://www.gnu.org/prep/standards/
kernel风格:https://www.kernel.org/doc/Documentation/CodingStyle

indent常用选项如下:
 -bad或–blank-lines-after-declarations  在声明区段或加上空白行。
 -bap或–blank-lines-after-procedures  在程序或加上空白行。
 -bbb或–blank-lines-after-block-comments  在注释区段后加上空白行。
 -bc或–blank-lines-after-commas  在声明区段中,若出现逗号即换行。
 -bl或–braces-after-if-line  if(或是else,for等等)与后面执行区段的"{"不同行,且"}"自成一行。
 -bli<缩排格数>或–brace-indent<缩排格数>  设置{ }缩排的格数。
 -br或–braces-on-if-line  if(或是else,for等等)与后面执行跛段的"{"不同行,且"}"自成一行。
 -bs或–blank-before-sizeof  在sizeof之后空一格。
 -c<栏数>或–comment-indentation<栏数>  将注释置于程序码右侧指定的栏位。
 -cd<栏数>或–declaration-comment-column<栏数>  将注释置于声明右侧指定的栏位。
 -cdb或–comment-delimiters-on-blank-lines  注释符号自成一行。
 -ce或–cuddle-else  将else置于"}"(if执行区段的结尾)之后。
 -ci<缩排格数>或–continuation-indentation<缩排格数>  叙述过长而换行时,指定换行后缩排的格数。
 -cli<缩排格数>或–case-indentation-<缩排格数>  使用case时,switch缩排的格数。
 -cp<栏数>或-else-endif-column<栏数>  将注释置于else与elseif叙述右侧定的栏位。
 -cs或–space-after-cast  在cast之后空一格。
 -d<缩排格数>或-line-comments-indentation<缩排格数>  针对不是放在程序码右侧的注释,设置其缩排格数。
 -di<栏数>或–declaration-indentation<栏数>  将声明区段的变量置于指定的栏位。
 -fc1或–format-first-column-comments  针对放在每行最前端的注释,设置其格式。
 -fca或–format-all-comments  设置所有注释的格式。
 -gnu或–gnu-style.  指定使用GNU的格式,此为预设值。
 -i<格数>或–indent-level<格数>  设置缩排的格数。
 -ip<格数>或–parameter-indentation<格数>  设置参数的缩排格数。
 -kr或–k-and-r-style.  指定使用Kernighan&Ritchie的格式。
 -lp或–continue-at-parentheses  叙述过长而换行,且叙述中包含了括弧时,将括弧中的每行起始栏位内容垂直对其排列。
 -nbad或–no-blank-lines-after-declarations  在声明区段后不要加上空白行。
 -nbap或–no-blank-lines-after-procedures  在程序后不要加上空白行。
 -nbbb或–no-blank-lines-after-block-comments  在注释区段后不要加上空白行。
 -nbc或–no-blank-lines-after-commas  在声明区段中,即使出现逗号,仍旧不要换行。
 -ncdb或–no-comment-delimiters-on-blank-lines  注释符号不要自成一行。
 -nce或–dont-cuddle-else  不要将else置于"}"之后。
 -ncs或–no-space-after-casts  不要在cast之后空一格。
 -nfc1或–dont-format-first-column-comments  不要格式化放在每行最前端的注释。
 -nfca或–dont-format-comments  不要格式化任何的注释。
 -nip或–no-parameter-indentation  参数不要缩排。
 -nlp或–dont-line-up-parentheses  叙述过长而换行,且叙述中包含了括弧时,不用将括弧中的每行起始栏位垂直对其排列。
 -npcs或–no-space-after-function-call-names  在调用的函数名称之后,不要加上空格。
 -npro或–ignore-profile  不要读取indent的配置文件.indent.pro。
 -npsl或–dont-break-procedure-type  程序类型与程序名称放在同一行。
 -nsc或–dont-star-comments  注解左侧不要加上星号(*)。
 -nsob或–leave-optional-semicolon  不用处理多余的空白行。
 -nss或–dont-space-special-semicolon  若for或while区段仅有一行时,在分号前不加上空格。
 -nv或–no-verbosity  不显示详细的信息。
 -orig或–original  使用Berkeley的格式。
 -pcs或–space-after-procedure-calls  在调用的函数名称与"{"之间加上空格。
 -psl或–procnames-start-lines  程序类型置于程序名称的前一行。
 -sc或–start-left-side-of-comments  在每行注释左侧加上星号(*)。
 -sob或–swallow-optional-blank-lines  删除多余的空白行。
 -ss或–space-special-semicolon  若for或swile区段今有一行时,在分号前加上空格。
 -st或–standard-output  将结果显示在标准输出设备。
 -T  数据类型名称缩排。
 -ts<格数>或–tab-size<格数>  设置tab的长度。
 -v或–verbose  执行时显示详细的信息。
 -version  显示版本信息。

7.1 调整大括号"{"和"}"的格式

7.1.1 让if,else,for等和"{"在同一行(-br和-ce)

-br或–braces-on-if-line 可设置左括号"{"和if(else或for)在同一行,且让"}"自成一行。

如:

$ cat test4.c
if (x > 0)
{
  x--;}
else {
  ;
}
$ indent -br test4.c
$ cat test4.c
if (x > 0) {
  x--;
}
else {
  ;
}

-ce或–cuddle-else 可将else置于"}"(if执行区段的结尾)之后。
说明:-ce常和-br同时使用!

如:

$ cat test4.c
if (x > 0) {
  x--;
}
else{
  ;
}
$ indent -br -ce test4.c
$ cat test4.c
if (x > 0) {
  x--;
} else {
  ;
}
7.1.1.1 -br仅调整一行

假设"{"和if之间有1个或多个空行,-br选项并不会把"{"和if放在同一行,仅仅会使"{"和if更近一行。

如:

$ cat test4.c
if (x > 0)

{
  x--;
}
$ indent -br test4.c
$ cat test4.c
if (x > 0)
{
  x--;
}

7.1.2 让if,else,for等和"{"在不同行(-bl和-bli)

-bl或-braces-after-if-line 可使if(或是else,for等等)与后面执行区段的"{"不同行,且"}"自成一行,默认"{"和"}"有2个空格的缩进(可通过-bli调整)。

如:

$ cat test4.c
if (x > 0) {
  x--;
}
else {
  ;
}
$ indent -bl test4.c
$ cat test4.c
if (x > 0)
  {
    x--;
  }
else
  {
    ;
  }

-bli<缩排格数>或–brace-indent<缩排格数> 设置"{"和"}"缩排的格数。
说明:-bli<缩排格数>常和-bl同时使用!

如:

$ cat test4.c
if (x > 0) {
  x--;
}
else {
  ;
}
$ indent -bl -bli0 test4.c
$ cat test4.c
if (x > 0)
{
  x--;
}
else
{
  ;
}

7.1.3 调整结构体和函数中的"{"和"}"(-brs/-bls和-brf/-blf)

The -brs or -bls option specifies how to format braces in struct declarations.
The -brs option formats braces like this:

            struct foo {
              int x;
            };

The -bls option formats them like this:

            struct foo
            {
              int x;
            };

Similarly to the structure brace -brs and -bls options, the function brace options -brf or -blf specify how to format the braces in function definitions.
The -brf option formats braces like this:

            int one(void) {
              return 1;
            };

The -blf option formats them like this:

            int one(void)
            {
              return 1;
            };

8 OpenGrok(查看源码交叉引用)

OpenGrok is a source code search and cross reference engine. It helps programmers to search, cross-reference and navigate source code trees.

It can understand various program file formats and version control histories like Monotone, SCCS, RCS, CVS, Subversion, Mercurial, Git, Clearcase, Perforce and Bazaar.

OpenGrok is being developed mainly by Oracle Corporation (former Sun Microsystems) engineers with help from its community. OpenGrok is released under the terms of the Common Development and Distribution License (CDDL).

参考:http://opengrok.github.io/OpenGrok/

8.1 安装配置OpenGrok

OpenGrok依赖于:

  1. Latest Java 1.7
  2. A servlet container like GlassFish or Tomcat (6.x, 7.x or later) also running with Java at least 1.7
  3. Exuberant Ctags(Ubuntu下可这样安装 sudo apt-get install exuberant-ctags)

下面的描述假定Java 1.7和Exuberant Ctags已经安装好。

第一步,安装Tomcat
下载最新的Tomcat, apache-tomcat-8.0.9.tar.gz

$ tar -xvzf apache-tomcat-8.0.9.tar.gz
$ cd apache-tomcat-8.0.9/bin
$ ./startup.sh

浏览器能正常访问下面网站,说明安装启动成功。
http://localhost:8080/

第二步,下载配置OpenGrok
OpenGrok下载地址:http://opengrok.github.io/OpenGrok/ 在该网址中可以下载OpenGrok的编译文件,也可以下载源文件。在此我们直接下载编译文件(对OpenGrok感兴趣的同学可以下载源码查看究竟),下载后通过以下命令进行解压:

$ tar xvzf opengrok-0.12.1.tar.gz

解压完成后进入到解压目录,将./lib目录下的source.war包拷贝到./apache-tomcat-8.0.9/webapps目录下,在浏览器中输入http://localhost:8080/source/ (备注:war包会自动解压)看到OpenGrok界面证明OpenGrok运行成功。

第三步,为项目源码生成索引
进入到./opengrok-0.12.1/bin 目录,执行以下命令建立源码索引:
如源码在/home/usr1/proj/emacs-22.1中,我们想把索引和opengrok的其它数据文件放在/home/usr1/opengrok/emacs-22.1中:
$ OPENGROK_INSTANCE_BASE=/home/usr1/opengrok/emacs-22.1 ./OpenGrok index /home/usr1/proj/emacs-22.1
如果想在命令执行时看到详细的信息,可能加上OPENGROK_VERBOSE=true,即:

$ OPENGROK_VERBOSE=true OPENGROK_INSTANCE_BASE=/home/usr1/opengrok/emacs-22.1 ./OpenGrok index /home/usr1/proj/emacs-22.1

成功建立好索引后,会在生成一个配置文件:OPENGROK_INSTANCE_BASE/etc/configuration.xml

第四步,更新项目的配置文件configuration.xml到Tomcat的web app.
进入到Tomcat目录,编译下面文件webapps/source/WEB-INF/web.xml,修改CONFIGURATION对应的param-value
即把下面内容

<web-app>
  <display-name>OpenGrok</display-name>
  <description>A wicked fast source browser</description>
  <context-param>
    <param-name>CONFIGURATION</param-name>
    <param-value>/var/opengrok/etc/configuration.xml</param-value>
    <description>Full path to the configuration file where OpenGrok can read it's configuration</description>
  </context-param>

修改为:

<web-app>
  <display-name>OpenGrok</display-name>
  <description>A wicked fast source browser</description>
  <context-param>
    <param-name>CONFIGURATION</param-name>
    <param-value>/home/usr1/opengrok/emacs-22.1/etc/configuration.xml</param-value>
    <description>Full path to the configuration file where OpenGrok can read it's configuration</description>
  </context-param>

注:在用cvs项目做测试时,发现生成索引时必须可访问cvs服务器。

参考:http://blog.csdn.net/weihan1314/article/details/8944291

9 pmap(查看进程的内存映像信息)

The pmap command reports the memory map of a process or processes.

SYNOPSIS
pmap [ -x | -d ] [ -q ] pids…
pmap -V

GENERAL OPTIONS
-x extended Show the extended format.
-d device Show the device format.
-q quiet Do not display some header/footer lines.
-V show version Displays version of program.

如查看进程1的内存映像信息:

$ sudo pmap -x 1
1:   /sbin/init
Address           Kbytes     RSS   Dirty Mode  Mapping
00007fe13c000000     164      12      12 rw---   [ anon ]
00007fe13c029000   65372       0       0 -----   [ anon ]
00007fe142f11000       4       0       0 -----   [ anon ]
00007fe142f12000    8192       8       8 rw---   [ anon ]
00007fe143712000       4       0       0 -----   [ anon ]
00007fe143713000    8192       8       8 rw---   [ anon ]
00007fe143f13000      16      16       0 r-x-- libattr.so.1.1.0
00007fe143f17000    2044       0       0 ----- libattr.so.1.1.0
00007fe144116000       4       4       4 r---- libattr.so.1.1.0
00007fe144117000       4       4       4 rw--- libattr.so.1.1.0
00007fe144118000      12      12       0 r-x-- libdl-2.19.so
00007fe14411b000    2044       0       0 ----- libdl-2.19.so
00007fe14431a000       4       4       4 r---- libdl-2.19.so
00007fe14431b000       4       4       4 rw--- libdl-2.19.so
00007fe14431c000     432      16       0 r-x-- libpcre.so.3.13.1
00007fe144388000    2048       0       0 ----- libpcre.so.3.13.1
00007fe144588000       4       4       4 r---- libpcre.so.3.13.1
00007fe144589000       4       4       4 rw--- libpcre.so.3.13.1
00007fe14458a000      28      28       0 r-x-- librt-2.19.so
00007fe144591000    2044       0       0 ----- librt-2.19.so
00007fe144790000       4       4       4 r---- librt-2.19.so
00007fe144791000       4       4       4 rw--- librt-2.19.so
00007fe144792000      88      88       0 r-x-- libkmod.so.2.2.8
00007fe1447a8000    2044       0       0 ----- libkmod.so.2.2.8
00007fe1449a7000       4       4       4 r---- libkmod.so.2.2.8
00007fe1449a8000       4       4       4 rw--- libkmod.so.2.2.8
00007fe1449a9000      16      16       0 r-x-- libcap.so.2.24
00007fe1449ad000    2044       0       0 ----- libcap.so.2.24
00007fe144bac000       4       4       4 r---- libcap.so.2.24
00007fe144bad000       4       4       4 rw--- libcap.so.2.24
00007fe144bae000     104     100       0 r-x-- libaudit.so.1.0.0
00007fe144bc8000    2044       0       0 ----- libaudit.so.1.0.0
00007fe144dc7000       8       8       8 r---- libaudit.so.1.0.0
00007fe144dc9000       4       4       4 rw--- libaudit.so.1.0.0
00007fe144dca000      40       4       4 rw---   [ anon ]
00007fe144dd4000      52      52       0 r-x-- libpam.so.0.83.1
00007fe144de1000    2048       0       0 ----- libpam.so.0.83.1
00007fe144fe1000       4       4       4 r---- libpam.so.0.83.1
00007fe144fe2000       4       4       4 rw--- libpam.so.0.83.1
00007fe144fe3000     132     116       0 r-x-- libselinux.so.1
00007fe145004000    2048       0       0 ----- libselinux.so.1
00007fe145204000       4       4       4 r---- libselinux.so.1
00007fe145205000       4       4       4 rw--- libselinux.so.1
00007fe145206000       8       4       4 rw---   [ anon ]
00007fe145208000    1660    1332       0 r-x-- libc-2.19.so
00007fe1453a7000    2048       0       0 ----- libc-2.19.so
00007fe1455a7000      16      16      16 r---- libc-2.19.so
00007fe1455ab000       8       8       8 rw--- libc-2.19.so
00007fe1455ad000      16      12      12 rw---   [ anon ]
00007fe1455b1000      96      96       0 r-x-- libpthread-2.19.so
00007fe1455c9000    2044       0       0 ----- libpthread-2.19.so
00007fe1457c8000       4       4       4 r---- libpthread-2.19.so
00007fe1457c9000       4       4       4 rw--- libpthread-2.19.so
00007fe1457ca000      16       4       4 rw---   [ anon ]
00007fe1457ce000     128     128       0 r-x-- ld-2.19.so
00007fe145908000     812     692     692 rw---   [ anon ]
00007fe1459ea000      16      16      16 rw---   [ anon ]
00007fe1459ee000       4       4       4 r---- ld-2.19.so
00007fe1459ef000       4       4       4 rw--- ld-2.19.so
00007fe1459f0000       4       4       4 rw---   [ anon ]
00007fe1459f1000    1160    1084       0 r-x-- systemd
00007fe145d12000     120     120     120 r---- systemd
00007fe145d30000       4       4       4 rw--- systemd
00007fe1474fc000    1172    1116    1116 rw---   [ anon ]
00007ffd46b0c000     132      48      48 rw---   [ stack ]
00007ffd46b2f000       8       8       0 r-x--   [ anon ]
00007ffd46b31000       8       0       0 r----   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
---------------- ------- ------- -------
total kB          110828    5260    2168

最后一行中110828表示该进程预先分配的虚拟内存大小。5260是实际使用的内存(RSS)。

9.1 实现pmap的另一种方法

通过查看 /proc/<pid>/maps 文件也可得到进程的内存映像信息。
如查看进程1的内存映像信息:

$ sudo cat /proc/1/maps
7fe13c000000-7fe13c029000 rw-p 00000000 00:00 0
7fe13c029000-7fe140000000 ---p 00000000 00:00 0
7fe142f11000-7fe142f12000 ---p 00000000 00:00 0
7fe142f12000-7fe143712000 rw-p 00000000 00:00 0
7fe143712000-7fe143713000 ---p 00000000 00:00 0
7fe143713000-7fe143f13000 rw-p 00000000 00:00 0
7fe143f13000-7fe143f17000 r-xp 00000000 08:01 130689                     /lib/x86_64-linux-gnu/libattr.so.1.1.0
7fe143f17000-7fe144116000 ---p 00004000 08:01 130689                     /lib/x86_64-linux-gnu/libattr.so.1.1.0
7fe144116000-7fe144117000 r--p 00003000 08:01 130689                     /lib/x86_64-linux-gnu/libattr.so.1.1.0
7fe144117000-7fe144118000 rw-p 00004000 08:01 130689                     /lib/x86_64-linux-gnu/libattr.so.1.1.0
7fe144118000-7fe14411b000 r-xp 00000000 08:01 130716                     /lib/x86_64-linux-gnu/libdl-2.19.so
7fe14411b000-7fe14431a000 ---p 00003000 08:01 130716                     /lib/x86_64-linux-gnu/libdl-2.19.so
7fe14431a000-7fe14431b000 r--p 00002000 08:01 130716                     /lib/x86_64-linux-gnu/libdl-2.19.so
7fe14431b000-7fe14431c000 rw-p 00003000 08:01 130716                     /lib/x86_64-linux-gnu/libdl-2.19.so
7fe14431c000-7fe144388000 r-xp 00000000 08:01 130810                     /lib/x86_64-linux-gnu/libpcre.so.3.13.1
7fe144388000-7fe144588000 ---p 0006c000 08:01 130810                     /lib/x86_64-linux-gnu/libpcre.so.3.13.1
7fe144588000-7fe144589000 r--p 0006c000 08:01 130810                     /lib/x86_64-linux-gnu/libpcre.so.3.13.1
7fe144589000-7fe14458a000 rw-p 0006d000 08:01 130810                     /lib/x86_64-linux-gnu/libpcre.so.3.13.1
7fe14458a000-7fe144591000 r-xp 00000000 08:01 130831                     /lib/x86_64-linux-gnu/librt-2.19.so
7fe144591000-7fe144790000 ---p 00007000 08:01 130831                     /lib/x86_64-linux-gnu/librt-2.19.so
7fe144790000-7fe144791000 r--p 00006000 08:01 130831                     /lib/x86_64-linux-gnu/librt-2.19.so
7fe144791000-7fe144792000 rw-p 00007000 08:01 130831                     /lib/x86_64-linux-gnu/librt-2.19.so
7fe144792000-7fe1447a8000 r-xp 00000000 08:01 130749                     /lib/x86_64-linux-gnu/libkmod.so.2.2.8
7fe1447a8000-7fe1449a7000 ---p 00016000 08:01 130749                     /lib/x86_64-linux-gnu/libkmod.so.2.2.8
7fe1449a7000-7fe1449a8000 r--p 00015000 08:01 130749                     /lib/x86_64-linux-gnu/libkmod.so.2.2.8
7fe1449a8000-7fe1449a9000 rw-p 00016000 08:01 130749                     /lib/x86_64-linux-gnu/libkmod.so.2.2.8
7fe1449a9000-7fe1449ad000 r-xp 00000000 08:01 130704                     /lib/x86_64-linux-gnu/libcap.so.2.24
7fe1449ad000-7fe144bac000 ---p 00004000 08:01 130704                     /lib/x86_64-linux-gnu/libcap.so.2.24
7fe144bac000-7fe144bad000 r--p 00003000 08:01 130704                     /lib/x86_64-linux-gnu/libcap.so.2.24
7fe144bad000-7fe144bae000 rw-p 00004000 08:01 130704                     /lib/x86_64-linux-gnu/libcap.so.2.24
7fe144bae000-7fe144bc8000 r-xp 00000000 08:01 130691                     /lib/x86_64-linux-gnu/libaudit.so.1.0.0
7fe144bc8000-7fe144dc7000 ---p 0001a000 08:01 130691                     /lib/x86_64-linux-gnu/libaudit.so.1.0.0
7fe144dc7000-7fe144dc9000 r--p 00019000 08:01 130691                     /lib/x86_64-linux-gnu/libaudit.so.1.0.0
7fe144dc9000-7fe144dca000 rw-p 0001b000 08:01 130691                     /lib/x86_64-linux-gnu/libaudit.so.1.0.0
7fe144dca000-7fe144dd4000 rw-p 00000000 00:00 0
7fe144dd4000-7fe144de1000 r-xp 00000000 08:01 130799                     /lib/x86_64-linux-gnu/libpam.so.0.83.1
7fe144de1000-7fe144fe1000 ---p 0000d000 08:01 130799                     /lib/x86_64-linux-gnu/libpam.so.0.83.1
7fe144fe1000-7fe144fe2000 r--p 0000d000 08:01 130799                     /lib/x86_64-linux-gnu/libpam.so.0.83.1
7fe144fe2000-7fe144fe3000 rw-p 0000e000 08:01 130799                     /lib/x86_64-linux-gnu/libpam.so.0.83.1
7fe144fe3000-7fe145004000 r-xp 00000000 08:01 130833                     /lib/x86_64-linux-gnu/libselinux.so.1
7fe145004000-7fe145204000 ---p 00021000 08:01 130833                     /lib/x86_64-linux-gnu/libselinux.so.1
7fe145204000-7fe145205000 r--p 00021000 08:01 130833                     /lib/x86_64-linux-gnu/libselinux.so.1
7fe145205000-7fe145206000 rw-p 00022000 08:01 130833                     /lib/x86_64-linux-gnu/libselinux.so.1
7fe145206000-7fe145208000 rw-p 00000000 00:00 0
7fe145208000-7fe1453a7000 r-xp 00000000 08:01 130701                     /lib/x86_64-linux-gnu/libc-2.19.so
7fe1453a7000-7fe1455a7000 ---p 0019f000 08:01 130701                     /lib/x86_64-linux-gnu/libc-2.19.so
7fe1455a7000-7fe1455ab000 r--p 0019f000 08:01 130701                     /lib/x86_64-linux-gnu/libc-2.19.so
7fe1455ab000-7fe1455ad000 rw-p 001a3000 08:01 130701                     /lib/x86_64-linux-gnu/libc-2.19.so
7fe1455ad000-7fe1455b1000 rw-p 00000000 00:00 0
7fe1455b1000-7fe1455c9000 r-xp 00000000 08:01 130825                     /lib/x86_64-linux-gnu/libpthread-2.19.so
7fe1455c9000-7fe1457c8000 ---p 00018000 08:01 130825                     /lib/x86_64-linux-gnu/libpthread-2.19.so
7fe1457c8000-7fe1457c9000 r--p 00017000 08:01 130825                     /lib/x86_64-linux-gnu/libpthread-2.19.so
7fe1457c9000-7fe1457ca000 rw-p 00018000 08:01 130825                     /lib/x86_64-linux-gnu/libpthread-2.19.so
7fe1457ca000-7fe1457ce000 rw-p 00000000 00:00 0
7fe1457ce000-7fe1457ee000 r-xp 00000000 08:01 130677                     /lib/x86_64-linux-gnu/ld-2.19.so
7fe145908000-7fe1459d3000 rw-p 00000000 00:00 0
7fe1459ea000-7fe1459ee000 rw-p 00000000 00:00 0
7fe1459ee000-7fe1459ef000 r--p 00020000 08:01 130677                     /lib/x86_64-linux-gnu/ld-2.19.so
7fe1459ef000-7fe1459f0000 rw-p 00021000 08:01 130677                     /lib/x86_64-linux-gnu/ld-2.19.so
7fe1459f0000-7fe1459f1000 rw-p 00000000 00:00 0
7fe1459f1000-7fe145b13000 r-xp 00000000 08:01 3879                       /lib/systemd/systemd
7fe145d12000-7fe145d30000 r--p 00121000 08:01 3879                       /lib/systemd/systemd
7fe145d30000-7fe145d31000 rw-p 0013f000 08:01 3879                       /lib/systemd/systemd
7fe1474fc000-7fe147621000 rw-p 00000000 00:00 0                          [heap]
7ffd46b0c000-7ffd46b2d000 rw-p 00000000 00:00 0                          [stack]
7ffd46b2f000-7ffd46b31000 r-xp 00000000 00:00 0                          [vdso]
7ffd46b31000-7ffd46b33000 r--p 00000000 00:00 0                          [vvar]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

10 pstack(进程当前stack信息)

工具pstack可查看进程的当前stack信息,效果类似于gdb中的bt命令。
注1:当程序包含调试信息时,gdb的bt命令能直接显示行号信息,而pstack不能。如:

$ pstack 1
#0  0x000000323f2da073 in __select_nocancel () from /lib64/libc.so.6
#1  0x000000323ee0d9dc in nih_main_loop () from /lib64/libnih.so.1
#2  0x000000000040466d in ?? ()
#3  0x000000323f21ec5d in __libc_start_main () from /lib64/libc.so.6
#4  0x00000000004040b9 in ?? ()
#5  0x00007fff36a365e8 in ?? ()
#6  0x000000000000001c in ?? ()
#7  0x0000000000000001 in ?? ()
#8  0x00007fff36a36fad in ?? ()
#9  0x0000000000000000 in ?? ()

注2:pstack在redhat系统中工作良好,但在64位debian中系统中无法正常工作。
注3:文件 /proc/<pid>/stack 的内容仅仅是显示进程的内核栈信息。如

$ cat /proc/self/stack
[<ffffffff81021bce>] save_stack_trace_tsk+0x1e/0x40
[<ffffffff8120817d>] proc_pid_stack+0x8d/0xe0
[<ffffffff81208d87>] proc_single_show+0x47/0x80
[<ffffffff811c9612>] seq_read+0xe2/0x360
[<ffffffff811a7ef3>] vfs_read+0x93/0x170
[<ffffffff811a8b22>] SyS_read+0x42/0xa0
[<ffffffff81512e68>] page_fault+0x28/0x30
[<ffffffff81510e4d>] system_call_fast_compare_end+0x10/0x15
[<ffffffffffffffff>] 0xffffffffffffffff

11 Source Insight

Source Insight is a light-weight and fast project oriented program code editor and code browser, with built-in analysis for C/C++, C#, and Java programs, as well as other languages.

Useful features:
Context Window is a Source Insight innovation that automatically provides relevant information while you are viewing and editing your source code. For example, Context Window will display the declaration of that variable/class or the implementation body of that function.

Relation Window is a Source Insight innovation that shows the relationship between the currently selected symbol and other things (function call graph or class tree diagram).

Reference:
Source Insight 3.5 User Manual: http://www.sourceinsight.com/docs35/ManualTOC.htm

11.1 常用快捷键

Source Insight常用快捷键如表 2 所示。

Table 2: Source Insight常用快捷键
快捷键 描述
F8 在当前文件中查找符号
Ctrl + = Jump to definition. 也可以用Ctrl + 鼠标左键单击
Ctrl + / Lookup reference.
Shift + F8 高亮(或取消高亮)和光标处单词相同的单词
Shift + F4 往后搜索光标处单词
Shift + F3 往前搜索光标处单词
F12 Incremental search. 一边输入一边搜索
Alt + , Jump backword
Alt + . Jump forward
F5 或 Ctrl + g 跳转到某行
Alt + F12 切换等宽字体,也可以用[View]->[Draft View]

12 strace, ltrace, mtrace

strace - trace system calls and signals.
ltrace - like strace, but trace library call.
mtrace - malloc tracing.(常用于调试内存泄漏问题)

13 strings

strings命令的功能是显示文件中的可打印字符。常用来在二进制文件中查找字符串,比如查找某一个函数或者字符串是否在某一个库中。
默认情况下,strings只显示文件里包含的所有4个或以上连续可打印字符的字符串。这可以通过 -n 选项来修改。
默认情况下,strings只显示object file中的初始化段和装载段的字符串。可以指定选项 -a 或-all来让strings描述整个object file.

例如:

$ cat test1.c
int main(void) {
  return printf("hello world\n");
}
$ gcc -o a.out test1.c
$ strings ./a.out
/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
printf
__libc_start_main
GLIBC_2.2.5
fff.
=p 
l$ L
t$(L
|$0H
hello world
;*3$"

说明:不同环境下输出可能不一样。

14 sysstat(sar)

The sysstat utilities are a collection of performance monitoring tools for Linux. These include sar, sadf, mpstat, iostat, tapestat, pidstat, cifsiostat and sa tools.

sysstat工具集中最重要的是sar(System Activity Reports),它是一个收集系统性能数据的强大工具。

主要工具的作用如下:

  • iostat 工具提供CPU使用率及硬盘吞吐效率的数据;
  • mpstat 工具提供单个处理器或多个处理器相关数据;
  • pidstat 工具收集进程运行时的I/O,CPU和内存使用情况;
  • sar 工具负责收集、报告并存储系统活跃的信息;
  • sa1 工具负责收集并存储每天系统动态信息到一个二进制的文件中。它是通过计划任务工具cron来运行,是为sadc所设计的程序前端程序;
  • sa2 工具负责把每天的系统活跃性息写入总结性的报告中。它是为sar所设计的前端 ,要通过cron来调用;
  • sadc 是系统动态数据收集工具,收集的数据被写一个二进制的文件中,它被用作sar工具的后端;
  • sadf 显示被sar通过多种格式收集的数据;

参考1:http://sebastien.godard.pagesperso-orange.fr/
参考2:http://blog.chinaunix.net/uid-12247636-id-2953458.html

第一步:安装
Ubuntu中可以这样安装:

$ apt-get install sysstat

第二步:配置
安装完成后,无法立即运行sar,因为其配置文件禁止了其运行。打开配置文件/etc/default/sysstat,把其中ENABLED值从false改为true。
然后启用相应服务,如 /etc/init.d/sysstat start

第三步:简单使用
sar的选项非常多,下面只列出常用的:
-A:所有报告的总和。
-u:CPU利用率(默认为查看CPU利用率,可省略)
-v:进程、I节点、文件和锁表状态。
-d:硬盘使用报告。
-r:没有使用的内存页面和硬盘块。
-g:串口I/O的情况。
-b:缓冲区使用情况。
-a:文件读写情况。
-c:系统调用情况。
-R:进程的活动情况。
-y:终端设备活动情况。
-w:系统交换活动。

sar使用时,一般最后两个参数分别为:interval、count(采样间隔和采样次数)
例如,每10秒采样一次,连续采样2次,观察CPU的使用情况:

$ sar -u 10 2
Linux 2.6.32-100.28.5.el6.x86_64        01/07/2013      _x86_64  _       (8 CPU)

01:00:14 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
01:00:24 AM     all      0.28      0.00      0.54      1.07      0.03     98.07
01:00:34 AM     all      0.38      0.00      0.74      0.11      0.02     98.75
Average:        all      0.33      0.00      0.64      0.58      0.02     98.41

15 SystemTap(stap, 内核调试工具)

SystemTap 是一个内核调试工具。

安装SystemTap的过程(Ubuntu 14.04):
第1步:安装stap

$ sudo apt-get install systemtap

第2步:安装匹配的内核调试文件(如果只是监视用户代码,则不需要内核调试文件)
To use systemtap you need to manually install the linux-image-X-dbg and linux-header-X packages that match your running kernel. To simplify this task you can use the stap-prep command.
运行stap-prep工具会提示需要安装哪个内核调试文件。

第3步:加入当前用户(如jack)到组stapusr和stapdev

$ sudo adduser jack stapusr
$ sudo adduser jack stapdev

参考:
http://blog.jeffli.me/blog/2014/10/10/install-systemtap-in-ubuntu-14-dot-04/
https://wiki.ubuntu.com/Kernel/Systemtap#Where_to_get_debug_symbols_for_kernel_X.3F

15.1 Tips

问题:待分析的程序需要环境变量才能运行,无法直接启动。
如prog需要设置一些环境变量,无法在stap中直接用-c参数启动。

$ stap -v -e 'probe process("./prog").function("main") {printf("%s\n", $$parms$$); }' -c "./prog"

出现错误:
error while loading shared libraries…..

注: $$parms$$ 是stap内置的用来显示函数参数的记号。

解决办法:写一个类似下面wrapper

$ cat 1.sh
. ./setenv
./prog

再用-c启动上面的wrapper程序:

$ stap -v -e 'probe process("./prog").function("main") {printf("%s\n", $$parms$$); }' -c "sh ./1.sh"

16 Valgrind

Valgrind is an instrumentation framework for building dynamic analysis tools. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail.

参考:
The Valgrind Quick Start Guide: http://valgrind.org/docs/manual/quick-start.html
Valgrind User Manual: http://valgrind.org/docs/manual/manual.html
Using Valgrind to Find Memory Leaks and Invalid Memory Use: http://www.cprogramming.com/debugging/valgrind.html

16.1 Valgrind实例:查找内存泄露

测试C程序如下:

#include <stdlib.h>
int main()
{
    char *x = malloc(100);
    return 0;
}

用valgrind执行编译好的程序:

$ valgrind --tool=memcheck ./a.out

==12945== Memcheck, a memory error detector
==12945== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==12945== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==12945== Command: ./a.out
==12945== 
==12945== 
==12945== HEAP SUMMARY:
==12945==     in use at exit: 100 bytes in 1 blocks
==12945==   total heap usage: 1 allocs, 0 frees, 100 bytes allocated
==12945== 
==12945== LEAK SUMMARY:
==12945==    definitely lost: 100 bytes in 1 blocks
==12945==    indirectly lost: 0 bytes in 0 blocks
==12945==      possibly lost: 0 bytes in 0 blocks
==12945==    still reachable: 0 bytes in 0 blocks
==12945==         suppressed: 0 bytes in 0 blocks
==12945== Rerun with --leak-check=full to see details of leaked memory
==12945== 
==12945== For counts of detected and suppressed errors, rerun with: -v
==12945== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

17 vmstat

vmstat (virtual memory statistics) is a computer system monitoring tool that collects and displays summary information about operating system memory, processes, interrupts, paging and block I/O.

下面是运行 vmstat 的输出例子:

$ vmstat 1 6    # 1表示采集间隔为1秒,6表示共采集6次
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 4615096 3038056 38104728    0    0     2    32    5    4  6  1 92  0  0
 1  0      0 4595820 3038056 38104728    0    0     0     8 6349 5219 17 25 58  0  0
 3  0      0 4489904 3038056 38106224    0    0     0   308 4182 5663 61 13 25  0  0
 3  0      0 4446832 3038056 38105612    0    0     0   460 3124 3228 78 13  9  0  0
 2  0      0 4388312 3038056 38105612    0    0     0     4 3193 4439 88 12  0  0  0
 2  0      0 4354088 3038056 38105612    0    0     0     0 2817 2873 77  5 18  0  0

默认地(不加参数), vmstat 的输出信息分为了6组(procs/memory/swap/io/system/cpu),下面分别解释这6组报告:
(1) Procs
r: The number of processes waiting for CPU time. (r=running queue)
b: The number of processes in uninterruptible sleep. (b=blocked queue, waiting for resource (e.g. filesystem I/O blocked, inode lock))

Tips:如果发现 r 值大于系统中的CPU核数,则往往意味着“CPU是性能瓶颈”。
Tips:当 b 值比较大时,则往往意味着“磁盘是性能瓶颈”。

(2) Memory
swpd: the amount of virtual memory used.
free: the amount of idle memory.
buff: the amount of memory used as buffers.
cache: the amount of memory used as cache.

Tips:上面4项内存相关输出在命令 free 的输出中都可以找到。

(3) Swap
si: Amount of memory swapped in from disk (/s). 每秒由内存进入内存交换区数量。
so: Amount of memory swapped to disk (/s). 每秒由内存交换区进入内存数量。

(4) IO
bi: Blocks received from (read) a block device (blocks/s). 每秒读磁盘的数据。
bo: Blocks sent to (write) a block device (blocks/s). 每秒写磁盘的数据。

(5) System
in: The number of interrupts per second, including the clock.
cs: The number of context switches per second.

(6) CPU
us: Time spent running non-kernel code. (user time, including nice time)
sy: Time spent running kernel code. (system time)
id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.

参考:
https://linux.die.net/man/8/vmstat
https://www.thomas-krenn.com/en/wiki/Linux_Performance_Measurements_using_vmstat
http://nonfunctionaltestingtools.blogspot.jp/2013/03/vmstat-output-explained.html


Author: cig01

Created: <2010-11-02 Tue 00:00>

Last updated: <2018-04-18 Wed 16:22>

Creator: Emacs 25.3.1 (Org mode 9.1.4)