(1)首先需要为每个被测程序的所有编译文件增加选项,如果文件太多,这无疑是灾难,可利用spec文件达到目的
1 sed -i '$ a\export LD_PRELOAD=/usr/local/bin/ccover_tool/gcov_out.so' /home/ads/.bash_profile 2 SPECFILE=`dirname $(gcc -print-libgcc-file-name)`/specs 3 gcc -dumpspecs >$SPECFILE 4 sed -i '/^\*libgcc:/ { n; s/$/ -lgcov/; }' $SPECFILE 5 sed -i '/^\*cc1:/ {n; s/$/ -fprofile-arcs -ftest-coverage/; }' $SPECFILE 6 sed -i '/^\*cc1plus:/ {n; s/$/ -fprofile-arcs -ftest-coverage/; }' $SPECFILE |
(2)其次,服务程序在正常退出的时候调用exit()才会dump统计信息,而常驻内存的服务使用kill -9 模式,需要捕捉kill信号
#include <stdio.h> #include <stdlib.h> #include <signal.h> #define SIMPLE_WAY void sighandler(int signo) { #ifdef SIMPLE_WAY exit(signo); #else extern void __gcov_flush(); // flush out gcov stats data __gcov_flush(); // raise the signal again to crash process raise(signo); #endif } __attribute__ ((constructor)) void ctor() { int sigs[] = { SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGSEGV, SIGHUP, SIGINT, SIGQUIT, SIGTERM }; int i; struct sigaction sa; sa.sa_handler = sighandler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESETHAND; for(i = 0; i < sizeof(sigs)/sizeof(sigs[0]); ++i) { if (sigaction(sigs[i], &sa, NULL) == -1) { perror("Could not set signal handler"); } } } |
讲上述打包为.so
gcov_out.so:gcov_out.c
gcc -shared -fPIC gcov_out.c -o gcov_out.so
然后设置export LD_PRELOAD=gcov_out.so
(3)部署执行:由于执行和代码必须在一起;还必须指定所使用的代码路径;
(4)合并统计:分布式系统执行在不同的机器上,则需要把每个机器上面的信息收集进行合并操作;