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

Why don't I see memory addresses in this call to `writev`?

我正在尝试使用 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

我读为:"to file descriptor 11, write the following 4 strings, each listed with its length, totaling 19 bytes."

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

当我 strace 这个过程时,为什么我看不到内存地址被分配给 writev

strace 越来越好。现在,它不再注销临时数组地址,而是实际告诉您正在写入的内容,从而在您的日​​志中留下有用的信息。

您可以尝试使用标志进行 futzing 以使用 -e verbose=!writev 触发冗长 – 请注意可能需要引用 and/or 转义 ! 取决于您的 shell –(可能只会返回您的临时数组地址,如您引用的示例中所示)并使用 -e raw=writev 翻转原始显示并查看您得到的结果。

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