dtruss
既是爲DTrace編寫的腳本的典型示例,也是DTrace可以完成的演示。然而,雖然它與truss
或strace
的相似性在相對貧瘠的OS X上是深受歡迎的,但我懷疑dtruss
從來不打算完全替代它們。
在任何情況下,您的問題都有點含糊不清:我不確定您是否擔心您看到的字符串被截斷或者根本沒有看到任何字符串,因爲sendto()
或recvfrom()
(基礎由DTrace顯示的接口)。我會解決這兩個問題。
首先,DTrace在內核中收集數據;在記錄並傳輸回消費者之前,通常使用D語言的copyin()
或copyinstr()
獲得用戶地緩衝區,通常是dtrace(1)
命令。 DTrace要求在編譯時知道其內核緩衝區大小,並因此對字符串的其他不可預知的長度施加限制。該限制默認爲256字節;如果你看到截斷,那麼你可以通過添加,例如更改限制,
#pragma D option strsize=512
下面dtruss
現有pragma
。其次,dtruss
是硬編碼,以瞭解各種系統調用的格式要求。您在其輸出中看不到任何緩衝區解釋爲sendto()
或recvfrom()
,因爲它們沒有在源中明確處理。沒有什麼能阻止你找到合適的添加他們的地方,但你可以代替編寫自己的腳本:
bash-3.2# cat sr.d
#pragma D option rawbytes
syscall::sendto:entry,
syscall::recvfrom:entry
/pid == $target/
{
self->bufp = arg1;
self->size = arg2;
}
syscall::sendto:return,
syscall::recvfrom:return
/pid == $target && self->bufp && self->size/
{
printf("%s():\n", probefunc);
tracemem(copyin(self->bufp, self->size), 64);
printf("\n");
self->bufp = self->size = NULL;
}
bash-3.2# dtrace -qs ./sr.d -p 16988
sendto():
0 1 2 3 4 5 6 7 8 9 a b c d e fabcdef
0: 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 hello...........
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
^C
bash-3.2#
注意的是,對於字符串,我們有義務提供tracemem()
的使用DTrace的硬性限制數據記錄緩衝區。如果極限很少被接近,那麼這會產生令人不愉快的結果,即輸出可能是壓倒性的並且大部分是多餘的。如果你知道你正在尋找字符串,那麼你可以簡單地使用copyinstr()
;如果你有一個更現代的DTrace執行比我的OS X 10.6.8,那麼你可能會發現,你可以寫
tracemem(copyin(self->bufp, self->size), 64, self->size);
,其中第二個參數是仍然字節記錄但數數的硬性限制字節顯示受限於可選的第三個參數。
最後,請注意,用戶地址地址記錄在系統調用的入口處,但僅用於出口。這是一個常見的習慣用法,如果有必要,系統調用可以使數據發生故障--DTrace本身不會這樣做,如果要求跟蹤非常駐地址,它將在運行時產生錯誤。