除錯跟蹤利器---strace
通過這篇文章你會學習到strace的用法,strace可以幫助你高效地定位程式中的一些錯誤,關於strace的用處有很多,可以自行發掘
前面我們講解了gdb除錯程式,這篇文章介紹另一個除錯跟蹤工具strace,同樣你可以在linux下執行man strace檢視幫助資訊
(一)starce是什麼
我們直接看man列印的幫助資訊
strace - trace system calls and signals
根據上面的描述我們可以知道strace主要是跟蹤系統的呼叫和訊號的傳遞,其實我們還可以用它來監視使用者程式和核心的互動,它能通過系統呼叫來偵測程式執行的詳細過程
在Linux世界,程式不能直接訪問硬體裝置,當程式需要訪問硬體裝置(比如讀取磁碟檔案,接收網路資料等等)時,必須由使用者態模式切換至核心態模式,通 過系統呼叫訪問硬體裝置。strace可以跟蹤到一個程式產生的系統呼叫,包括引數,返回值,執行消耗的時間。
(二)strace如何使用
引數 | 引數說明 |
---|---|
-c | 統計每一系統呼叫的所執行的時間,次數和出錯的次數等. |
-d | 輸出strace關於標準錯誤的除錯資訊. |
-f | 跟蹤由fork呼叫所產生的子程式. |
-ff | 如果提供-o filename,則所有程式的跟蹤結果輸出到相應的filename.pid中,pid是各程式的程式號. |
-F | 嘗試跟蹤vfork呼叫.在-f時,vfork不被跟蹤. |
-h | 輸出簡要的幫助資訊. |
-i | 輸出系統呼叫的入口指標. |
-q | 禁止輸出關於脫離的訊息. |
-r | 列印出相對時間關於,每一個系統呼叫. |
-t | 在輸出中的每一行前加上時間資訊. |
-tt | 在輸出中的每一行前加上時間資訊,微秒級. |
-ttt | 微秒級輸出,以秒了表示時間. |
-T | 顯示每一呼叫所耗的時間. |
-v | 輸出所有的系統呼叫.一些呼叫關於環境變數,狀態,輸入輸出等呼叫由於使用頻繁,預設不輸出. |
-V | 輸出strace的版本資訊. |
-x | 以十六進位制形式輸出非標準字串 |
-xx | 所有字串以十六進位制形式輸出. |
-e expr :指定一個表示式,用來控制如何跟蹤,由於格式比較多我們單獨拿出來
格式如下:
[qualifier=][!]value1[,value2]...
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用來限定的符號或數字.預設的 qualifier是 trace.感嘆號是否定符號.
-e expr | 引數設定 |
---|---|
-e trace=set | 只跟蹤指定的系統 呼叫.例如:-e trace=open,close,rean,write表示只跟蹤這四個系統呼叫.預設的為set=all. |
-e trace=file | 只跟蹤有關檔案操作的系統呼叫. |
-e trace=process | 只跟蹤有關程式控制的系統呼叫. |
-e trace=network | 跟蹤與網路有關的所有系統呼叫. |
-e strace=signal | 跟蹤所有與系統訊號有關的 系統呼叫 |
-e trace=ipc | 跟蹤所有與程式通訊有關的系統呼叫 |
-e abbrev=set | 設定 strace輸出的系統呼叫的結果集.-v 等與 abbrev=none.預設為abbrev=all. |
-e raw=set | 將指 定的系統呼叫的引數以十六進位制顯示. |
-e signal=set | 指定跟蹤的系統訊號.預設為all.如 signal=!SIGIO(或者signal=!io),表示不跟蹤SIGIO訊號. |
-e read=set | 輸出從指定檔案中讀出 的資料.例如: |
-o filename | 將strace的輸出寫入檔案filename |
-p pid | 跟蹤指定的程式pid. |
-s strsize | 指定輸出的字串的最大長度.預設為32.檔名一直全部輸出. |
-u username | 以username 的UID和GID執行被跟蹤的命令 |
示例:
(1)根據指定pid程式跟蹤
strace -o output.txt -T -tt -e trace=all -p 28979
上面的含義是 跟蹤28979程式的所有系統呼叫(-e trace=all),並統計系統呼叫的花費時間,以及開始時間(並以視覺化的時分秒格式顯示),最後將記錄結果存在output.txt檔案裡面。
(2)根據程式名跟蹤
strace -o output.txt -T -tt -e trace=all ./a.out
(三)strace的一個分析例項
test.c
#include <stdio.h>
#include <unistd.h>
int main(int argc,char * argv[])
{
char buff[256]={0};
FILE* file=NULL;
file=fopen(argv[1],"r");
if(file == NULL)
{
printf("fopen error\n");
// return -1;
}
fread(buff,sizeof(buff),1,file);
printf("buff=%s\n",buff);
return 0;
}
我們執行:
gcc test.c -o test
./test
上面我們執行時不輸入任何引數,肯定會報段錯誤
fopen error
段錯誤 (核心已轉儲)
我們這裡使用strace檢視資訊:
root@lvirtual-machine:~/test# strace -T -tt -e trace=all ./test
22:32:53.349314 execve("./test", ["./test"], [/* 60 vars */]) = 0 <0.000440>
22:32:53.350129 brk(NULL) = 0xb3f000 <0.000097>
22:32:53.350417 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000094>
22:32:53.350769 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000062>
22:32:53.351014 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000127>
22:32:53.351316 fstat(3, {st_mode=S_IFREG|0644, st_size=96373, ...}) = 0 <0.000105>
22:32:53.351585 mmap(NULL, 96373, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0bec216000 <0.000065>
22:32:53.351793 close(3) = 0 <0.000052>
22:32:53.352046 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000068>
22:32:53.352313 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000106>
22:32:53.352597 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\t\2\0\0\0\0\0"..., 832) = 832 <0.000061>
22:32:53.352789 fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0 <0.000110>
22:32:53.353092 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0bec215000 <0.000122>
22:32:53.353409 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0bebc3f000 <0.000117>
22:32:53.353629 mprotect(0x7f0bebdff000, 2097152, PROT_NONE) = 0 <0.000115>
22:32:53.353841 mmap(0x7f0bebfff000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f0bebfff000 <0.000110>
22:32:53.354073 mmap(0x7f0bec005000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0bec005000 <0.000060>
22:32:53.354297 close(3) = 0 <0.000035>
22:32:53.354556 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0bec214000 <0.000060>
22:32:53.354736 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0bec213000 <0.000045>
22:32:53.354888 arch_prctl(ARCH_SET_FS, 0x7f0bec214700) = 0 <0.000040>
22:32:53.355125 mprotect(0x7f0bebfff000, 16384, PROT_READ) = 0 <0.000051>
22:32:53.355288 mprotect(0x600000, 4096, PROT_READ) = 0 <0.000050>
22:32:53.355487 mprotect(0x7f0bec22e000, 4096, PROT_READ) = 0 <0.000085>
22:32:53.355724 munmap(0x7f0bec216000, 96373) = 0 <0.000094>
22:32:53.356015 brk(NULL) = 0xb3f000 <0.000072>
22:32:53.356203 brk(0xb60000) = 0xb60000 <0.000075>
22:32:53.356426 open(NULL, O_RDONLY) = -1 EFAULT (Bad address) <0.000078>
22:32:53.356664 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 11), ...}) = 0 <0.000065>
22:32:53.356879 write(1, "fopen error\n", 12fopen error
) = 12 <0.000065>
22:32:53.357116 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
22:32:53.542212 +++ killed by SIGSEGV (core dumped) +++
段錯誤 (核心已轉儲)
上面輸出的資訊非常多,但是我們可以找到我們需要的
open(NULL, O_RDONLY) = -1 EFAULT (Bad address)
我們使用starce也就是根據這些系統呼叫去過濾出我們需要的資訊
當我們發現程式執行異常時,我們可以使用strace來跟蹤其系統呼叫,看看這些系統呼叫有沒有異常,進而找到異常的原因。
相關文章
- [20200219]strace跟蹤設定ENABLE=BROKEN的情況.txt
- git刪除未跟蹤檔案Git
- 除錯利器 Laravel Dump Server除錯LaravelServer
- Laravel除錯利器 Laravel DebugbarLaravel除錯
- Linux命令strace跟蹤程式的系統呼叫-linux學習用什麼書Linux
- [20200219]strace跟蹤設定ENABLE=BROKEN的情況(網路的情況).txt
- 視覺化程式碼跟蹤除錯與STM32應用設計視覺化除錯
- 【LOG】Oracle資料庫清理日誌、跟蹤檔案利器Oracle資料庫
- 記一次除錯YOLOv5+DeepSort車輛跟蹤專案的經過除錯YOLO
- phpstorm+x_debug 網頁除錯利器!PHPORM網頁除錯
- 使用ErrorStack進行錯誤跟蹤及診斷Error
- 利用errorstack事件進行錯誤跟蹤和診斷Error事件
- sp_trace_setfilter sqlserver篩選跟蹤或跟蹤過濾FilterSQLServer
- 主力跟蹤戰法
- 反跟蹤技術
- git的跟蹤分支和遠端跟蹤分支學習筆記Git筆記
- 【ORA-】ORA-12547: TNS:lost contact錯誤的跟蹤分析
- SQLServer進行SQL跟蹤SQLServer
- 會話跟蹤技術會話
- [20190402]跟蹤vmstat.txt
- Linux 跟蹤器之選Linux
- 跟蹤執行命令T
- 像跟蹤分散式服務呼叫那樣跟蹤 Go 函式呼叫鏈分散式Go函式
- 鏈路追蹤 SkyWalking 原始碼分析 —— 除錯環境搭建原始碼除錯
- git 刪除已經新增到git跟蹤的檔案或資料夾Git
- Node 除錯利器,前端、Node 開發必備 - VSCode JS Debug Terminal除錯前端VSCodeJS
- Linux系統程式底層debug除錯及程式原理分析利器Linux除錯
- 在Mac book安裝vscode開發利器ide除錯mysql mhaMacVSCodeIDE除錯MySql
- 移動端除錯痛點?——送你五款前端開發利器除錯前端
- Oracle資料庫跟蹤SQLOracle資料庫SQL
- APT組織跟蹤與溯源APT
- Zipkin — 微服務鏈路跟蹤.微服務
- [20210603]如何跟蹤索引分裂.txt索引
- 模版匹配定位跟蹤原始碼原始碼
- Sleuth服務跟蹤:整合 Logstash
- Git跟蹤與提交檔案Git
- ATC系統跟蹤事項
- .gitignore忽略跟蹤指定檔案Git