zynq交叉編譯
㈠ opencv不用把庫放到開發板上嗎
由於我本機PC端測試使用的opencv的版本為opencv2.4.6.1.故而我想要移植這個版本的opencv到zedboard板卡上。參考Xilinx出版的《Zynq開發實戰》的第13章以及幾個人的博客進行配置編譯的時候,總是會出現如下的錯誤:
In file included from /usr/include/math.h:409:0,
from /opt/opencv-2.4.6.1/moles/core/include/opencv2/core/types_c.h:94,
from /opt/opencv-2.4.6.1/moles/core/include/opencv2/core/core.hpp:49,
from /opt/opencv-2.4.6.1_forArm/moles/core/precomp.hpp:50:
/usr/include/bits/mathinline.h: In function 'void cv::randnScale_8u(const float*, uchar*, int, int, const float*, const float*, bool)':
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
/usr/include/bits/mathinline.h: In function 'void cv::randShuffle_(cv::Mat&, cv::RNG&, double) [with T = unsigned char]':
/usr/include/bits/mathinline.h:675:3: error: unknown register name 'st' in 'asm'
/usr/include/bits/mathinline.h: In function 'void cv::randShuffle_(cv::Mat&, cv:
......
在用交叉編譯工具鏈編譯opencv時候,我本來已經將交叉編譯工具鏈寫入了環境變數,那它搜索的時候,應該是遍歷交叉編譯工具鏈下的頭文件,但是 opencv卻默認遍歷到gcc頭文件下,故而出現這樣的錯誤,為何會這樣呢?試了多種方式均不能編譯通過,故而棄用書上編譯opencv的方式,轉向下 面的方式:
我們採用圖形化的cmake進行配置,這樣就可以指定交叉編譯工具鏈的頭文件目錄,下載cmake安裝包(ps:不要下載源代碼),下載地址如下:
http://www.cmake.org/cmake/resources/software.html我使用的系統為32位Centos6.4,故而我選擇的平台為linux i386,下載其後面的壓縮包。
下載完成後,解壓縮cmake-2.8.12.2-Linux-i386.tar.gz到/usr/local下,使用下面的命令:
tar xvzf cmake-2.8.12.2-Linux-i386.tar.gz -C /usr/local
export PATH=$PATH:/usr/local/cmake-2.8.12.2-Linux-i386/bin
接下來,我們利用cmake-gui進行opencv的配置,創建zedopencv目錄,解壓縮opencv代碼到此目錄下,在opencv的源代碼下創建zed_install,然後進入此目錄。命令如下:
tar xvzf opencv-2.4.6.1.tar.gz -C ./zedopencv
cd ./zedopencv/opencv-2.4.6.1
mkdir zed_install
cd zed_install
cmake-gui
出現如下的界面:
其中,按照提示選擇要編譯的opencv源代碼的路徑以及安裝編譯路徑,這里如圖所示。然後點擊Configure,出現如下的配置界面:
這里一定要注意,選擇Unix Makefile選項,在下面選擇指定編譯器選項,然後點擊next進入下面的界面,按照提示,填入如下的信息:
指定交叉編譯環境的頭文件目錄是/opt/xlinx-arm-gcc/arm-xilinx-linux-gnueabi/libc/usr/,選擇C 與C++的編譯器,還有平台,這里一定要注意Library mode的選項,這里一定要選擇在根目錄與本地系統下均搜索,如上圖所示,點擊Finish完成配置。第三方庫,盡量不用選,如下圖所示:
然後點擊Generate,完成配置,然後執行make,開始編譯,編譯的過程中會出現下面的一個錯誤:
Linking CXX executable ../../bin/opencv_createsamples
../../lib/libcxcore.so: undefined reference to `clock_gettime'
../../lib/libcxcore.so: undefined reference to `pthread_key_create'
../../lib/libcxcore.so: undefined reference to `pthread_getspecific'
../../lib/libcxcore.so: undefined reference to `pthread_setspecific'
按照錯誤的提示,是缺少線程鏈接,我們需要對此目錄下的CmakeCache.txt進行修改,修改的位置如下:
178 //Flags used by the linker.
179 CMAKE_EXE_LINKER_FLAGS:STRING=-lpthread -lrt
然後保存退出,繼續編譯就可以完成所有的編譯。完成後,在此目錄下的lib下發現已經編譯好了所有的庫文件,創建zed-lib-opencv文件夾,拷貝所用的.so文件到此目錄下。
為了便於製作鏡像文件,在此目錄下創建ramdisk文件夾。我寫了個shell腳本,也就是圖中所示的fs.sh,為了便於操作其中的參數$1代表要製作的鏡像的名稱,$2代表要製作鏡像的文件夾,$3代表鏡像的大小,腳本的具體內容如下:
#!/bin/bash
dd if=/dev/zero of=$1.image bs=1M count=$3
mke2fs -F $1.image -L "ramdisk" -b 1024 -m 0
tune2fs $1.image -i 0
chmod 777 $1.image
#mkdir ramdisk
mount -o loop $1.image ./ramdisk
cp -R ./$2/* ./ramdisk
umount ./ramdisk
由於ramdisk文件系統的大小為8M,而Opencv的庫文件顯然大於8M,其接近於25M,故而8M是滿足不了的,SD卡有4G的空間,製作庫文件的鏡像,拷貝到SD卡上,把SD卡掛載到Linux系統,就可以解決空間不夠用的問題。我們進行如下的操作:
首先進入filesys,在usr目錄下創建lib,再進入etc/init.d,對rcS文件進行修改。添加下面幾行代碼:
echo "mount otherlib....."
mount /dev/mmcblk0p1 /mnt
mount /mnt/opencvlib.image /usr/lib
export PATH=$PATH:/usr/local/bin
export LD_LIBRARY_PATH=/usr/local/lib:/lib
然後,我們進行鏡像的製作:
./fs.sh ramdisk8M filesys 8
./fs.sh opecv_lib zed-lib-opencv 80
製作了兩個鏡像文件ramdisk8M.image opecv_lib.image大小分別為8M與80M.
然後對ramdisk進行壓縮:
gzip -9 ramdisk8M.image
然後將新生成的ramdisk8M.image.gz與opencv_lib.image拷 貝到SD卡啟動zedboard即可發現,/usr/lib目錄下已經有了opencv庫文件,至此opencv移植到zedboard工作徹底完成!此 方法也可以用於一般的arm開發板opencv的移植。
要支持第三方庫,可以參照這個博客:ffmpeg支持,在編譯完第三方庫之後,需要重新編譯opencv庫!
㈡ 如何使用oprofile對軟體做profiling
一. Oprofile簡介
Profiling是對不同性能特徵的數據的形式化總結或分析,它通常以圖形和表的形式出現。它提供為特定的處理器事件收集的采樣百分數或數量,比如cache miss rate、TLB miss rate等等。一般來說,主要目的是為了找出軟體中的性能瓶頸,然後有針對性的優化以提升軟體的整體性能。
Oprofile 是用於 Linux 的若干種評測和性能監控工具中的一種。它可以工作在不同的體系結構上,包括ARM, PowerPC, MIPS, IA32, IA64 和 AMD Athlon等等。它的開銷很小,從Linux 2.6 版起,它被包含進了Linux內核中。
Oprofile可以收集有關處理器事件的信息,幫助用戶識別諸如循環的展開、cache的使用率低、低效的類型轉換和冗餘操作、錯誤預測轉移等問題。Oprofile是一種細粒度的工具,可以為指令集或者為函數、系統調用或中斷處理常式收集采樣。Oprofile 通過取樣來工作。使用收集到的評測數據,用戶可以很容易地找出性能問題。
通過監察CPU的hardware events,oprofile可以在運行狀態下對整個Linux系統進行profiling。Profiling的對象可以是Linux kernel (包括moles和interrupt handlers), shared libraries或者應用程序。
從0.9.8版本開始,oprofile支持Perf_events profiling mode模式。應用程序operf被用來控制profiling過程;而在legacy mode下,是通過opcontrol腳本和oprofiled daemon來完成的。Operf不再象legacy mode那樣需要OProfile kernel driver,它直接和Linux Kernel Performance Events Subsystem打交道。使用operf,就可以用普通用戶的身份來profiling用戶的應用程序了,當然如果需要對整個系統來profiling的時候還是需要root許可權的。
如果硬體不支持OProfile使用performance counters,OProfile就只能工作在Timer Mode下了。Timer Mode只能在legacy profiling mode下使用,即只能通過opcontrol腳本來控制。
Oprofile的優勢:
Ÿ 比較低的運行開銷
Ÿ 對被profiling的對象影響很小
Ÿ 可以profiling中斷服務程序(interrupt handlers)
Ÿ 可以profiling應用程序和shared libraries
Ÿ 可以profiling dynamically compiled (JIT) code
Ÿ 可以對整個系統做profiling
Ÿ 可以觀察CPU內部的細節,例如cache miss rate
Ÿ 可以多源代碼做annotation
Ÿ 可以支持instruction-level的profiling
Ÿ 可以生成call-graph profiles
不過OProfile也不是萬能的,它也有自己的局限性:
Ÿ 只能在x86, ARM, 和PowerPC架構上生成call graph profiles
Ÿ 不支持100%精確的instruction-level profiling
Ÿ 對dynamically compiled (JIT) code profiling的支持還不完善。
無論如何,Oprofile的功能都比gprof要強很多,代價是配置起來會比較麻煩。
二. 編譯Oprofile
首先最好在Linux kernel裡面選中Oprofile driver,以獲得全面的支持。因為筆者使用的是Xilinx Linux pre-built 14.7,所以這里下載的是linux-xlnx-xilinx-v14.7.tar.gz
解壓縮後,用以下命令調出Linux kernel的配置界面:
export ARCH=arm
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
make xilinx_zynq_defconfig
make xconfig 或者make menuconfig
在配置界面上將以下兩項勾上:
General setup --->
[*] Profiling support
<*> OProfile system profiling
然後make uImage即可生成新的uImage,用來替換Xilinx Linux pre-built 14.7中的Linux kernel image。同時我們也需要vmlinux來檢查profiling的結果。
Oprofile需要popt, bfd, liberty庫,要在嵌入式單板上使用這些庫,需要手工完成交叉編譯。
針對popt 1.7,用以下命令完成編譯:
./configure --prefix=/home/wave/xilinx/oprofileprj/rootfs --host=arm-xilinx-linux-gnueabi --with-kernel-support --disable-nls && make && make install
針對binutils 2.24,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --enable-install-libbfd --enable-install-libiberty --enable-shared && make && make install
不過--enable-install-libiberty沒有效果,所以需要手工把libiberty.a和libiberty.h拷貝到相應的位置。
針對oprofile 0.9.9,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --with-kernel-support --with-binutils=/home/wave/xilinx/oprofileprj/rootfs && make && make install
配置過程結束後可能會有以下提示,因為沒有打算用GUI和profile JITed code,所以直接忽視之。
config.status: executing libtool commands
Warning: QT version 3 was requested but not found. No GUI will be built.
Warning: The user account 'oprofile:oprofile' does not exist on the system.
To profile JITed code, this special user account must exist.
Please ask your system administrator to add the following user and group:
user name : 'oprofile'
group name: 'oprofile'
The 'oprofile' group must be the default group for the 'oprofile' user.
將編譯完成的uImage,vmlinux,oprofile binary,重新編譯的沒有-pg的libjpeg binary以及tool chain的libc打包放到SD卡中,准備在ZC706開發板上嘗試profile djpeg。
三. 運行Oprofile
正常啟動嵌入式Linux後,在開發板的console上一次輸入以下命令:
mount /dev/mmcblk0p1 /mnt
mkdir -p /home/root/work
cd /home/root/work
tar zxvf /mnt/jpeg-bin-nopg.tar.gz
cd jpeg-bin/bin
cp /mnt/park-2880x1800.jpg .
export LD_LIBRARY_PATH=/home/root/work/jpeg-bin/lib
cd /home/root/work
tar zxvf /mnt/rootfs.tar.gz
cd rootfs
chown root:root -R *
cp -R bin/* /usr/bin
cp -R lib/* /lib
cp /bin/which /usr/bin
cp /bin/dirname /usr/bin
mkdir -p /home/wave/xilinx/oprofileprj/rootfs/share
cp -R ./rootfs/* /home/wave/xilinx/oprofileprj/rootfs
cd /home/root/work
tar zxvf /mnt/libc.tar.gz
cp ./lib/libstdc*.* /lib
mkdir -p /home/wave/xilinx/libjpeg
cd /home/wave/xilinx/libjpeg
tar zxvf /mnt/jpeg-9.tar.gz
cp /mnt/vmlinux /home/root/work
cd /home/root/work/jpeg-bin/bin
opcontrol --init
opcontrol --vmlinux=/home/root/work/vmlinux
opcontrol --setup --event=CPU_CYCLES:100000::0:1 --session-dir=/home/root/
operf --vmlinux /home/root/work/vmlinux ./djpeg -bmp park-2880x1800.jpg > result.bmp
opreport -l ./djpeg
完成這一步後,我們就可以看到profiling的結果了,在筆者的平台上看到的內容的主要部分如下:
root@zynq:~/work/jpeg-bin/bin# opreport -l ./djpeg
Using /home/root/work/jpeg-bin/bin/oprofile_data/samples/ for samples directory.
CPU: ARM Cortex-A9, speed 666667 MHz (estimated)
Counted CPU_CYCLES events (CPU cycle) with a unit mask of 0x00 (No unit mask) count 100000
samples % image name symbol name
15293 58.6253 libc-2.17.so /lib/libc-2.17.so
2044
㈢ 在ARM上運行交叉編譯後的opencv文件,沒有輸出
一、交叉編譯opencv
構造:
下載:各個庫的下載可以直接搜名字到官網下載
幾個關鍵解釋:
「--prefix=」 後邊跟make install時的位置,本例中,libz在make install時將安裝到/usr/arm-linux-gnueabihf中
「--host=」 後邊跟arm-linux表明使用的是ARM環境
有configure的才能進行configure配置
4)所有的makefile修改類似
Libz的交叉編譯
第一步:# ./configure --prefix=/usr/arm-linux-gnueabihf --shared
第二步:修改makefile,主要有下邊幾個,修改的時候通篇參照即可
CC=arm-linux-gnueabihf-gcc
AR=arm-linux-gnueabihf-ar rc
RANLIB=arm-linux-gnueabihf-ranlib
STRIP = arm-linux-gnueabihf-strip
如果有ARCH的話,ARCH=ARM
第三步:#sudo make
#sudo make install
Libjpeg的交叉編譯
第一步:#./configure --host=arm-linux --prefix=/usr/arm-linux-gnueabihf --enable-shared --enable-static CC=arm-linux-gnueabihf-gcc
第二步:參考1)中方法修改makefile
第三步:#sudo make
#sudo make install
Libpng的交叉編譯
第一步:#./configure --host=arm-linux --prefix=/usr/arm-linux-gnueabihf --enable-shared --enable-static CC=arm-linux-gnueabihf-gcc
第二步:參考1)中方法修改makefile
第三步:#sudo make
#sudo make install
Yasm的交叉編譯
第一步:#./configure --host=arm-linux --prefix=/usr/arm-linux-gnueabihf --enable-shared --enable-static
第二步:修改makefile
第三步:#sudo make
#sudo make install
Libx264的交叉編譯
第一步:#CC=arm-linux-gnueabihf-gcc ./configure --enable-shared --host=arm-linux --disable-asm --prefix=/usr/arm-linux-gnueabihf
第二步:修改config.mak里的參數,因為makefile要調用config.mak,所以修改方法同makefile
第三步:#sudo make
#sudo make install
Libxvid的交叉編譯
第一步:首先切換目錄 #cd build/generic
第二步:#./configure --prefix=/usr/arm-linux-gnueabihf --host=arm-linux --disable-assembly
第三步:#sudo make
#sudo make install
ffmpeg的交叉編譯
第一步:
./configure --enable-cross-compile --target-os=linux --cc=arm-linux-gnueabihf-gcc --arch=arm --enable-shared --disable-static --enable-gpl --enable-nonfree --enable-ffmpeg --disable-ffplay --enable-ffserver --enable-swscale --enable-pthreads --disable-yasm --disable-stripping --enable-libx264 --enable-libxvid --extra-cflags=-I/usr/arm-linux-gnueabihf/include --extra-ldflags=-L/usr/arm-linux-gnueabihf/lib --prefix=/usr/arm-linux-gnueabihf
第二步:修改makefile文件
第三步:#sudo make
#sudo make install
第四步:將ffmpeg加入pkg-config
執行#sudo gedit /etc/bash.bashrc,在末尾加入
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib/
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/arm-linux-gnueabihf /lib/pkgconfig
export PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR:/usr/arm-linux-gnueabihf /lib/
完畢後使用命令:#source /etc/bash.bashrc
或者單獨使用三個export,不過壽命只在一個終端中,終端關閉時就失效。
幾個關鍵解釋:--extra-flags指向xvid的安裝路徑,--extra-ldflags指向x264的路徑
安裝cmake-gui
執行:#sudo apt-get install cmake-qt-gui
Opencv的交叉編譯
第一步:修改opencv/platflrms/linux/目錄下的arm-gnueabi.toolchain.cmake,將其所有刪掉,寫入:
set( CMAKE_SYSTEM_NAME Linux )
set( CMAKE_SYSTEM_PROCESSOR arm )
set( CMAKE_C_COMPILER arm-linux-gnueabihf-gcc )
set( CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++ )
第二步:在opencv目錄下新建build目錄,進入build目錄,執行命令:
#cmake -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/arm-gnueabi.toolchain.cmake ../
這時,要保證出現:
第三步:使用cmake-gui打開CMakeCache.txt,去掉所有的無關項,修改CMAKE_INSTALL_PREFIX,來確定make install的目錄
第四步:#sudo make
#sudo make install
可能出現的錯誤:
opencv編譯不通過,出現skip之類的,說明ffmpeg沒編譯好,或者其編譯好了,但是pkg-config沒有設置好,一定要設置好其環境
前邊幾步不通過的話,看看命令有沒有少,或者有沒有修改好makefile
在arm上使用時,一種方法時直接將編譯好的opencv目錄下的lib文件拷貝到開發板對應的/lib目錄下,其他或者拷貝到自己指定的目錄,並設置好環境變數即可使用
㈣ 如何使用oprofile對軟體做profiling
下載的是linux-xlnx-xilinx-v14.7.tar.gz
解壓縮後,用以下命令調出Linux kernel的配置界面:
export ARCH=arm
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
make xilinx_zynq_defconfig
make xconfig 或者make menuconfig
在配置界面上將以下兩項勾上:
General setup --->
[*] Profiling support
<*> OProfile system profiling
然後make uImage即可生成新的uImage,用來替換Xilinx Linux pre-built 14.7中的Linux kernel image。同時我們也需要vmlinux來檢查profiling的結果。
Oprofile需要popt, bfd, liberty庫,要在嵌入式單板上使用這些庫,需要手工完成交叉編譯。
針對popt 1.7,用以下命令完成編譯:
./configure --prefix=/home/wave/xilinx/oprofileprj/rootfs --host=arm-xilinx-linux-gnueabi --with-kernel-support --disable-nls && make && make install
針對binutils 2.24,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --enable-install-libbfd --enable-install-libiberty --enable-shared && make && make install
不過--enable-install-libiberty沒有效果,所以需要手工把libiberty.a和libiberty.h拷貝到相應的位置。
針對oprofile 0.9.9,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --with-kernel-support --with-binutils=/home/wave/xilinx/oprofileprj/rootfs && make && make install
配置過程結束後可能會有以下提示,因為沒有打算用GUI和profile JITed code,所以直接忽視之。
config.status: executing libtool commands
Warning: QT version 3 was requested but not found. No GUI will be built.
Warning: The user account 'oprofile:oprofile' does not exist on the system.
To profile JITed code, this special user account must exist.
Please ask your system administrator to add the following user and group:
user name : 'oprofile'
group name: 'oprofile'
The 'oprofile' group must be the default group for the 'oprofile' user.
將編譯完成的uImage,vmlinux,oprofile binary,重新編譯的沒有-pg的libjpeg binary以及tool chain的libc打包放到SD卡中,准備在ZC706開發板上嘗試profile djpeg。
三. 運行Oprofile
正常啟動嵌入式Linux後,在開發板的console上一次輸入以下命令:
mount /dev/mmcblk0p1 /mnt
mkdir -p /home/root/work
cd /home/root/work
tar zxvf /mnt/jpeg-bin-nopg.tar.gz
cd jpeg-bin/bin
cp /mnt/park-2880x1800.jpg .
export LD_LIBRARY_PATH=/home/root/work/jpeg-bin/lib
cd /home/root/work
tar zxvf /mnt/rootfs.tar.gz
cd rootfs
chown root:root -R *
cp -R bin/* /usr/bin
cp -R lib/* /lib
cp /bin/which /usr/bin
cp /bin/dirname /usr/bin
mkdir -p /home/wave/xilinx/oprofileprj/rootfs/share
cp -R ./rootfs/* /home/wave/xilinx/oprofileprj/rootfs
cd /home/root/work
tar zxvf /mnt/libc.tar.gz
cp ./lib/libstdc*.* /lib
mkdir -p /home/wave/xilinx/libjpeg
cd /home/wave/xilinx/libjpeg
tar zxvf /mnt/jpeg-9.tar.gz
cp /mnt/vmlinux /home/root/work
cd /home/root/work/jpeg-bin/bin
opcontrol --init
opcontrol --vmlinux=/home/root/work/vmlinux
opcontrol --setup --event=CPU_CYCLES:100000::0:1 --session-dir=/home/root/
operf --vmlinux /home/root/work/vmlinux ./djpeg -bmp park-2880x1800.jpg > result.bmp
opreport -l ./djpeg
完成這一步後,我們就可以看到profiling的結果了,在筆者的平台上看到的內容的主要部分如下:
root@zynq:~/work/jpeg-bin/bin# opreport -l ./djpeg
Using /home/root/work/jpeg-bin/bin/oprofile_data/samples/ for samples directory.
CPU: ARM Cortex-A9, speed 666667 MHz (estimated)
Counted CPU_CYCLES events (CPU cycle) with a unit mask of 0x00 (No unit mask) count 100000
samples % image name symbol name
15293 58.6253 libc-2.17.so /lib/libc-2.17.so
2044
㈤ 如何使用oprofile對軟體做profiling
關於Xilinx Zynq-7000帶來的新的系統設計思路,以及Profiling的對象libjpeg,前文已經描述過了,再此不再贅述。
一. Oprofile簡介
Profiling是對不同性能特徵的數據的形式化總結或分析,它通常以圖形和表的形式出現。它提供為特定的處理器事件收集的采樣百分數或數 量,比如cache miss rate、TLB miss rate等等。一般來說,主要目的是為了找出軟體中的性能瓶頸,然後有針對性的優化以提升軟體的整體性能。
Oprofile 是用於 Linux 的若干種評測和性能監控工具中的一種。它可以工作在不同的體系結構上,包括ARM, PowerPC, MIPS, IA32, IA64 和 AMD Athlon等等。它的開銷很小,從Linux 2.6 版起,它被包含進了Linux內核中。
Oprofile可以收集有關處理器事件的信息,幫助用戶識別諸如循環的展開、cache的使用率低、低效的類型轉換和冗餘操作、錯誤預測轉移 等問題。Oprofile是一種細粒度的工具,可以為指令集或者為函數、系統調用或中斷處理常式收集采樣。Oprofile 通過取樣來工作。使用收集到的評測數據,用戶可以很容易地找出性能問題。
通過監察CPU的hardware events,oprofile可以在運行狀態下對整個Linux系統進行profiling。Profiling的對象可以是Linux kernel (包括moles和interrupt handlers), shared libraries或者應用程序。
從0.9.8版本開始,oprofile支持Perf_events profiling mode模式。應用程序operf被用來控制profiling過程;而在legacy mode下,是通過opcontrol腳本和oprofiled daemon來完成的。Operf不再象legacy mode那樣需要OProfile kernel driver,它直接和Linux Kernel Performance Events Subsystem打交道。使用operf,就可以用普通用戶的身份來profiling用戶的應用程序了,當然如果需要對整個系統來profiling 的時候還是需要root許可權的。
如果硬體不支持OProfile使用performance counters,OProfile就只能工作在Timer Mode下了。Timer Mode只能在legacy profiling mode下使用,即只能通過opcontrol腳本來控制。
Oprofile的website為:http://oprofile.sourceforge.net/
可以支持的處理器的hardware event類型:http://oprofile.sourceforge.net/docs/
對於Zynq-7000來說,http://oprofile.sourceforge.net/docs/armv7-ca9- events.php 列出了ARM Cortex-A9內核PMU(Performance Monitor Unit)所支持的所有hardware event種類,可以看出oprofile可以支持很多深入處理器內部的分析。
http://oprofile.sourceforge.net/examples/ 提供了一些oprofile生成的結果,可以方便開發者在開始使用之前了解oprofile能夠做到哪些事情。
Oprofile的詳細使用文檔:http://oprofile.sourceforge.net/doc/index.html
Oprofile的優勢:
? 比較低的運行開銷
? 對被profiling的對象影響很小
? 可以profiling中斷服務程序(interrupt handlers)
? 可以profiling應用程序和shared libraries
? 可以profiling dynamically compiled (JIT) code
? 可以對整個系統做profiling
? 可以觀察CPU內部的細節,例如cache miss rate
? 可以多源代碼做annotation
? 可以支持instruction-level的profiling
? 可以生成call-graph profiles
不過OProfile也不是萬能的,它也有自己的局限性:
? 只能在x86, ARM, 和PowerPC架構上生成call graph profiles
? 不支持100%精確的instruction-level profiling
? 對dynamically compiled (JIT) code profiling的支持還不完善。
無論如何,Oprofile的功能都比gprof要強很多,代價是配置起來會比較麻煩。
二. 編譯Oprofile
首先最好在Linux kernel裡面選中Oprofile driver,以獲得全面的支持。
下載Linux kernel Source:從https://github.com/Xilinx/linux-xlnx 可以下載到Xilinx提供的驗證好的內核。如果不方便使用Linux下的git工具,可以單擊頁面上的releases找到相應的版本下載tar ball。下載的時候最好選tar.gz格式的,而不是zip格式的,因為後者在處理symbol link的時候有可能會出問題。
因為筆者使用的是Xilinx Linux pre-built 14.7,所以這里下載的是linux-xlnx-xilinx-v14.7.tar.gz
解壓縮後,用以下命令調出Linux kernel的配置界面:
export ARCH=arm
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
make xilinx_zynq_defconfig
make xconfig 或者make menuconfig
在配置界面上將以下兩項勾上:
General setup --->
[*] Profiling support
<*> OProfile system profiling
然後make uImage即可生成新的uImage,用來替換Xilinx Linux pre-built 14.7中的Linux kernel image。同時我們也需要vmlinux來檢查profiling的結果。
Oprofile需要popt, bfd, liberty庫,要在嵌入式單板上使用這些庫,需要手工完成交叉編譯。
針對popt 1.7,用以下命令完成編譯:
./configure --prefix=/home/wave/xilinx/oprofileprj/rootfs --host=arm-xilinx-linux-gnueabi --with-kernel-support --disable-nls && make && make install
針對binutils 2.24,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --enable-install-libbfd --enable-install-libiberty --enable-shared && make && make install
不過--enable-install-libiberty沒有效果,所以需要手工把libiberty.a和libiberty.h拷貝到相應的位置。
針對oprofile 0.9.9,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --with-kernel-support --with-binutils=/home/wave/xilinx/oprofileprj/rootfs && make && make install
配置過程結束後可能會有以下提示,因為沒有打算用GUI和profile JITed code,所以直接忽視之。
config.status: executing libtool commands
Warning: QT version 3 was requested but not found. No GUI will be built.
Warning: The user account 'oprofile:oprofile' does not exist on the system.
To profile JITed code, this special user account must exist.
Please ask your system administrator to add the following user and group:
user name : 'oprofile'
group name: 'oprofile'
The 'oprofile' group must be the default group for the 'oprofile' user.
將編譯完成的uImage,vmlinux,oprofile binary,重新編譯的沒有-pg的libjpeg binary以及tool chain的libc打包放到SD卡中,准備在ZC706開發板上嘗試profile djpeg。
三. 運行Oprofile
正常啟動嵌入式Linux後,在開發板的console上一次輸入以下命令:
mount /dev/mmcblk0p1 /mnt
mkdir -p /home/root/work
cd /home/root/work
tar zxvf /mnt/jpeg-bin-nopg.tar.gz
cd jpeg-bin/bin
cp /mnt/park-2880x1800.jpg .
export LD_LIBRARY_PATH=/home/root/work/jpeg-bin/lib
cd /home/root/work
tar zxvf /mnt/rootfs.tar.gz
cd rootfs
chown root:root -R *
cp -R bin/* /usr/bin
cp -R lib/* /lib
cp /bin/which /usr/bin
cp /bin/dirname /usr/bin
mkdir -p /home/wave/xilinx/oprofileprj/rootfs/share
cp -R ./rootfs/* /home/wave/xilinx/oprofileprj/rootfs
cd /home/root/work
tar zxvf /mnt/libc.tar.gz
cp ./lib/libstdc*.* /lib
mkdir -p /home/wave/xilinx/libjpeg
cd /home/wave/xilinx/libjpeg
tar zxvf /mnt/jpeg-9.tar.gz
cp /mnt/vmlinux /home/root/work
cd /home/root/work/jpeg-bin/bin
opcontrol --init
opcontrol --vmlinux=/home/root/work/vmlinux
opcontrol --setup --event=CPU_CYCLES:100000::0:1 --session-dir=/home/root/
operf --vmlinux /home/root/work/vmlinux ./djpeg -bmp park-2880x1800.jpg > result.bmp
opreport -l ./djpeg
完成這一步後,我們就可以看到profiling的結果了,在筆者的平台上看到的內容的主要部分如下:
root@zynq:~/work/jpeg-bin/bin# opreport -l ./djpeg
Using /home/root/work/jpeg-bin/bin/oprofile_data/samples/ for samples directory.
CPU: ARM Cortex-A9, speed 666667 MHz (estimated)
Counted CPU_CYCLES events (CPU cycle) with a unit mask of 0x00 (No unit mask) count 100000
samples % image name symbol name
15293 58.6253 libc-2.17.so /lib/libc-2.17.so
2044 7.8356 libjpeg.so.9.0.0 ycc_rgb_convert
1964 7.5289 libjpeg.so.9.0.0 jpeg_idct_16x16
1918 7.3526 libjpeg.so.9.0.0 decode_mcu
1570 6.0186 libjpeg.so.9.0.0 jpeg_idct_islow
1567 6.0071 djpeg finish_output_bmp
528 2.0241 libjpeg.so.9.0.0 jpeg_fill_bit_buffer
397 1.5219 djpeg put_pixel_rows
73 0.2798 vmlinux ___from_user
70 0.2683 libjpeg.so.9.0.0 decompress_onepass
65 0.2492 libjpeg.so.9.0.0 jpeg_huff_decode
56 0.2147 vmlinux get_page_from_freelist
50 0.1917 vmlinux __memzero
45 0.1725 vmlinux ___to_user_std
41 0.1572 vmlinux _raw_spin_unlock_irqrestore
15 0.0575 vmlinux do_page_fault
14 0.0537 vmlinux __generic_file_aio_write
13 0.0498 vmlinux _raw_spin_unlock_irq
11 0.0422 vmlinux free_hot_cold_page
11 0.0422 vmlinux vector_swi
10 0.0383 vmlinux handle_pte_fault
從結果中我們可以看到libjpeg.so.9.0.0, djpeg和vmlinux中的symbol name已經可以被正確的解析出來了,和gprof的結果基本一致。相比gprof,oprofile可以在更大的范圍內完成profiling。
我們還可以用以下命令觀察源代碼中特定行的執行時間,進一步縮小優化的范圍,達到事半功倍的效果。
opannotate --source ./djpeg > opannotate.txt
四. 小結
通過實驗,我們可以看到Oprofile可以提供更豐富的profiling結果,可以更好的幫助開發者找到瓶頸,通過有針對性的優化提升軟體 性能;profiling的結果也可以幫助開發者將性能瓶頸代碼通過Xilinx HLS工具用硬體加速器來實現,從而為進一步提升整個嵌入式系統的性能打開了大門。
㈥ zynq linux 移植過程中編譯u-boot出現問題
明顯是提示沒有庫文件吧。 libmpfr.so.1: cannot open shared object file: No such file or directory