我知道,在Linux中,在引用页面中的虚拟地址之前,不会为虚拟地址空间页面分配RAM页面。但是,我在设备中使用嵌入式 Linux,其中所有 ELF 文件在加载之前都已驻留在 RAM(RAM 磁盘)中(从每个 ELF 文件启动进程)。所以我在想是否可以在加载每个 ELF 文件时为每个 ELF 文件中的所有代码和数据分配 RAM。如果可能的话,我想一旦所有 ELF 文件的代码和数据都被分页到 RAM 中,我就能够从 RAM 中删除每个 ELF 文件,以便释放更多的内存空间以供将来使用。
答案1
您可以使用诸如 之类的技巧强制对所有进程的地址空间进行分页mlockall()
,但这不会帮助您节省内存,因为无论内核如何,只要它映射到内存中,内核都会保持支持文件打开(即使你删除它)。
你正在寻找的东西叫做就地执行 (XIP)并且是一项功能,可让您直接从内存映射存储执行文件,而不是先复制到(单独的)RAM 中。
XIP 很难支持,因为它对如何在存储中(在文件系统中,如果适用)布置可执行文件提出了严格的要求。例如,要映射到内存的文件部分必须在存储中页面对齐,并且不能与文件系统元数据混合。此外,理想情况下,二进制文件将被编译为位置无关代码这样运行时链接器在映射后就不必修改它的任何部分。几乎没有文件系统支持 XIP。
幸运的是,我的理解是临时文件系统 做支持XIP。如果这是正确的,那么您的解决方案只是挂载 tmpfs 文件系统并在运行之前将可执行文件移动到那里。
更新后小考伊评论了:
如果我只是将可执行文件移动到tmpfs中,它会自动就地执行吗?为什么?是什么使文件在 RAM 中页对齐?加载器每次开始加载可执行文件时都会检查可执行文件是否满足以XIP方式运行所需的条件吗?
tmpfs 可以支持 XiP,因为它在 RAM 中存储文件的方式。 tmpfs 中的文件存储在内存页中,每个文件都分配有不与 tmpfs 中的其他文件共享的全部内存页。 (这就是 tmpfs 中的文件始终占用 4 KiB 的倍数(页面大小)的原因。)数据以文件的第一个字节存储在其内存页面的第一个字节中,依此类推。因此,当mmap()
调用(或内核 ELF 加载器)从文件映射页面时,它不需要将数据复制到新页面,它只需共享已经属于 tmpfs 的页面 - 只要映射对齐即可(应该是 ELF 的情况)。