在Linux中共享可执行内存页面? [英] Sharing executable memory pages in Linux?

查看:214
本文介绍了在Linux中共享可执行内存页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了节省空间,是否可以在Linux上共享可执行页面?我知道有些共享内存API可用于在不同进程之间共享内存,但我认为这并不是用于此目的的.

Is it possible to share executable pages on Linux for the sake of preserving space? I know that there are shared memory APIs that can be used to share memory between different processes but I don't think that is meant to be used for that.

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

Basically, I want to have a shared memory region where some commonly used shared libraries can be loaded into. I want to get the dynamic linker to link against the preloaded (read only) images instead of having to load all of the shared library images into every single process (which seems like a waste).

在Linux内核上可能吗?达尔文内核使用称为 commpages 的Mach VM功能(dyld共享缓存存储在此处)来实现此目的.奖励是每个进程都可以接受并共享的.

Is this possible on the Linux kernel? The Darwin kernel implements this using a feature of Mach VM known as commpages (the dyld shared cache is stored there). The commpages are accesible to and shared between every process.

请澄清一下,我知道什么是共享库(库).当前,动态链接程序在Linux上所做的是将所有必需的库加载到程序的地址空间中,这意味着每个与libc链接的应用程序(例如)在其地址空间中都会有libc映像.在Darwin上,可以通过将libc的可执行文件(和其他只读文件)放在一组共享内存页上来消除此问题.共享映像的可写部分仍然是分开的.

Just to clarify, I know what shared objects (libraries) are. Currently, what the dynamic linker does on Linux is it loads all the required libraries into the program's address space, which means that each application that links against libc (for example) will have an image of libc somewhere in its address space. On Darwin, this issue can be eliminated by having the executable (and other read only) sections of libc on a set of shared memory pages. The writable sections of the shared images are still separate.

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

I know that the ELF format does not support separating DATA and TEXT segments of the shared libraries. I'm not using ELF, I'm using a different binary format (with my own binfmt kernel module and my own dynamic linker). I'm interested if the Linux kernel supports a commpage-like feature.

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

Edit 2: The only way I can think of doing this would be to allocate a big slab of memory in the kernel and map it into every binary that gets executed. The first time any binary is executed, the dynamic linker could unprotect it, fill it with the desired data and protect it. Then somehow, the kernel would have to make sure that the memory segment is not modified by anything else as it would open a massive security hole. Another

推荐答案

正如geekosaur所说,Linux已经做到了.

As geekosaur said, Linux already does this.

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

At application startup the dynamic linker (ld.so) mmap()s the shared libraries. It performs several calls to mmap() for each library:

  • mmap(PROT_READ|PROT_EXEC)用于可执行节(即.text)
  • mmap(PROT_READ|PROT_WRITE)用于数据(即.data和.bss)
  • mmap(PROT_READ|PROT_EXEC) for the executable section (i.e. .text)
  • mmap(PROT_READ|PROT_WRITE) for the data (i.e. .data and .bss)

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

(You can check this for yourself using strace.)

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

The kernel, being a clever little bit of code, realises that the executable section, identified by offset and the inode (known through the fd), is already mapped. As it's read-only there's no point in allocating more memory for it.

这也意味着,如果您从多个应用程序中只读出任何其他文件,则该内存也将仅消耗一次.

This also means that if you have any other file which you mmap() read-only from several application the memory will also be consumed only once.

这篇关于在Linux中共享可执行内存页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆