目录



运行strace -h可以看到strace的用法
- root@bm1684:/data/chw/bm_det_track# strace -h
- usage: strace [-CdffhiqrtttTvVwxxy] [-I n] [-e expr]...
- [-a column] [-o file] [-s strsize] [-P path]...
- -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
- or: strace -c[dfw] [-I n] [-e expr]... [-O overhead] [-S sortby]
- -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
-
- Output format:
- -a column alignment COLUMN for printing syscall results (default 40)
- -i print instruction pointer at time of syscall
- -o file send trace output to FILE instead of stderr
- -q suppress messages about attaching, detaching, etc.
- -r print relative timestamp
- -s strsize limit length of print strings to STRSIZE chars (default 32)
- -t print absolute timestamp
- -tt print absolute timestamp with usecs
- -T print time spent in each syscall
- -x print non-ascii strings in hex
- -xx print all strings in hex
- -y print paths associated with file descriptor arguments
- -yy print protocol specific information associated with socket file descriptors
-
- Statistics:
- -c count time, calls, and errors for each syscall and report summary
- -C like -c but also print regular output
- -O overhead set overhead for tracing syscalls to OVERHEAD usecs
- -S sortby sort syscall counts by: time, calls, name, nothing (default time)
- -w summarise syscall latency (default is system time)
-
- Filtering:
- -e expr a qualifying expression: option=[!]all or option=[!]val1[,val2]...
- options: trace, abbrev, verbose, raw, signal, read, write, fault
- -P path trace accesses to path
-
- Tracing:
- -b execve detach on execve syscall
- -D run tracer process as a detached grandchild, not as parent
- -f follow forks
- -ff follow forks with output into separate files
- -I interruptible
- 1: no signals are blocked
- 2: fatal signals are blocked while decoding syscall (default)
- 3: fatal signals are always blocked (default if '-o FILE PROG')
- 4: fatal signals and SIGTSTP (^Z) are always blocked
- (useful to make 'strace -o FILE PROG' not stop on ^Z)
-
- Startup:
- -E var remove var from the environment for command
- -E var=val put var=val in the environment for command
- -p pid trace process with process id PID, may be repeated
- -u username run command as username handling setuid and/or setgid
-
- Miscellaneous:
- -d enable debug output to stderr
- -v verbose mode: print unabbreviated argv, stat, termios, etc. args
- -h print help message
- -V print version




我们使用strace跟踪我们前面的驱动测试程序
strace -o log.txt ./firstdrvtest on
得到

前面首先是打开一大堆库,倒数第三行的open是打开这个文件,返回文件描述符3,倒数第二行是把中间的数写到文件fd为3的文件中,写的长度是4个字节。
我们可以看到,strace可以打印出来我们的应用程序调用了哪些系统调用。
如果我们用busybox-1.20,那么我们卸载驱动程序的时候可能会报错,我们用strace来看一下。

然后编译选项里面加上交叉编译前缀,然后使用默认的配置,直接make

编译过程中遇到了一些错误,为了省事直接把报错的命令不编译了,配置项里面把报错的项去掉,编译完之后替换掉之前的busybox.

然后重启开发板,然后装卸、卸载驱动,报错了

我们用strace命令看一下
strace -o log.txt rmmod first_drv

报错没有这么目录,那我们就创建这个目录,

还是报错,那继续strace

那么继续创建目录,错误消失

strace是一个父进程,它会创建一个子进程,子进程就就是对应的应用程序,

我们应用层的open函数本质上就是执行了一个swi指令,然后发生异常进入内核态,

我们到entry-common.S中看一下,然后在entry-common.S中搜索vector_swi
- ENTRY(vector_swi)
- sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - r12} @ Calling r0 - r12
- add r8, sp, #S_PC
- stmdb r8, {sp, lr}^ @ Calling sp, lr
- mrs r8, spsr @ called from non-FIQ mode, so ok.
- str lr, [sp, #S_PC] @ Save calling PC
- str r8, [sp, #S_PSR] @ Save CPSR
- str r0, [sp, #S_OLD_R0] @ Save OLD_R0
- zero_fp
先是保存现场,然后往下看有这个
- stmdb sp!, {r4, r5} @ push fifth and sixth args
- tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
- bne __sys_trace
-
- cmp scno, #NR_syscalls @ check upper syscall limit
- adr lr, ret_fast_syscall @ return address
- ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
里面有个tst ip,测试应用程序是否被跟踪,如果被跟踪就bne __sys_trace
- /*
- * This is the really slow path. We're going to be doing
- * context switches, and waiting for our parent to respond.
- */
- __sys_trace:
- mov r2, scno
- add r1, sp, #S_OFF
- mov r0, #0 @ trace entry [IP = 0]
- bl syscall_trace
然后子进程给父进程发一个信号,然后等待父进程,父进程记录了一些东西之后,然后子进程再继续跑。