按需加载/卸载ELF部分?

3
对于一个相当晦涩的用例,我希望有一个(大型)静态链接的Linux可执行文件,由一小段控制代码和大量的静态(只读)数据组成。为了节省内存,是否可能让加载器仅加载控制代码部分,然后手动加载所需的RO数据部分,并在处理完成后再次卸载它们?
这是否可能?
(我想文件流(在文件系统级别上)可以用来解决这个问题,但它们对我不可用(EXT3),而且分发会很棘手,因为数据流很容易丢失。)
4个回答

4

很可能这个已经为你解决了。

当然,真正的答案会依赖于系统,但是一般来说,现代操作系统(特别是Linux)对可执行文件使用需求分页技术,所以不会为你没有引用的ELF文件部分分配任何RAM。


1
是的,那正是我所期望的,但是我还需要在完成后从RAM中清除页面。不幸的是,我正在使用的系统上没有虚拟内存,因此依靠该机制来释放RAM是不可用的。 - Magnus
可执行页面在需要更多页面时将自动取消映射。Linux始终实现某种虚拟内存,您可以将可执行文件视为只读交换文件。 - karunski

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部分,最简单的方法就是映射整个文件。


1

不要将你的 blob 链接到二进制文件中,而是将它们附加到其中。它们不会被映射,但你可以在需要时读取或映射它们。


0
不,如果它是ELF文件的一部分,它将被映射。我不确定ELF的细节,但如果这是一个PE文件,你可以简单地将你添加的数据附加到PE文件的末尾,超出PE结构。在Windows中,不属于PE结构的数据不会被映射到内存中。我认为在ELF中也存在同样的情况。

嗯,我猜我在这里走向了一个不同的方向,但是你可能已经猜到了,我的可用RAM有限。将整个文件映射到内存中会导致使用等量的RAM吗?还是只有文本段(代码)会被实际加载到RAM中(按需加载)? - Magnus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接