W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
有時小問題可以通過觀察用戶空間的應用程序的行為來追蹤. 監(jiān)視程序也有助于建立對驅動正確工作的信心. 例如, 我們能夠對 scull 感到有信心, 在看了它的讀實現(xiàn)如何響應不同數(shù)量數(shù)據(jù)的讀請求之后.
有幾個方法來監(jiān)視用戶空間程序運行. 你可以運行一個調試器來單步過它的函數(shù), 增加打印語句, 或者在 strace 下運行程序. 這里, 我們將討論最后一個技術, 當真正目的是檢查內核代碼時它是最有趣的.
strace 命令時一個有力工具, 顯示所有的用戶空間程序發(fā)出的系統(tǒng)調用. 它不僅顯示調用, 還以符號形式顯示調用的參數(shù)和返回值. 當一個系統(tǒng)調用失敗, 錯誤的符號值(例如, ENOMEM)和對應的字串(Out of memory) 都顯示. strace 有很多命令行選項; 其中最有用的是 -t 來顯示每個調用執(zhí)行的時間, -T 來顯示調用中花費的時間, -e 來限制被跟蹤調用的類型, 以及-o 來重定向輸出到一個文件. 缺省地, strace 打印調用信息到 stderr.
strace 從內核自身獲取信息. 這意味著可以跟蹤一個程序, 不管它是否帶有調試支持編譯(對 gcc 是 -g 選項)以及不管它是否 strip 過. 你也可以連接追蹤到一個運行中的進程, 類似于一個調試器的方式連接到一個運行中的進程并控制它.
跟蹤信息常用來支持發(fā)給應用程序開發(fā)者的故障報告, 但是對內核程序員也是很有價值的. 我們已經看到驅動代碼運行如何響應系統(tǒng)調用; strace 允許我們檢查每個調用的輸入和輸出數(shù)據(jù)的一致性.
例如, 下面的屏幕輸出顯示(大部分)運行命令 strace ls /dev > /dev/scull0 的最后的行:
open("/dev", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|0755, st_size=24576, ...}) = 0
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
getdents64(3, /* 141 entries */, 4096) = 4088
[...]
getdents64(3, /* 0 entries */, 4096) = 0
close(3) = 0
[...]
fstat64(1, {st_mode=S_IFCHR|0664, st_rdev=makedev(254, 0), ...}) = 0
write(1, "MAKEDEV\nadmmidi0\nadmmidi1\nadmmid"..., 4096) = 4000
write(1, "b\nptywc\nptywd\nptywe\nptywf\nptyx0\n"..., 96) = 96
write(1, "b\nptyxc\nptyxd\nptyxe\nptyxf\nptyy0\n"..., 4096) = 3904
write(1, "s17\nvcs18\nvcs19\nvcs2\nvcs20\nvcs21"..., 192) = 192
write(1, "\nvcs47\nvcs48\nvcs49\nvcs5\nvcs50\nvc"..., 673) = 673
close(1) = 0
exit_group(0) = ?
從第一個 write 調用看, 明顯地, 在 ls 結束查看目標目錄后, 它試圖寫 4KB. 奇怪地(對ls), 只有 4000 字節(jié)寫入, 并且操作被重復. 但是, 我們知道 scull 中的寫實現(xiàn)一次寫一個單個量子, 因此我們本來就期望部分寫. 幾步之后, 所有東西清空, 程序成功退出.
作為另一個例子, 讓我們讀取 scull 設備(使用 wc 命令):
[...]
open("/dev/scull0", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFCHR|0664, st_rdev=makedev(254, 0), ...}) = 0
read(3, "MAKEDEV\nadmmidi0\nadmmidi1\nadmmid"..., 16384) = 4000
read(3, "b\nptywc\nptywd\nptywe\nptywf\nptyx0\n"..., 16384) = 4000
read(3, "s17\nvcs18\nvcs19\nvcs2\nvcs20\nvcs21"..., 16384) = 865
read(3, "", 16384) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
write(1, "8865 /dev/scull0\n", 17) = 17
close(3) = 0
exit_group(0) = ?
如同期望的, read 一次只能獲取 4000 字節(jié), 但是數(shù)據(jù)總量等同于前個例子寫入的. 注意在這個例子里讀取是如何組織的, 同前面跟蹤的相反. wc 為快速讀被優(yōu)化過, 因此繞過了標準庫, 試圖一個系統(tǒng)調用讀取更多數(shù)據(jù). 你可從跟蹤的讀的行里看到 wc 是如何試圖一次讀取 16 KB.
Linux 專家能夠從 strace 的輸出中發(fā)現(xiàn)更多有用信息. 如果你不想看到所有的符號, 你可使用 efile 標志來限制你自己僅查看文件方法是如何工作的.
就個人而言, 我們發(fā)現(xiàn) strace 對于查明系統(tǒng)調用的運行時錯誤是非常有用. 常常是應用程序或演示程序中的 perror 調用不足夠詳細, 并且能夠確切說出哪個系統(tǒng)調用的哪個參數(shù)觸發(fā)了錯誤是非常有幫助的.
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: