2

为了节省空间,是否可以在 Linux 上共享可执行页面?我知道有共享内存 API 可用于在不同进程之间共享内存,但我不认为这意味着要使用它。

基本上,我想要一个共享内存区域,可以将一些常用的共享库加载到其中。我想让动态链接器链接到预加载的(只读)图像,而不是必须将所有共享库图像加载到每个进程中(这似乎是一种浪费)。

这在 Linux 内核上可行吗?Darwin 内核使用 Mach VM 的一个称为commpages的功能来实现这一点(dyld 共享缓存存储在那里)。commpages 可以访问并在每个进程之间共享。

澄清一下,我知道共享对象(库)是什么。目前,动态链接器在 Linux 上所做的是将所有需要的库加载到程序的地址空间中,这意味着每个链接到 libc 的应用程序(例如)将在其地址空间的某个位置有一个 libc 的图像。在 Darwin 上,可以通过将 libc 的可执行(和其他只读)部分放在一组共享内存页面上来消除此问题。共享图像的可写部分仍然是分开的。

编辑:我知道 ELF 格式不支持分隔共享库的 DATA 和 TEXT 段。我没有使用 ELF,我使用的是不同的二进制格式(使用我自己的 binfmt 内核模块和我自己的动态链接器)。如果 Linux 内核支持类似 commpage 的功能,我很感兴趣。

编辑2:我能想到的唯一方法是在内核中分配一大块内存并将其映射到每个执行的二进制文件中。第一次执行任何二进制文件时,动态链接器可以取消保护它,用所需数据填充它并保护它。然后不知何故,内核必须确保内存段没有被其他任何东西修改,因为它会打开一个巨大的安全漏洞。其他

4

2 回答 2

6

正如 geekosaur 所说,Linux 已经做到了这一点。

在应用程序启动时,动态链接器 (ld.so)mmap()是共享库。mmap()它对每个库执行多次调用:

  • mmap(PROT_READ|PROT_EXEC)对于可执行部分(即.text)
  • mmap(PROT_READ|PROT_WRITE)对于数据(即 .data 和 .bss)

(您可以使用 自行检查strace。)

内核是一段聪明的代码,它意识到由偏移量和 inode(通过 fd 知道)标识的可执行部分已经被映射。由于它是只读的,因此没有必要为其分配更多内存。

这也意味着,如果您有任何其他文件是您mmap()从多个应用程序中只读的,则内存也只会被消耗一次。

于 2012-04-11T19:48:08.360 回答
4

Linux 已经这样做了;事实上,这就是共享对象的意义所在。

于 2012-04-11T00:55:40.160 回答