我运行了 strace
并在它的输出中得到如下行:
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\273\0\0\0\0\0\0"..., 832) = 832
我在 read 上读过 man ,所以字符串 ""
是指向 buf (ssize_t read(int fd, void *buf, size_t count);
) 的指针,但是那个特定的字符串是什么意思?特别是:
ELF
最有可能是可执行链接的 - 为什么这里是指针?\
让特殊字符转义 - 为什么在这里转义数字?>
是做什么用的?
最佳答案
您在这里看到的是动态加载程序打开并读取所需库的 header 。 ELF 程序(这是 Linux 中的标准可执行格式)的几乎所有 strace
都以一堆 open
/read
/ 开头mmap
/close
原因:动态加载器正在加载所需的库。
你在这里看到的:
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\273\0\0\0\0\0\0"..., 832) = 832
就是加载器从文件中读取的内容:
3
:这是由open()
分配给打开文件的fd
。"\177ELF\2\1\1\0..."
:这是正在读取的文件的内容。数字在那里是因为它们是八进制转义序列,例如\1
表示字节 1。它们是这样打印的,否则你将无法看到它们,并且会在你的终端上造成困惑,因为其中大部分是特殊的不可打印字符。832
:这是加载程序要从文件中读取的字节数。= 832
:这是read()
的结果,这意味着已读取所有请求的字节。
换句话说,那些转义序列只是一种使不可打印的字节可读的方法。您可以在加载程序试图打开的文件上运行 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 \0 \0 \0 \0 \0 \0 \0 \0
0000020 003 000 076 000 001 000 000 000 260 034 002 000 000 000 000 000
003 \0 > \0 001 \0 \0 \0 260 034 002 \0 \0 \0 \0 \0
下面是一个更完整的示例,来自 strace/bin/true
:
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 4
read(4, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\4\2\0\0\0\0\0"..., 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
内存中所有需要的部分,分配正确的权限。
关于c - Linux 读取 strace 记录的系统调用 - 如何理解指向缓冲区值的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58049023/