linux-系统调用01-strace工具的使用

来源:互联网 发布:手机淘宝买东西流程 编辑:程序博客网 时间:2024/06/05 15:27

1 简介:
strace程序截取程序发出的系统调用并且显示它们以供查看。

2.真实使用实例
在嵌入式串口编程中,有时候某些函数没有集成在所使用的库中。例如tcdrain函数没有集成在某些soc的芯片中。首先在linux系统中编写包含有tcdrain函数的小程序test.c,编译成可执行文件test,使用strace ./test

3 strace的基本使用方法

注: find .|xargs grep -ri “tcdrain” 在当前目录及其子目录搜索“包含有tcdrain字符串的文件”这个命令个工具也是linux系统下搜索字符串的大刀,有时候很有用处–不妨可以记录下,以待后用哦。

root@ubuntu-core:/home# find .|xargs grep -ri “tcdrain”
…..
Binary file ./test/tcdrain matches
./test/tcdrain.c: tcdrain(fd);
…..
root@ubuntu-core:/home/test# cat tcdrain.c

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <unistd.h>int main(){    int  fd = open("/dev/ttyS3",O_RDWR);    write(fd,"hello",5);    tcdrain(fd);    return 0;}

root@ubuntu-core:/home/test#
root@ubuntu-core:/home/test# gcc -o tcdrain tcdrain.c
root@ubuntu-core:/home/test# strace ./tcdrain
execve(“./tcdrain”, [“./tcdrain”], [/* 46 vars */]) = 0 //shell使用execve加载可执行程序
brk(0) = 0xde4000
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdde8fbd000
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=119536, …}) = 0
mmap(NULL, 119536, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fdde8f9f000
close(3) = 0
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
open(“/lib/x86_64-linux-gnu/libc.so.6”, O_RDONLY|O_CLOEXEC) = 3
read(3, “\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200\30\2\0\0\0\0\0”…, 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1815224, …}) = 0
mmap(NULL, 3929304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fdde89dd000
mprotect(0x7fdde8b92000, 2097152, PROT_NONE) = 0
mmap(0x7fdde8d92000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b5000) = 0x7fdde8d92000
mmap(0x7fdde8d98000, 17624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fdde8d98000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdde8f9e000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdde8f9d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdde8f9c000
arch_prctl(ARCH_SET_FS, 0x7fdde8f9d700) = 0
mprotect(0x7fdde8d92000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7fdde8fbf000, 4096, PROT_READ) = 0
munmap(0x7fdde8f9f000, 119536) = 0
open(“/dev/ttyS3”, O_RDWR) = 3
write(3, “hello”, 5) = -1 EIO (Input/output error)
ioctl(3, TCSBRK, 0x1) = 0 //从这里可以看出,tcdrain函数可以使用ioctl替换
exit_group(0) = ?
root@ubuntu-core:/home/test#

4 使用-c参数
在程序执行之后创建一个报告,概述发出的所有系统调用,以及每个系统调用发费的时间,以及调用出错计数。
root@ubuntu-core:/home/test# strace -c ./tcdrain
% time seconds usecs/call calls errors syscall


-nan 0.000000 0 1 read
-nan 0.000000 0 1 1 write
-nan 0.000000 0 3 open
-nan 0.000000 0 2 close
-nan 0.000000 0 2 fstat
-nan 0.000000 0 8 mmap
-nan 0.000000 0 4 mprotect
-nan 0.000000 0 1 munmap
-nan 0.000000 0 1 brk
-nan 0.000000 0 1 ioctl
-nan 0.000000 0 3 3 access
-nan 0.000000 0 1 execve
-nan 0.000000 0 1 arch_prctl


100.00 0.000000 29 4 total
root@ubuntu-core:/home/test#

5 strace的参数
-c
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
root@ubuntu-core:/home/test# strace –help
strace: invalid option – ‘-’
usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] … [-o file]
[-p pid] … [-s strsize] [-u username] [-E var=val] …
[command [arg …]]
or: strace -c -D [-e expr] … [-O overhead] [-S sortby] [-E var=val] …
[command [arg …]]
-c – count time, calls, and errors for each syscall and report summary
统计每一系统调用的所执行的时间,次数和出错的次数等.

-f – follow forks, -ff – with output into separate files
跟踪由fork调用所产生的子进程. -ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.

-F – attempt to follow vforks,
-h – print help message
-i – print instruction pointer at time of syscall
输出系统调用的入口指针
-q – suppress messages about attaching, detaching, etc.
-r – print relative timestamp,-t – absolute timestamp,
-tt – with usecs
-T – print time spent in each syscall, -V – print version
-v – verbose mode: print unabbreviated argv, stat, termio[s], etc. args
-x – print non-ascii strings in hex, -xx – print all strings in hex
-a column – alignment COLUMN for printing syscall results (default 40)
-e expr – a qualifying expression: option=[!]all or option=[!]val1[,val2]…
options: trace, abbrev, verbose, raw, signal, read, or write
指定输出的过滤表达式
-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
输出从指定文件中读出 的数据.例如:
-e read=3,5
-e write=set
输出写入到指定文件中的数据

-o file – send trace output to FILE instead of stderr
-O overhead – set overhead for tracing syscalls to OVERHEAD usecs
-p pid – trace process with process id PID, may be repeated
跟踪指定的进程pid

-D – run tracer process as a detached grandchild, not as parent
-s strsize – limit length of print strings to STRSIZE chars (default 32)
-S sortby – sort syscall counts by: time, calls, name, nothing (default time)
-u username – run command as username handling setuid and/or setgid
-E var=val – put var=val in the environment for command
-E var – remove var from the environment for command
root@ubuntu-core:/home/test#

6.常用方式
<1>.输出信息到文件
root@ubuntu-core:/home/test# strace -o test.txt ./tcdrain
root@ubuntu-core:/home/test# ls test.txt
test.txt**
root@ubuntu-core:/home/test#
<2>.使用-c可以查看到发生错误的系统调用
root@ubuntu-core:/home/test# strace -c ./tcdrain
% time seconds usecs/call calls errors syscall


-nan 0.000000 0 1 read
-nan 0.000000 0 1 1 write
-nan 0.000000 0 3 open
-nan 0.000000 0 2 close
-nan 0.000000 0 2 fstat
-nan 0.000000 0 8 mmap
-nan 0.000000 0 4 mprotect
-nan 0.000000 0 1 munmap
-nan 0.000000 0 1 brk
-nan 0.000000 0 1 ioctl
-nan 0.000000 0 3 3 access
-nan 0.000000 0 1 execve
-nan 0.000000 0 1 arch_prctl


100.00 0.000000 29 4 total
root@ubuntu-core:/home/test#

<3>.挑选查看的系统调用(筛选错误的系统调用,是怎么回事)
root@ubuntu-core:/home/test# strace -e trace=open,write ./tcdrain
open(“/etc/ld.so.cache”, O_RDONLY|O_CLOEXEC) = 3
open(“/lib/x86_64-linux-gnu/libc.so.6”, O_RDONLY|O_CLOEXEC) = 3
open(“/dev/ttyS3”, O_RDWR) = 3
write(3, “hello”, 5) = -1 EIO (Input/output error)
root@ubuntu-core:/home/test#

<4>.附加到正在运行的程序
root@ubuntu-core:/home/test# cat tcdrain.c

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <unistd.h>int main(){    int  fd = open("/dev/ttyS3",O_RDWR);    write(fd,"hello",5);    sleep(10);    tcdrain(fd);    return 0;}

root@ubuntu-core:/home/test#
root@ubuntu-core:/home/test# ./tcdrain &
[1] 2641
root@ubuntu-core:/home/test# strace -p 2641
Process 2641 attached - interrupt to quit
restart_syscall(<… resuming interrupted call …>) = 0
ioctl(3, TCSBRK, 0x1) = 0
exit_group(0) = ?
Process 2641 detached
[1]+ Done ./tcdrain


strace入门,更多的学习,需要man+练习+结合工作只需。see you!

0 0