我们在内核调试的时候,经常想跟踪一下某一个进程的库函数调用或者跟踪每个进程的系统调用,这个时候我们就用到strace和ltrace
ltrace能够跟踪进程的库函数调用,它会显现出哪个库函数被调用,而strace则是跟踪进程的每个系统调用.
下面我们还是用最简单的helloworld说明问题:
#include <stdio.h>
int
main ()
{
printf("Hello world!\n");
return 0;
}
编译:
gcc hello.c -o hello
用ltrace跟踪hello程序,如下:
ltrace ./hello
__libc_start_main(0x80483b4, 1, 0xbfeab574, 0x80483e0, 0x80483d0 <unfinished ...>
puts("Hello World"Hello World
) = 12
+++ exited (status 0) +++
这里我们注意到puts()库函数打印出字符串。puts()这个函数在内核arch/arm/boot/compressed/head.S有实现,另外,puts()这个函数在uboot代码中也有实现,我们的printf,print都是靠puts函数去实现输出的,大家可以看一下。
现在,我们在用strace去跟踪一下hello
strace ./hello
得到
execve("./hello", ["./hello"], [/* 41 vars */]) = 0
brk(0) = 0x9afa000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb785d000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=61532, ...}) = 0
mmap2(NULL, 61532, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb784d000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@n\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1421892, ...}) = 0
mmap2(NULL, 1431976, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x507000
mprotect(0x65e000, 4096, PROT_NONE) = 0
mmap2(0x65f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x157) = 0x65f000
mmap2(0x662000, 10664, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x662000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb784c000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb784c6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x65f000, 8192, PROT_READ) = 0
mprotect(0x8049000, 4096, PROT_READ) = 0
mprotect(0xcda000, 4096, PROT_READ) = 0
munmap(0xb784d000, 61532) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb785c000
write(1, "Hello World\n", 12Hello World
) = 12
exit_group(0) = ?
Linux系统默认分配了3个文件描述符值:0- standard input,1-standard output,2-standard error。
我们看到程序调用write()系统调用做了输出,同时strace还把hello程序运行时所做的系统调用都打印出来了.