strace是個功能強大的Linux調試分析診斷工具,可用於跟蹤程序執行時進程系統調用(system call)和所接收的信號,尤其是針對源碼不可讀或源碼無法再編譯的程序。
在Linux系統中,用戶程序運行在一個沙箱(sandbox)裏,用戶進程不能直接訪問計算機硬件設備。當進程需要訪問硬件設備(如讀取磁盤文件或接收網絡數據等)時,必須由用戶態模式切換至內核態模式,通過系統調用訪問硬件設備。strace可跟蹤進程產生的系統調用,包括參數、返回值和執行所消耗的時間。若strace沒有任何輸出,並不代表此時進程發生阻塞;也可能程序進程正在自己的沙箱裏執行某些不需要與系統其它部分發生通信的事情。strace從內核接收信息,且無需以任何特殊方式來構建內核。
當然它還可以做更多的事情:
strace可以過篩選出特定的系統調用。
strace可以記錄系統調用的次數,時間,成功和失敗的次數。
strace可以跟蹤發給進程的信號。
strace可以通過pid附加到任何正在運行的進程上。
strace類似其他Unix系統上的truss,或者Sun's Dtrace
對於成熟的服務器或者桌面系統,strace是已經集成好的一個應用,對於從零開發的嵌入式系統,需要構建者自己來編譯這個工具。
恰好我們就是自己構建的內核,所以應用程序都需要自己構建。
最新的是5.0,ok我們就使用這個最新的來構建這個工具。
這裏給出源碼地址,可以直接克隆下來源碼構建。
https://github.com/strace/strace
克隆下來
構建配置,查看下面的configure裏面的介紹,如果是工具的使用,就查看 README-linux-ptrace
生成自動配置文件 configure
./bootstrap
我這邊系統報錯,說是找不到autoconf
那就先安裝自動配置文件
sudo apt-get install automake
繼續生成配置文件
./bootstrap
自動配置成功
配置
./configure --host=arm-none-linux-gnueabi CC=arm-none-linux-gnueabi-gcc
配置成功
編譯
make
下面表示編譯成功
生成的應用程序
拷貝我們自己的arm開發板所在的文件系統上
下面我們以一個簡單的例子爲例來使用一下這個工具
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int fd = 0;
char buf[] = "You're a good man!\n";
int len = 0;
/*
* 創建一個文件
*/
fd = open("file.txt", O_CREAT|O_RDWR);
if(fd < 0) {
perror("open fail\n");
exit(1);
}
/*
* 寫入一段字符串
*/
len = strlen(buf);
if(write(fd, buf, len) < len) {
perror("write fail\n");
exit(1);
}
/*
* 關閉文件
*/
close(fd);
return 0;
}
關於這個工具的使用,我們可以直接使用幫助文檔。
可以看到,這個工具的用法非常多,這裏我們以最簡單的一種用法爲例來說一下它的使用。
-o + file,表示把這個程序的結果輸出到file文件中。
可以看一下我們上面這個應用程序中,系統調用的一些輸出結果。
剛打來文件,前面的都是一些頭文件包含中的系統調用的結果。
一般我們不關係,我們只關心我們自己的應用程序的結果。
所以直接看輸出信息的後面。
可以看到,我們這個app中系統調用的順序,以及輸出輸出的參數。
比如open的返回值爲3,表示文件描述符標號是3.
write返回值19,表示成功寫入19個字符。
新創建的文件權限爲063440,這個權限可以通過下表查看。
也可c參數,來查看各個系統調用在整個應用中的佔用時間百分比,已經具體時間。
strace -c -o log.txt ./create_file
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
52.00 0.002064 108 19 16 open
18.47 0.000733 48 15 15 stat64
10.86 0.000431 61 7 mmap2
4.54 0.000180 60 3 close
4.54 0.000180 45 4 mprotect
2.27 0.000090 90 1 write
2.19 0.000087 43 2 fstat64
2.12 0.000084 42 2 read
1.69 0.000067 67 1 1 access
0.53 0.000021 21 1 uname
0.40 0.000016 16 1 brk
0.40 0.000016 16 1 set_tls
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.003969 58 32 total
一般通過strace + -c參數,可以判斷程序的具體性能,以便確定是否需要優化,以及優化的目標。
也可以查看某個shell命令的調用方式,比如
strace cat log.txt
execve("/bin/cat", ["cat", "log.txt"], 0x7ede9e74 /* 10 vars */) = 0
uname({sysname="Linux", nodename="linux", ...}) = 0
brk(NULL) = 0x206000
brk(0x206d20) = 0x206d20
set_tls(0x2064c0) = 0
brk(0x227d20) = 0x227d20
brk(0x228000) = 0x228000
getuid32() = 0
open("log.txt", O_RDONLY|O_LARGEFILE) = 3
sendfile64(1, 3, NULL, 16777216% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
52.00 0.002064 108 19 16 open
18.47 0.000733 48 15 15 stat64
10.86 0.000431 61 7 mmap2
4.54 0.000180 60 3 close
4.54 0.000180 45 4 mprotect
2.27 0.000090 90 1 write
2.19 0.000087 43 2 fstat64
2.12 0.000084 42 2 read
1.69 0.000067 67 1 1 access
0.53 0.000021 21 1 uname
0.40 0.000016 16 1 brk
0.40 0.000016 16 1 set_tls
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.003969 58 32 total
) = 999
sendfile64(1, 3, NULL, 16777216) = 0
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
[root@linux]/app#
當然 本節只是簡單的說一下這個工具的使用,後面章節項目應用程序部分,會直接使用這個工具來做調試。