strace命令使用

命令介紹

strace是Linux環境下的一款程序調試工具,用來輸出一個應用程序所使用的系統調用。

strace底層使用內核的ptrace特性來實現其功能。

什麼是系統調用?

系統調用是通向操作系統本身的接口,是面向底層硬件的。通過系統調用,可以使得用戶態運行的進程與硬件設備(如CPU、磁盤、打印機等)進行交互,是操作系統留給應用程序的一個接口。

常用選項

-t 在每行輸出的前面顯示時間(精確到秒)
-tt 在每行輸出的前面顯示時間(精確到毫秒)
-T 顯示每次系統調用所花費的時間
-v 對於某些相關調用,顯示詳細信息(把完整的環境變量,文件stat結構等打出來)
-f 跟蹤目標進程,以及目標進程創建的所有子進程
-e 指定要跟蹤的系統調用
-o 把strace的輸出寫到文件中
-s 當系統調用的某個參數是字符串時,最多輸出指定長度的內容,默認是32個字節
-p 指定要跟蹤的進程pid, 要同時跟蹤多個pid, 重複多次-p選項即可。
-c 統計每種系統調用所執行的時間,調用次數,出錯次數。

使用

1.追蹤打開文件的系統調用

[root@localhost ~]# strace cat /etc/hosts

execve("/usr/bin/cat", ["cat", "/etc/hosts"], 0x7fff79f5beb8 /* 26 vars */) = 0
brk(NULL)                               = 0x81e000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3cee950000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=20640, ...}) = 0
mmap(NULL, 20640, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3cee94a000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156240, ...}) = 0
mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f3cee362000
mprotect(0x7f3cee525000, 2097152, PROT_NONE) = 0
mmap(0x7f3cee725000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f3cee725000
mmap(0x7f3cee72b000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f3cee72b000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3cee949000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3cee947000
arch_prctl(ARCH_SET_FS, 0x7f3cee947740) = 0
mprotect(0x7f3cee725000, 16384, PROT_READ) = 0
mprotect(0x60b000, 4096, PROT_READ)     = 0
mprotect(0x7f3cee951000, 4096, PROT_READ) = 0
munmap(0x7f3cee94a000, 20640)           = 0
brk(NULL)                               = 0x81e000
brk(0x83f000)                           = 0x83f000
brk(NULL)                               = 0x83f000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106176928, ...}) = 0
mmap(NULL, 106176928, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3ce7e1f000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
open("/etc/hosts", O_RDONLY)            = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=158, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "127.0.0.1   localhost localhost."..., 65536) = 158
write(1, "127.0.0.1   localhost localhost."..., 158127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
) = 158
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

2.顯示系統調用的時間

[root@localhost ~]# strace -tt  -T  cat /etc/hosts

11:25:50.561449 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000023>
11:25:50.561522 fstat(3, {st_mode=S_IFREG|0644, st_size=106176928, ...}) = 0 <0.000013>
11:25:50.561585 mmap(NULL, 106176928, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7ecb038000 <0.000018>
11:25:50.561649 close(3)                = 0 <0.000013>
11:25:50.561830 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 <0.000017>
11:25:50.561908 open("/etc/hosts", O_RDONLY) = 3 <0.000024>
11:25:50.561979 fstat(3, {st_mode=S_IFREG|0644, st_size=158, ...}) = 0 <0.000014>
11:25:50.562046 fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0 <0.000014>
11:25:50.562118 read(3, "127.0.0.1   localhost localhost."..., 65536) = 158 <0.000019>
11:25:50.562183 write(1, "127.0.0.1   localhost localhost."..., 158127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
) = 158 <0.000018>
11:25:50.562244 read(3, "", 65536)      = 0 <0.000014>
11:25:50.562304 close(3)                = 0 <0.000016>
11:25:50.562386 close(1)                = 0 <0.000013>
11:25:50.562443 close(2)                = 0 <0.000012>
# 時間戳                                # 花費的時間

3.跟蹤特定系統調用

-e trace=file 文件相關的調用(參數中有文件名)
-e trace=process 進程管理相關的調用,比如fork/exec/exit_group
-e trace=network 網絡通信相關的調用,比如socket/sendto/connect
-e trace=signal 信號相關的調用,比如kill/sigaction
-e trace=desc 和文件描述符相關,比如write/read/select/epoll等
-e trace=ipc 進程通信相關的調用,比如shmget等

# 跟蹤文件訪問相關係統調用
[root@localhost ~]# strace -e file  cat /etc/hosts
execve("/usr/bin/cat", ["cat", "/etc/hosts"], 0x7fff79c90c58 /* 26 vars */) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/hosts", O_RDONLY)            = 3

4.跟蹤多線程(進程)應用的系統調用

下面是一個多線程demo代碼。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

void* ThreadA(void* par)
{
	while(1)
	 {
	    printf("hello world\n");
	    sleep(1);
	 }
}

int main()
{
	pthread_t t1;
	pthread_create(&t1, NULL, ThreadA, NULL);
	pthread_join(t1, NULL);
	
	return 0;
}

編譯代碼

# gcc demo.c  -o demo -lpthread

開始跟蹤

# strace -ff -o out ./demo

執行完成後得到兩個文件(每個線程一個)

# ls out.*
out.7611  out.7612

主線程 out.7611

mprotect(0x7fa0e4b6e000, 16384, PROT_READ) = 0
mprotect(0x7fa0e4d8f000, 4096, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7fa0e4fb6000, 4096, PROT_READ) = 0
munmap(0x7fa0e4faf000, 20776)           = 0
set_tid_address(0x7fa0e4faca10)         = 7611
set_robust_list(0x7fa0e4faca20, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7fa0e4b7f860, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7fa0e4b88630}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7fa0e4b7f8f0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7fa0e4b88630}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fa0e3faa000
brk(NULL)                               = 0x15c8000
brk(0x15e9000)                          = 0x15e9000
brk(NULL)                               = 0x15e9000
mprotect(0x7fa0e3faa000, 4096, PROT_NONE) = 0
clone(child_stack=0x7fa0e47a9fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fa0e47aa9d0, tls=0x7fa0e47aa700, child_tidptr=0x7fa0e47aa9d0) = 7612
futex(0x7fa0e47aa9d0, FUTEX_WAIT, 7612, NULL) = 0
exit_group(0)                           = ?
+++ exited with 0 +++

工作線程 out.7612

set_robust_list(0x7fa0e47aa9e0, 24)     = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa0e4fb4000
write(1, "hello world\n", 12)           = 12
madvise(0x7fa0e3faa000, 8368128, MADV_DONTNEED) = 0
exit(0)                                 = ?
+++ exited with 0 +++
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章