linux - 映射文件的非线性部分

标签 linux mmap file-mapping

我有一个场景,我需要在进程空间中线性映射文件的非线性部分。

例如, 如果文件有 10 页,我可能需要映射前 3 页、跳过 4 页和最后 3 页。 映射应该是线性的,s.t.进程空间中的增量访问允许在第 3 页之后转到文件的第 8 页,因为未映射第 4、5、6 和 7 页。

我想知道这在 Linux 中是否可行。

谢谢。

最佳答案

使用MAP_FIXED 多次调用mmap() 为第二次和后续映射指定固定地址的策略应该可行,但问题是如果有任何在第一次映射后立即映射到内存中的东西都会被破坏,因为 MAP_FIXED 在进行新映射之前会自动取消映射。

我在这里查看了 Linux 系统地址空间中一些映射的布局,我观察到,至少在某些时候,内核选择的内存映射地址从高地址向下增长到一个低地址。也就是说,新映射的地址空间紧接在最近的现有映射使用的地址空间之下。根据该策略,当您进行第一个映射时,几乎可以保证紧随该映射之后的地址空间已经被其他东西占用(而且它可能也很重要,比如系统库)。其他系统(不同的内核版本、不同的体系结构或非 Linux 等)可能会使用不同的地址空间分配策略,这不会使这个问题不太可能发生,但你应该假设它可能发生并通过使用来防止它以下技术。

  1. 首先制作一个虚拟映射,它是您要构建的所有映射的大小之和。所以如果你想映射文件的前 3 页,那么跳过 4,然后再映射 3 页,做一个 6 页的虚拟映射。

    对于这个虚拟映射,您可以只映射匿名内存 (MAP_ANONYMOUS)。感谢Basile Starynkevitch对于也使用 MAP_NORESERVE 进行此映射的建议。

  2. 使用 MAP_FIXED 指定您希望每个映射出现的精确地址,将这个虚拟映射逐个替换为您实际想要的文件的映射。

    编辑: 我最初建议在为新映射重新使用地址空间之前使用 munmap() 破坏虚拟映射,但感谢 jstine指出这是不必要的(如果您的程序是多线程的,它会引入竞争条件)。

    对于第一个映射,使用虚拟映射的起始地址。将第二个映射的地址计算为虚拟映射的起始地址加上第一个映射的大小。这应该将第二个映射放在第一个映射结束之后。第三个和第四个映射依此类推。在您的场景中,所有内容都是页面大小和页面对齐的,因此不会因对齐而出现间隙。

在完成第 2 步中的所有映射后,原始虚拟映射应该没有任何剩余。

关于linux - 映射文件的非线性部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14346979/

相关文章:

linux - HDFS文件权限问题

c - mmap on/proc/pid/mem

c - 如何在 Windows 平台中找到内存映射文件的末尾而不事先知道文件的大小?

c++ - 如何通过 MapViewOfFile 发送 vector<vector<type>>

linux - 软件中断例程和用户态函数的区别

linux - bash 脚本中的 tar 用法

c - 能够访问内存位置的 mmap 系统调用操作

python - Python 中使用 mmap 和 re.findall 搜索大文件时出现 MemoryError

c++ - windows下如何正确使用共享内存

linux - 动态地逐行解析程序输出