strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序。
在Linux系统中,用户程序运行在一个沙箱(sandbox)里,用户进程不能直接访问计算机硬件设备。当进程需要访问硬件设备(如读取磁盘文件或接收网络数据等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可跟踪进程产生的系统调用,包括参数、返回值和执行所消耗的时间。若strace没有任何输出,并不代表此时进程发生阻塞;也可能程序进程正在自己的沙箱里执行某些不需要与系统其它部分发生通信的事情。strace从内核接收信息,且无需以任何特殊方式来构建内核。
当然它还可以做更多的事情:
strace可以过筛选出特定的系统调用。
strace可以记录系统调用的次数,时间,成功和失败的次数。
strace可以跟踪发给进程的信号。
strace可以通过pid附加到任何正在运行的进程上。
strace类似其他Unix系统上的truss,或者Sun's Dtrace
对于成熟的服务器或者桌面系统,strace是已经集成好的一个应用,对于从零开发的嵌入式系统,需要构建者自己来编译这个工具。恰好我们就是自己构建的内核,所以应用程序都需要自己构建。
strace 源码下载链接 https://github.com/strace/strace
我这里直接从Ubuntu上使用 git 下载,Windows下下载再传输到Ubuntu上不能使用(有一些文件被破坏了)。
./bootstrap
./configure --host=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc
make
cp strace ./../../rootfs/bin/
下面我们以一个简单的例子为例来使用一下这个工具
#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_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;
}
关于这个工具的使用,我们可以直接使用帮助文档。
Usage: strace [-ACdffhiqqrtttTvVwxxyyzZ] [-I N] [-b execve] [-e EXPR]...
[-a COLUMN] [-o FILE] [-s STRSIZE] [-X FORMAT] [-O OVERHEAD]
[-S SORTBY] [-P PATH]... [-p PID]... [-U COLUMNS] [--seccomp-bpf]
{ -p PID | [-DDD] [-E VAR=VAL]... [-u USERNAME] PROG [ARGS] }
or: strace -c[dfwzZ] [-I N] [-b execve] [-e EXPR]... [-O OVERHEAD]
[-S SORTBY] [-P PATH]... [-p PID]... [-U COLUMNS] [--seccomp-bpf]
{ -p PID | [-DDD] [-E VAR=VAL]... [-u USERNAME] PROG [ARGS] }
General:
-e EXPR a qualifying expression: OPTION=[!]all or OPTION=[!]VAL1[,VAL2]...
options: trace, abbrev, verbose, raw, signal, read, write, fault,
inject, status, quiet, kvm, decode-fds
Startup:
-E VAR=VAL, --env=VAR=VAL
put VAR=VAL in the environment for command
-E VAR, --env=VAR
remove VAR from the environment for command
-p PID, --attach=PID
trace process with process id PID, may be repeated
-u USERNAME, --user=USERNAME
run command as USERNAME handling setuid and/or setgid
Tracing:
-b execve, --detach-on=execve
detach on execve syscall
-D, --daemonize[=grandchild]
run tracer process as a grandchild, not as a parent
-DD, --daemonize=pgroup
run tracer process in a separate process group
-DDD, --daemonize=session
run tracer process in a separate session
-f, --follow-forks
follow forks
-ff, --follow-forks --output-separately
follow forks with output into separate files
-I INTERRUPTIBLE, --interruptible=INTERRUPTIBLE
1, anywhere: no signals are blocked
2, waiting: fatal signals are blocked while decoding syscall (default)
3, never: fatal signals are always blocked (default if '-o FILE PROG')
4, never_tstp: fatal signals and SIGTSTP (^Z) are always blocked
(useful to make 'strace -o FILE PROG' not stop on ^Z)
Filtering:
-e trace=[!]{[?]SYSCALL[@64|@32|@x32]|[?]/REGEX|GROUP|all|none},
--trace=[!]{[?]SYSCALL[@64|@32|@x32]|[?]/REGEX|GROUP|all|none}
trace only specified syscalls.
groups: %clock, %creds, %desc, %file, %fstat, %fstatfs %ipc, %lstat,
%memory, %net, %process, %pure, %signal, %stat, %%stat,
%statfs, %%statfs
-e signal=SET, --signal=SET
trace only the specified set of signals
print only the signals from SET
-e status=SET, --status=SET
print only system calls with the return statuses in SET
statuses: successful, failed, unfinished, unavailable, detached
-P PATH, --trace-path=PATH
trace accesses to PATH
-z, --successful-only
print only syscalls that returned without an error code
-Z, --failed-only
print only syscalls that returned with an error code
Output format:
-a COLUMN, --columns=COLUMN
alignment COLUMN for printing syscall results (default 40)
-e abbrev=SET, --abbrev=SET
abbreviate output for the syscalls in SET
-e verbose=SET, --verbose=SET
dereference structures for the syscall in SET
-e raw=SET, --raw=SET
print undecoded arguments for the syscalls in SET
-e read=SET, --read=SET
dump the data read from the file descriptors in SET
-e write=SET, --write=SET
dump the data written to the file descriptors in SET
-e quiet=SET, --quiet=SET
suppress various informational messages
messages: attach, exit, path-resolution, personality, thread-execve
-e kvm=vcpu, --kvm=vcpu
print exit reason of kvm vcpu
-e decode-fds=SET, --decode-fds=SET
what kinds of file descriptor information details to decode
details: dev (device major/minor for block/char device files)
path (file path),
pidfd (associated PID for pidfds),
socket (protocol-specific information for socket descriptors)
-i, --instruction-pointer
print instruction pointer at time of syscall
-n, --syscall-number
print syscall number
-o FILE, --output=FILE
send trace output to FILE instead of stderr
-A, --output-append-mode
open the file provided in the -o option in append mode
--output-separately
output into separate files (by appending pid to file names)
-q, --quiet=attach,personality
suppress messages about attaching, detaching, etc.
-qq, --quiet=attach,personality,exit
suppress messages about process exit status as well.
-qqq, --quiet=all
suppress all suppressible messages.
-r, --relative-timestamps[=PRECISION]
print relative timestamp
precision: one of s, ms, us, ns; default is microseconds
-s STRSIZE, --string-limit=STRSIZE
limit length of print strings to STRSIZE chars (default 32)
--absolute-timestamps=[[format:]FORMAT[,[precision:]PRECISION]]
set the format of absolute timestamps
format: none, time, or unix; default is time
precision: one of s, ms, us, ns; default is seconds
-t, --absolute-timestamps[=time]
print absolute timestamp
-tt, --absolute-timestamps=[time,]us
print absolute timestamp with usecs
-ttt, --absolute-timestamps=unix,us
print absolute UNIX time with usecs
-T, --syscall-times[=PRECISION]
print time spent in each syscall
precision: one of s, ms, us, ns; default is microseconds
-v, --no-abbrev
verbose mode: print entities unabbreviated
-x, --strings-in-hex=non-ascii
print non-ascii strings in hex
-xx, --strings-in-hex[=all]
print all strings in hex
-X FORMAT, --const-print-style=FORMAT
set the FORMAT for printing of named constants and flags
formats: raw, abbrev, verbose
-y, --decode-fds[=path]
print paths associated with file descriptor arguments
-yy, --decode-fds=all
print all available information associated with file
descriptors in addition to paths
Statistics:
-c, --summary-only
count time, calls, and errors for each syscall and report
summary
-C, --summary like -c, but also print the regular output
-O OVERHEAD[UNIT], --summary-syscall-overhead=OVERHEAD[UNIT]
set overhead for tracing syscalls to OVERHEAD UNITs
units: one of s, ms, us, ns; default is microseconds
-S SORTBY, --summary-sort-by=SORTBY
sort syscall counts by: time, min-time, max-time, avg-time,
calls, errors, name, nothing (default time)
-U COLUMNS, --summary-columns=COLUMNS
show specific columns in the summary report: comma-separated
list of time-percent, total-time, min-time, max-time,
avg-time, calls, errors, name
(default time-percent,total-time,avg-time,calls,errors,name)
-w, --summary-wall-clock
summarise syscall latency (default is system time)
Tampering:
-e inject=SET[:error=ERRNO|:retval=VALUE][:signal=SIG][:syscall=SYSCALL]
[:delay_enter=DELAY][:delay_exit=DELAY][:when=WHEN],
--inject=SET[:error=ERRNO|:retval=VALUE][:signal=SIG][:syscall=SYSCALL]
[:delay_enter=DELAY][:delay_exit=DELAY][:when=WHEN]
perform syscall tampering for the syscalls in SET
delay: microseconds or NUMBER{s|ms|us|ns}
when: FIRST[..LAST][+[STEP]]
-e fault=SET[:error=ERRNO][:when=WHEN], --fault=SET[:error=ERRNO][:when=WHEN]
synonym for -e inject with default ERRNO set to ENOSYS.
Miscellaneous:
-d, --debug enable debug output to stderr
-h, --help print help message
--seccomp-bpf enable seccomp-bpf filtering
-V, --version print version
[root@IMX6ULL]#
可以看到,这个工具的用法非常多,这里我们以最简单的一种用法为例来说一下它的使用。
-o + file,表示把这个程序的结果输出到file文件中。
可以看一下我们上面这个应用程序中,系统调用的一些输出结果。
[root@IMX6ULLwork]#cat log1.txt
execve("./test", ["./test"], 0x7ea3fd68 /* 17 vars */) = 0
brk(NULL) = 0x18fe000
uname({sysname="Linux", nodename="IMX6ULL", ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f04000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/vfp", 0x7ebe5418) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0]d\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=8802547, ...}) = 0
mmap2(NULL, 976272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76def000
mprotect(0x76ec8000, 65536, PROT_NONE) = 0
mmap2(0x76ed8000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd9000) = 0x76ed8000
mmap2(0x76edb000, 9616, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76edb000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f03000
set_tls(0x76f034c0) = 0
mprotect(0x76ed8000, 8192, PROT_READ) = 0
mprotect(0x76f05000, 4096, PROT_READ) = 0
open("file.txt", O_RDWR) = 3
write(3, "You're a good man!\n", 19) = 19
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
[root@IMX6ULLwork]#
可以看到,我们这个app中系统调用的顺序,以及输出输出的参数。
比如open的返回值为3,表示文件描述符标号是3.
write返回值19,表示成功写入19个字符。
新创建的文件权限为063440,这个权限可以通过下表查看。
也可c参数,来查看各个系统调用在整个应用中的占用时间百分比,已经具体时间。
[root@IMX6ULLwork]#strace -c -o log1.txt ./test
[root@IMX6ULLwork]#cat log1.txt
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 1 read
0.00 0.000000 0 1 write
0.00 0.000000 0 33 31 open
0.00 0.000000 0 2 close
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 brk
0.00 0.000000 0 1 uname
0.00 0.000000 0 3 mprotect
0.00 0.000000 0 5 mmap2
0.00 0.000000 0 15 15 stat64
0.00 0.000000 0 1 fstat64
0.00 0.000000 0 1 set_tls
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 0 66 47 total
[root@IMX6ULLwork]#
一般通过strace + -c参数,可以判断程序的具体性能,以便确定是否需要优化,以及优化的目标。
也可以查看某个shell命令的调用方式,比如
strace cat log1.txt
[root@IMX6ULLwork]#strace cat log1.txt
execve("/bin/cat", ["cat", "log1.txt"], 0x7efccd74 /* 17 vars */) = 0
brk(NULL) = 0x1b43000
uname({sysname="Linux", nodename="IMX6ULL", ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fad000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/tls/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/v7l/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/neon/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/neon/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/neon", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/vfp/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/lib/vfp", 0x7ee97418) = -1 ENOENT (No such file or directory)
open("/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0h<\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1510945, ...}) = 0
mmap2(NULL, 471184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76f13000
mprotect(0x76f76000, 61440, PROT_NONE) = 0
mmap2(0x76f85000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x62000) = 0x76f85000
close(3) = 0
open("tls/v7l/neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libresolv.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0@%\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=307572, ...}) = 0
mmap2(NULL, 133044, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76ef2000
mprotect(0x76eff000, 65536, PROT_NONE) = 0
mmap2(0x76f0f000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd000) = 0x76f0f000
mmap2(0x76f11000, 6068, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76f11000
close(3) = 0
open("tls/v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("v7l/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("neon/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("vfp/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0]d\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=8802547, ...}) = 0
mmap2(NULL, 976272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76e03000
mprotect(0x76edc000, 65536, PROT_NONE) = 0
mmap2(0x76eec000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd9000) = 0x76eec000
mmap2(0x76eef000, 9616, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76eef000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fac000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fab000
set_tls(0x76fab4c0) = 0
mprotect(0x76eec000, 8192, PROT_READ) = 0
mprotect(0x76f0f000, 4096, PROT_READ) = 0
mprotect(0x76f85000, 4096, PROT_READ) = 0
mprotect(0x76fae000, 4096, PROT_READ) = 0
getuid32() = 0
open("log1.txt", O_RDONLY|O_LARGEFILE) = 3
sendfile64(1, 3, NULL, 16777216% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 1 read
0.00 0.000000 0 1 write
0.00 0.000000 0 33 31 open
0.00 0.000000 0 2 close
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 brk
0.00 0.000000 0 1 uname
0.00 0.000000 0 3 mprotect
0.00 0.000000 0 5 mmap2
0.00 0.000000 0 15 15 stat64
0.00 0.000000 0 1 fstat64
0.00 0.000000 0 1 set_tls
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 0 66 47 total
) = 999
sendfile64(1, 3, NULL, 16777216) = 0
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
[root@IMX6ULLwork]#
当然 本节只是简单的说一下这个工具的使用,后面章节项目应用程序部分,会直接使用这个工具来做调试。
参考文章
[Pthread] Linux上程序调试的基石(一)--ptrace
[Pthread] Linux程序调试的基石(二)--Inside GDB