< | 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 | > |