为什么我在调用`writev`时看不到内存地址?

时间:2016-07-08 18:43:32

标签: strace

我正在尝试使用strace来了解Erlang VM如何使用writev。我对系统调用知之甚少,而且我正在努力理解我所看到的内容。

this article中,作者展示了一个跟踪一个小的Erlang程序的例子,该程序写入文件,并看到如下系统调用:

writev(0x1A, 0x1A5405F8, 0x4)

他接着解释说,writev被赋予了向量的内存地址,该向量包含更多的内存地址。据推测,操作系统然后从这些地址获取数据并将其放入文件中。

我自己尝试了作者的例子 - 在名为iex的Elixir repl中运行相同的代码(在Ubunto 12.04 VM中),并按照以下方式进行跟踪:

# show me system calls for process 1166...
# ... and show long output if necessary (the -s flag)
# ... and also trace any child processes (the -f flag)
# ... and I only care about calls to writev (the -e flag)
# ... and capture standard error to a file (the >(tee ...))
strace -p 1166 -s 99999 -f -e writev 2> >(tee syscalls.txt)

然而,我得到的输出看起来像这样:

writev(11, [{"Hello ", 6}, {"&", 1}, {"amp;", 4}, {" Goodbye", 8}], 4) = 19

我将其读作:“到文件描述符11,写下以下4个字符串,每个字符串的长度,总共19个字节。”

但为什么我会看到实际的字符串值而不是内存地址?这是否暗示数据是以某种方式被复制而不是通过地址引用,或者我只是以某种方式错误地显示它?

当我writev这个过程时,为什么我看不到strace的内存地址?

1 个答案:

答案 0 :(得分:1)

strace不断变得更好。现在,它不是记录一个短暂的数组地址,而是实际告诉您正在编写的内容,这会在您的日志中留下有用的信息。

你可以尝试使用旗帜进行预测,以便用-e verbose=!writev来消除冗长 - 请注意根据你的外壳需要引用和/或逃避! - (可能只是给出你支持你的短暂数组地址,就像你引用的例子一样)并用-e raw=writev翻转原始显示,看看你得到了什么。

您还可以调查附加调试器并拦截writev调用。这将让你四处寻找并检查从进程发送到内核的数据。 (如果您手头有dtrace这样的动态跟踪实用程序,那么也可以让您做类似的事情,但不会停止这个世界。)