对于一个相当模糊的用例,我希望有一个(大)静态链接的Linux可执行文件,由一小段控制代码和大量静态(只读)数据组成。是否可以节省内存,让加载程序只加载控制代码的各个部分,然后在需要时手动加载RO数据部分,并在处理完成后再次卸载它们?
这可能吗?
(我想数据流(在文件系统级别上)可以用来解决这个问题,但我不能使用它们(EXT3),因为数据流容易丢失,所以分发会很棘手。)
答案 0 :(得分:4)
这(很可能)已经为你照顾过了。
当然,真正的答案将取决于系统,但一般而言,现代操作系统(当然还有Linux)对可执行文件使用请求分页,因此实际上不会为未引用的ELF文件部分分配RAM
答案 1 :(得分:1)
不是将blob链接到二进制文件中,而是将它们附加到它。它们不会被映射,但您可以根据需要阅读或映射它们。
答案 2 :(得分:1)
有些答案有些误导,因为它们暗示将映射整个二进制文件。不,那是错的。并非一切都会被映射!
证明:
$ cat /proc/self/maps
**08048000**-08052000 r-xp 00000000 08:03 78433 /bin/cat
**08052000**-08053000 rw-p 0000a000 08:03 78433 /bin/cat
...
这是将映射的唯一两个部分。为什么?因为这些是唯一具有DT_LOAD类型的那些:
$ readelf -l /bin/cat
Elf file type is EXEC (Executable file)
Entry point 0x8049cf8
There are 8 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 **0x08048000** 0x08048000 0x09ba0 0x09ba0 R E 0x1000 <<
LOAD 0x00a000 **0x08052000** 0x08052000 0x00228 0x00804 RW 0x1000 <<
DYNAMIC 0x00a014 0x08052014 0x08052014 0x000c8 0x000c8 RW 0x4
NOTE 0x000148 0x08048148 0x08048148 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x008c48 0x08050c48 0x08050c48 0x002a4 0x002a4 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
您还会注意到虚拟地址与ELF文件中定义的相同。
实际上,您只能访问文件的前40 KiB(0x8052000-0x8048000 = 40960字节)。这对于ELF标题已经足够了,但是你无法访问说DWARF .debug标题,更不用说字符串表(.strtab)了。
如果您想要访问所有ELF部分,最简单的方法是映射整个文件。
答案 3 :(得分:0)
不,如果它是ELF文件的一部分,它将被映射。我不确定ELF的详细信息,但如果这是一个PE文件,您可以简单地将添加的数据标记到PE文件的末尾,超出PE结构。不属于PE结构的数据不会映射到Windows中的内存。我怀疑ELF中存在同样的情况。