strace pwd
:
getcwd("/root"..., 4096) = 6
ltrace pwd
:
getcwd(NULL, 0) = "/root"
为什么第一个参数NULL
在ltrace
?
似乎 strace/ltrace 都使用ptrace
系统调用,但为什么它们得到不同的信息?
是的,他们都使用ptrace
,而且他们得到不同的信息。这是因为它们的使用ptrace
方式不同。
如果您查看ptrace 手册页,您会发现存在几个决定 ptrace 行为的“请求”值。
更具体地说,如果您ptrace
以前设置了 option PTRACE_O_TRACESYSGOOD
,则可以区分导致系统调用的陷阱和不导致系统调用的陷阱。
ltrace
显示库调用。在这种情况下,它显示了libc
源代码正在调用的函数。
如果您看到pwd
's source,您将看到(coreutils-8.13,文件 lib/xgetcwd.c):
char *cwd = getcwd (NULL, 0);
所以,ltrace
的输出是正确的:pwd
执行getcwd(NULL, 0)
。根据 Linux 手册页getcwd(3)
:
如果 buf 为 NULL,getcwd() 使用 malloc(3) 动态分配缓冲区。
然而,系统调用getcwd(2)
总是需要一个不同于 NULL 的第一个参数来复制路径名。您可以在 libc 源代码中看到这是如何完成的(例如,libc-3.13,文件 sysdeps/unix/sysv/linux/getcwd.c)。
库调用getcwd(NULL, 0)
执行系统调用getcwd(path, alloc_size)
,其中path
是先前 malloc() 的结果,alloc_size
是页面大小 (4096)。
为了确认这一点,如果您运行,ltrace -S pwd
您将看到库调用和系统调用:您将看到如下内容:
getcwd(NULL, 0 <unfinished ...>
SYS_getcwd("/root", 4096) = 6
<... getcwd resumed> ) = "/root"
因为系统调用和库调用不同。阅读 getcwd 函数的手册页,您会看到它具有以下原型:
long getcwd(char *buf, unsigned long size);