如何从linux进程中保留特定范围的虚拟内存

时间:2016-01-22 23:40:04

标签: linux linker mmap

i86-32位系统: 有没有办法在进程内存映射中保留特定范围的虚拟地址空间,以阻止ld.so(动态链接器)将任何共享对象加载到该范围内?

我想使用至少2个1G虚拟内存来映射两个1G大页面,但是,ld.so在中间加载共享库,所以我无法映射1G大页面。

编译器无法完成这项工作。链接器脚本也不行。 ld.so由加载器加载到可执行文件中,然后ld.so加载其他共享库。然而,ld.so本身甚至在映射空间的中间。

ld.so和libc.so的入口点位于更高的地址,无法为我们的应用程序更改。   入口点地址:0x46c38810

谢谢, 江涛

2 个答案:

答案 0 :(得分:1)

  

ld.so由加载器加载到可执行文件中,

否:ld.so 加载程序,它由内核加载到进程中。

你有几个选择:

  • 最简单的解决方案是完全静态地链接二进制文件。请注意,在Linux上,这样的二进制文件仍然可以dlopen其他共享库,尽管这不是一个受到良好支持或经过良好测试的事情。
  • 更难的解决方案是构建您自己的修补ld.so,并使您的应用程序使用ld.so(使用-Wl,--dynamic-linker=...标记)。
  • 如果您不想这样做,rtldi可能有所帮助(它将在 ld.so之前运行)。

答案 1 :(得分:0)

共享库中的入口点地址由预链接编辑。 prelink是为了避免共享库的加载地址冲突,以优化和加速运行时加载器。默认情况下,它在我们的系统中。

prelink是一个修改ELF共享库和ELF动态链接二进制文件的程序,并为每个lib分配一个唯一的虚拟地址空间槽。以这种方式,动态链接器在启动时执行重定位所需的时间显着减少。由于重定位次数减少,运行时内存消耗也会减少。

/ usr / sbin / prelink -avmR 预链接在/etc/prelink.conf中指定的目录中找到的所有二进制文件及其所有依赖库,为库分配唯一的虚拟地址空间插槽

通过禁用预链接,入口点不在lib的中间。所以我们可以获得另一个1G内存。