linux 读取 strace 生成的系统调用 - 如何理解指向缓冲区值的指针?

linux read system call produced by strace - how to understand pointer to buffer value?

I 运行 strace 并且在它的输出中我得到如下行:

read(3, "7ELF[=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=]>[=11=][=11=][=11=][=11=]3[=11=][=11=][=11=][=11=][=11=][=11=]"..., 832) = 832

我在 read 上读过 man,所以字符串 "" 是指向 buf (ssize_t read(int fd, void *buf, size_t count);) 的指针,但是那个特定的字符串是什么意思?特别是:

您在这里看到的是动态加载程序打开并读取所需库的 header。几乎所有 strace 的 ELF 程序(这是 Linux 中的标准可执行格式)都以一堆 open/read/mmap/close 出于这个原因:动态加载程序正在加载所需的库。

你在这里看到的:

read(3, "7ELF[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]>[=10=][=10=][=10=][=10=]3[=10=][=10=][=10=][=10=][=10=][=10=]"..., 832) = 832

加载程序正在从文件中读取的内容:

  • 3:这是open()分配给打开文件的fd
  • "7ELF[=21=]...":这是正在读取的文件内容。数字在那里是因为它们是八进制转义序列,例如 </code> 表示字节 1。它们是这样打印的,否则你将无法看到它们,并且会在你的终端上造成混乱,因为大多数这些是特殊的不可打印字符。</li> <li><code>832:这是加载程序要从文件中读取的字节数。
  • = 832:这是read()的结果,这意味着所有请求的字节都被读取了。

换句话说,那些转义序列只是一种使 non-printable 字节可读的方法。您可以在加载程序试图打开的文件上测试此 运行 od -bc,您可以看到其八进制形式的内容加上可打印字符和反斜杠转义:

$ od -bc /lib/x86_64-linux-gnu/libc.so.6 | head -n4
0000000 177 105 114 106 002 001 001 003 000 000 000 000 000 000 000 000
        177   E   L   F 002 001 001 003  [=11=]  [=11=]  [=11=]  [=11=]  [=11=]  [=11=]  [=11=]  [=11=]
0000020 003 000 076 000 001 000 000 000 260 034 002 000 000 000 000 000
        003  [=11=]   >  [=11=] 001  [=11=]  [=11=]  [=11=] 260 034 002  [=11=]  [=11=]  [=11=]  [=11=]  [=11=]

下面是一个更完整的示例,来自 strace /bin/true

open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 4
read(4, "7ELF[=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=]>[=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=]"..., 832) = 832
fstat(4, {st_mode=S_IFREG|0755, st_size=1689360, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0d3d877000
mmap(NULL, 3795296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7f0d3d2dd000
mprotect(0x7f0d3d472000, 2097152, PROT_NONE) = 0
mmap(0x7f0d3d672000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x195000) = 0x7f0d3d672000
mmap(0x7f0d3d678000, 14688, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0d3d678000
close(4)  

可以看到加载器正在打开"libc",这是标准C库的ELF文件。它读取其 header 以确定要加载的部分,然后 mmap 将所有需要的部分存储在内存中,并分配正确的权限。