我是dtrace的新手,并尝试编写一些基本的dtrace脚本。我找到了一个示例,在单独的终端上捕获read(2)和write(2)syscall,如下所示,
syscall::read:entry,
syscall::write:entry
/pid==4217/
{
}
指定的pid号来自另一个终端的pid id。当我看到这个例子时,如果我用dtrace运行这个脚本,它应该显示一些读写系统调用。但我只观察过读取系统调用而不是写入系统调用。
因此,如果我理解正确,在我观察的终端上(pid 4217),如果我在该终端上键入内容,内核将读取其字符,因此读取syscall假设发生。如果我输入类似“ls”的东西并按Enter键,内核将读取并执行它,并将一些输出写入终端,因此写入syscall假设被调用。但我没有看到任何写入系统调用。那是为什么?
答案 0 :(得分:1)
我首先验证write()适用于任何其他进程,例如一个简单的测试用例。在你的例子中,可能的是(a)它的错误的pid,或者它的孩子在写作,或者(b)写入调用没有被使用,但可能是,例如, writev()或其他一些调用(尝试使用strace验证)。
答案 1 :(得分:0)
我同意@PaulFox,这可能是一个错误的pid
值。在按Enter键之前暂停终端时,终端位于read
系统调用的中间。但是,当它打印终端提示符(按Enter和ls
运行之后)时,它会通过发出write
系统调用来实现。请注意,ls
的输出不是write
系统调用的来源! pid
将是正在运行的ls
命令的进程ID。
要测试write
系统调用实际上是否正常工作,请运行:
# dtrace -n 'syscall::write:entry {printf("hello")}'
然后尝试使用您的终端(将'bash'替换为您正在使用的任何内容)作为目标:
# dtrace -n 'syscall::write:entry /pid==$target/ {printf("hello")}' -c 'bash'
如果其中一个在您输入终端时未能显示任何内容,请回复。
另请注意,您的shell可能正在使用多个版本的write syscall(尽管如果它使用普通write
之外的其他内容我会感到惊讶):
# dtrace -ln 'syscall::*write*:entry'
ID PROVIDER MODULE FUNCTION NAME
147 syscall write entry
381 syscall writev entry
447 syscall pwrite entry
777 syscall aio_write entry
933 syscall write_nocancel entry
963 syscall writev_nocancel entry
969 syscall pwrite_nocancel entry