| < | 1. Wstęp | 2. printk | 3. klogd i syslogd | 5. gdb i UML | 6. kdb i kgdb | > |
strace jest narzędziem pozwalającym badać interakcję dowolnego programu z jądrem systemu operacyjnego. W najprostszym przypadku uruchamia dany program i przechwytuje generowane przez niego wywołania funkcji systemowych oraz sygnały przez niego otrzymywane. Nazwa każdej funkcji, razem z jej argumentami oraz zwracaną wartością są kierowane na wyjście diagnostyczne lub do zadanego pliku (którego nazwę należy podać używając opcji -o), np:
$ strace mkdir tmp
execve("/bin/mkdir", ["mkdir", "tmp"], [/* 29 vars */]) = 0
uname({sys="Linux", node="xubuntu", ...}) = 0
brk(0) = 0x804e000
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f92000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f91000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f90000
open("/etc/ld.so.cache", O_RDONLY) = 3
(...)
W przypadku błędu otrzymuje się informację o jego nazwie symbolicznej wraz z odpowiednim opisem, np:
open("/usr/lib/locale/en_US.UTF-8/LC_NUMERIC", O_RDONLY) = -1 ENOENT (No such file or directory)
ltrace jest narzędziem podobnym, z tą różnicą, że śledzi wywołania funkcji bibliotecznych (l- jak library).
Przykładowe dane, generowane przez
$ ltrace date
wygldają następująco:
__libc_start_main(0x8049505, 1, 0xbfe92424, 0x804fa74, 0x804fac5 <unfinished ...>
setlocale(6, "") = "en_US.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"
textdomain("coreutils") = "coreutils"
__cxa_atexit(0x804bb2d, 0, 0, 0xb7f68adc, 0xbfe92398) = 0
getopt_long(1, 0xbfe92424, "d:f:I::r:Rs:u", 0x804fd00, NULL) = -1
nl_langinfo(131180, 0xbfe92424, 0x804fde0, 0x804fd00, 0) = 0xb7d53915
clock_gettime(0, 0xbfe9237c, 0xbfe92424, 1, 0xbfe92398) = 0
localtime(0xbfe92278) = 0xb7f6c500
strftime(" Tue", 1024, " %a", 0xb7f6c500) = 4
fwrite("Tue", 3, 1, 0xb7f690e0) = 1
(...)
Istotną cechą obu tych narzędzi jest fakt, że do pracy z danym programem nie jest potrzebne posiadanie jego źródeł, nie musi on być również kompilowany w specjalny sposób (np. z opcją -g, jak to ma miejsce w przypadku gdb)
Znaczącą niedogodnocią jest natomiast ilość generowanych danych, która powoduje, że trudno z nich wyłowić istotne informacje - szczególnie w przypadku większych programów. Na przykład
$ strace ls
może generować kilkaset linii komunikatów:
execve("/bin/ls", ["ls"], [/* 29 vars */]) = 0
uname({sys="Linux", node="xubuntu", ...}) = 0
brk(0) = 0x805c000
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f1e000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f1d000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f1c000
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=30762, ...}) = 0
old_mmap(NULL, 30762, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f14000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/librt.so.1", 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\20\36\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=28116, ...}) = 0
...
Dlatego należy pamiętać, że informacje generowane przz strace i ltrace służą przede wszystkim do przeszukiwania, zamiast czytania w całości.
Ze względu na powyższe oraz fakt, że w przypadku wystąpienia błędu informacja o nim jest zwykle mało precyzyjna (może się zdarzyć, że nie wiadomo lub trudno jest ustalić która dokładnie instrukcja wywołała błąd), użyteczność strace i ltrace w debugowaniu jest ograniczona. Narzędzia te przydają się zwykle tam, gdzie ważne jest poznanie interakcji różnych programów z jądrem systemu operacyjnego. Przykładem takiej sytuacji może być program, korzystający z pewnych zewnętrznych plików, ale w przypadku ich braku kończy się bez wyświetlenia odpowiedniej informacji o błędzie. Dzięki strace można wtedy rozpoznać błąd i uzyskac informację o nazwie brakującego pliku.
www.gnome.org/~newren/tutorials/developing-with-gnome/html/ch03.html
strony manuala strace i ltrace
| < | 1. Wstęp | 2. printk | 3. klogd i syslogd | 5. gdb i UML | 6. kdb i kgdb | > |