作者:ARM-WinCE
具体内容开始之前,先说点缘由。我不用WinCE已经很久了,呵呵,目前公司的项目都是基于Linux/Android,所以也开始在Linux上面做开发。我在接触WinCE之前就做Linux驱动,后来改做WinCE或者说主要做WinCE,但断断续续的接触Embedded Linux,所以写了大量的WinCE博客。现如今风水轮流转,以后要以Linux/Android为主,断断续续的做点WinCE或者Windows Embedded Compact 7了。说实话,刚开始还真有点不太适应。不多说了,下面进入正题。
做过Linux系统性能分析和优化的人,一定对Oprofile不陌生,我用到的有两个工具,OProfile和Ftrace,都是用来分析内核性能的工具,今天先介绍一下OProfile的使用。刚开始用得时候,我也是一个初学者,最大的感受就是很难将OProfile在我的嵌入式Linux上面运行起来,在花了很多时间以后才搞定,所以这里写一篇如何玩转OProfile的文章。如下:
1. 首先要下载OProfile的相关软件包,如下:
oprofile-0.9.6.tar.gz: http://oprofile.sourceforge.net/download/
popt-1.14.tar.gz: http://freshmeat.net/projects/popt/
binutils-2.20.tar.gz: http://ftp.gnu.org/gnu/binutils/
注意:在下载oprofile-0.9.6.tar.gz的时候,建议通过git来下载,否则可能不能支持ARM-CortexA9.
下载完成后,创建一个文件夹名为OProfile_Project,进入该文件夹通过Git命令下载oprofile-0.9.6.tar.gz,解压另外两个工具包,命令如下:
cd Oprofile_Project
git clone git://oprofile.git.sourceforge.net/gitroot/oprofile/oprofile
tar -zxvf popt-1.14.tar.gz
tar -zxvf binutils-2.20.tar.gz
rm *.gz
完成后,应该获得三个子文件夹分别是binutils-2.20,oprofile和popt-1.14。
2. 使用交叉编译器编译OProfile
首先,确认你的目标板上运行的Linux是否支持下面的选项:
Profiling Support
OProfile system profiling
Kernel performance events and counters
然后为你的交叉编译器设置环境变量,如下:
export CC=arm-none-linux-gnueabi-gcc
export CXX=arm-none-linux-gnueabi-g++
export CFLAGS=-static
export CXXFLAGS=-static
export CPPFLAGS=-static
export ac_cv_va_copy=C99
2.1 交叉编译popt-1.14
进入"OProfile_Project/popt-1.14"目录,打开configure.ac文件,注释掉46行,如下:
AC_ISC_POSIX
AM_C_PROTOTYPES
#AC_CHECK_VA_COPY
AC_CHECK_HEADERS
然后在当前目录下创建一个"mypopt"的文件夹,并运行下面的命令进行配置,编译和安装:
./configure –with-kernel=<your embedded linux kernel path> --with-kernel-support –target=arm-none-linux-gnueabi –host=arm-none-linux-gnueabi –prefix= <..../OProfile_Project/popt-1.14/mypopt>
make
make install
然后拷贝所生成的头文件及库到你的交叉编译器的目录下面如下:
cp ./mypopt/include/* <your cross-compiler directory>/arm-none-linux-gnueabi/include
cp ./mypopt/lib/* <your cross-compiler directory>/arm-none-linux-gnueabi/lib
2.2 交叉编译binutils-2.20
首先进入"OProfile_Project/binutils-2.20/gas/config"目录,然后打开tc-arm.c,在2488行做如下的修改:
if (frag->tc_frag_data.last_map != NULL) {
know (S_GET_VALUE (frag->tc_frag_data.last_map) < S_GET_VALUE(symbolP));
}
在"OProfile_Project/binutils-2.20/"下创建"mybinutils"子目录,运行下面的命令进行编译:
./configure --with-kernel-support –target=arm-none-linux-gnueabi –host=arm-none-linux-gnueabi –prefix= <..../OProfile_Project/binutils-2.20/mybinutils>
make
make install
2.3 交叉编译opofile-0.9.6
进入"OProfile_Project/oprofile"文件夹,运行下面的命令进行编译:
./autogen.sh
./configure –with-linux=<your embedded linux kernel path> --with-kernel-support –target=arm-none-linux-gnueabi –host=arm-none-linux-gnueabi –with-binutils=<../OProfile_Project/binutils-2.20/mybinutils/>
Make
然后进入"OProfile_Project/oprofile/utils/"目录,打开opcontrol文件,在大概1153行做如下修改:
#tmp=”${1/cell/CELL}”
#if test “$1” = “$tmp”; then
#No substitution occurred, so cputype is not cell
if echo $1 | grep -q cell; then
return 1
else
return 0
fi
然后回到"OProfile_Project/oprofile/"目录,运行下面的命令:
make DESTDIR=$PWD/tgt install
3. 拷贝OProfile到目标板上面
接下来,要将交叉编译好的oprofile及相关文件拷贝的目标板上面。在目标板启动Linux以后,可以将整个"OProfile_Project"目录拷贝到目标板上的文件系统中,比如"/home/username/OProfile_Project"目录。同时还需要linux的内核文件vmlinux,这个应该和你的目标板上面正在运行的linux是一致的。然后运行下面的拷贝命令:
cp /home/username/OProfile_Project/binutils-2.20/mybinutils/arm-none-linux-gnueabi/bin/obj* /usr/bin
cp -r /home/username/OProfile_Project/oprofile/tgt/usr/local/* /usr/local/
4. 运行OProfile
首先初始化,如下:
opcontrol –init
opcontrol –vmlinux=<your_linux_kernel_path/vmlinux>
然后启动Oprofile
opcontrol –start
停止Oprofile
opcontrol –stop
看一下report
opreport
CPU: ARM Cortex-A9, speed 1200 MHz (estimated)
Counted CPU_CYCLES events (Number of CPU cycles) with a unit mask of 0x00 (No unit mask) count 100000
CPU_CYCLES:100000|
samples| %|
------------------
4047 69.3930 vmlinux
1161 19.9074 libc-2.10.1.so
345 5.9156 ld-2.10.1.so
153 2.6235 dash
65 1.1145 oprofiled
16 0.2743 bash
10 0.1715 grep
7 0.1200 cat
....
....
1 0.0171 libdl-2.10.1.so
1 0.0171 libgcc_s.so.1
1 0.0171 libm-2.10.1.so
上面的运行结果只是一个例子,是基于默认的event(CPU_CYCLES)的,可以使用"-list-event"来查看所支持的event,命令如下:
opcontrol –list-events
如果想查看其它的event,需要先关闭oprofile然后重新启动,命令如下:
opcontrol --shutdown
opcontrol –event= <your event>
opcontrol --start
在运行opofile之后,还可以通过下面的命令查看函数调用的更多的细节:
Opreport -l
这里介绍了如何编译并安装oprofile到嵌入式Linux当中,更加具体的使用,可以到oprofile的网站上面察看:oprofile.sourceforge.net。