在Linux中共享可执行的内存页面?
为了保留空间,是否可以在Linux上共享可执行页面? 我知道有共享内存API可用于在不同进程之间共享内存,但我不认为这是用于此目的的。
基本上,我想有一个共享内存区域,可以加载一些常用的共享库。 我想让动态连接器与预加载(只读)图像链接,而不必将所有共享库图像加载到每个单独的进程中(这看起来像是浪费)。
这在Linux内核上可能吗? Darwin内核使用称为commpages的Mach VM功能(dyld共享缓存存储在那里)实现此功能。 每个流程都可访问并共享联系。
为了澄清,我知道共享对象(库)是什么。 目前,动态连接器在Linux上的作用是将所有必需的库加载到程序的地址空间中,这意味着每个与libc链接的应用程序在其地址空间中都会有libc映像。 在Darwin上,可以通过在一组共享内存页面上使用 libc的可执行文件(和其他只读文件)来消除此问题。 共享图像的可写部分仍然是分开的。
编辑:我知道ELF格式不支持分离共享库的DATA和TEXT段。 我没有使用ELF,我使用了不同的二进制格式(使用我自己的binfmt内核模块和我自己的动态链接器)。 如果Linux内核支持类似commpage的功能,我很感兴趣。
编辑2:我能想到的唯一方法就是在内核中分配一大块内存,并将其映射到每个执行的二进制文件中。 第一次执行任何二进制文件时,动态链接程序可以取消它的保护,填充所需的数据并保护它。 然后,不知何故,内核将不得不确保内存段没有被其他任何修改,因为它会打开一个巨大的安全漏洞。 另一个
正如geekosaur所说,Linux已经这样做了。
在应用程序启动时,动态链接器(ld.so) mmap()
是共享库。 它对每个库执行mmap()
几个调用:
mmap(PROT_READ|PROT_EXEC)
(即.text) mmap(PROT_READ|PROT_WRITE)
) (你可以使用strace
来检查你自己。)
内核作为一个巧妙的代码,意识到由offset和inode(通过fd已知)标识的可执行部分已经被映射。 由于它是只读的,因此为它分配更多内存毫无意义。
这也意味着,如果您有任何其他文件,其中mmap()
只读应用程序,则内存也将仅被使用一次。
Linux已经做到这一点; 实际上,这就是共享对象所关心的/为了什么。
链接地址: http://www.djcxy.com/p/46445.html