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);