Posix
如何測試應用程序正在使用 POSIX 的哪些部分?
我已經獲得了 C 語言的原始碼,並且想查看其中使用了 POSIX 的哪些部分(函式、系統呼叫)。
是否有測試套件或其他程序,可以給我一個概述?
strace
跟踪系統呼叫。POSIX 包括系統呼叫和函式。一些平台支持類似的ltrace
(跟踪庫呼叫)。例如,
date
命令行實用程序ltrace
將顯示如下內容:__libc_start_main(0x401a50, 1, 0x7ffe41310418, 0x40a100, 0x40a0f0 <unfinished ...> strrchr("date", '/') = NULL setlocale(6, "") = "en_US.UTF-8" bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale" textdomain("coreutils") = "coreutils" __cxa_atexit(0x402b60, 0, 0, 0x736c6974756572, 0x7f8c29d9bea8) = 0 getenv("POSIXLY_CORRECT") = NULL nl_langinfo(131180, 0x40b6b9, 0, 0, 0) = 0x7f8c23e98955 clock_gettime(0, 0x7ffe41310260, 0x20ef440, 0, 0) = 0 localtime(0x7ffe413101d0) = 0x7f8c29d9f380 strftime("", 140239874654731, NULL, 0x7ffe4130fd63) = 4 fwrite("Mon", 3, 1, 0x7f8c29d9a7a0) = 1 fputc(' ', 0x7f8c29d9a7a0) = 32 strftime("", 140239874654844, NULL, 0x7ffe4130fd63) = 4 fwrite("Sep", 3, 1, 0x7f8c29d9a7a0) = 1 fputc(' ', 0x7f8c29d9a7a0) = 32 fwrite("12\004\200\0011A\376\177", 2, 1, 0x7f8c29d9a7a0) = 1 fputc(' ', 0x7f8c29d9a7a0) = 32 fwrite("17\004\200\0011A\376\177", 2, 1, 0x7f8c29d9a7a0) = 1 fputc(':', 0x7f8c29d9a7a0) = 58 fwrite("43\004\200\0011A\376\177", 2, 1, 0x7f8c29d9a7a0) = 1 fputc(':', 0x7f8c29d9a7a0) = 58 fwrite("52\004\200\0011A\376\177", 2, 1, 0x7f8c29d9a7a0) = 1 fputc(' ', 0x7f8c29d9a7a0) = 32 strlen("EDT") = 3 fwrite("EDT", 3, 1, 0x7f8c29d9a7a0) = 1 fputc(' ', 0x7f8c29d9a7a0) = 32 fwrite("2016\004\200\0011A\376\177", 4, 1, 0x7f8c29d9a7a0) = 1 __overflow(0x7f8c29d9a7a0, 10, 4, 54, 0x7f8c2a1c401c) = 10 exit(0 <unfinished ...> ...
而
strace
顯示不同的東西:execve("/bin/date", ["date"], [/* 60 vars */]) = 0 brk(0) = 0x1ac9000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff3eed91000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=132177, ...}) = 0 mmap(NULL, 132177, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff3eed70000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220!\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0644, st_size=31744, ...}) = 0 mmap(NULL, 2128856, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff3ee96c000 mprotect(0x7ff3ee973000, 2093056, PROT_NONE) = 0 mmap(0x7ff3eeb72000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7ff3eeb72000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\357\1\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1607696, ...}) = 0 mmap(NULL, 3721272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff3ee5df000 mprotect(0x7ff3ee763000, 2093056, PROT_NONE) = 0 mmap(0x7ff3ee962000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x183000) = 0x7ff3ee962000 mmap(0x7ff3ee967000, 18488, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ff3ee967000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\\\0\0\0\0\0\0"..., 832) = 832 ...
對於這兩種情況,我只給出了一個樣本。但是,如果您要比較兩條完整的軌跡,您將不會看到兩者之間有太大的相關性。這並不總是正確的:執行 I/O 的函式可以在兩者之間相當接近地匹配。但是只有日誌的最後才
strace
顯示可以與ltrace
日誌匹配的任何 I/O。所有這些fwrite
和fputc
呼叫都會在記憶體中工作,直到最後的write
系統呼叫:open("/usr/lib/locale/locale-archive", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=110939968, ...}) = 0 mmap(NULL, 110939968, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff3e79f6000 close(3) open("/etc/localtime", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0 fstat(3, {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff3eed90000 read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0\0"..., 4096) = 3519 lseek(3, -2252, SEEK_CUR) = 1267 read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\5\0\0\0\5\0\0\0\0"..., 4096) = 2252 close(3) = 0 munmap(0x7ff3eed90000, 4096) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff3eed90000 write(1, "Mon Sep 12 17:43:41 EDT 2016\n", 29) = 29 close(1) = 0 munmap(0x7ff3eed90000, 4096) = 0 close(2) = 0 exit_group(0) = ?
在這兩個跟踪中,以下劃線開頭的名稱肯定是非 POSIX。其他一些也是特定於實現的,例如
exit_group
呼叫。如果您沒有應用程序的原始碼並且只能觀察二進製文件,則沒有可行的方法來改進這種方法。POSIX 基於使用應用程序原始碼的各種功能。例如,一些特性依賴於編譯應用程序的系統標頭檔,而其他特性依賴於命令行實用程序的行為。POSIX 認證測試使用給定原始碼的應用程序的可觀察行為,使用標準介面。內部細節可能不同,這些是 strace/ltrace 向您顯示的內容,如
exit_group
.進一步閱讀:
如果您可以編譯和執行程式碼,並且如果查看 sys 呼叫它的內容就足夠了(即您可以練習您需要了解的所有內容),那麼
strace myapp
將執行
myapp
並列出它所做的所有系統呼叫(POSIX 和其他)。