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

linux-映射文件的非线性部分,linux,mmap,file-mapping,Linux,Mmap,File Mapping,我有一个场景,需要在流程空间中线性映射文件的非线性部分 比如说,, 若文件是10页,我可能需要映射前3页、跳过4页和最后3页。 映射应该是线性的,s.t.进程空间中的增量访问允许转到第3页之后的文件第8页,因为第4、5、6和7页没有映射 我想知道这在Linux中是否可行 谢谢。使用MAP\u FIXED多次调用mmap()为第二次和后续映射指定固定地址的策略应该有效,但问题是,如果在第一次映射后立即有任何内容映射到内存中,它将被关闭,因为MAP\u FIXED会在进行新映射之前自动取消映射以前存

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

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

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


谢谢。

使用
MAP\u FIXED
多次调用
mmap()
为第二次和后续映射指定固定地址的策略应该有效,但问题是,如果在第一次映射后立即有任何内容映射到内存中,它将被关闭,因为
MAP\u FIXED
会在进行新映射之前自动取消映射以前存在的任何对象

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

  • 首先创建一个虚拟映射,它是要构造的所有映射的大小之和。因此,如果要映射文件的前3页,则跳过4页,再映射3页,创建6页的虚拟映射

    对于这个虚拟映射,您可以只映射匿名内存(
    map\u anonymous
    )。感谢您的建议,也可以使用
    MAP\u NORESERVE
    进行此映射

  • 使用实际需要的文件映射逐个替换此虚拟映射,使用
    MAP\u FIXED
    指定希望每个映射出现的精确地址

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

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

  • 在完成步骤2中的所有映射之后,原始的虚拟映射应该什么都没有了。

    除了Celada之外,您可能还对您的操作之后的Linux特定系统调用感兴趣


    第一个
    mmap
    可能会使用
    MAP\u NORESERVE
    来避免占用交换空间(只保留地址空间,而不是数据)。

    这不仅仅是多次调用
    mmap
    的情况吗?多次调用mmap不会为每次mmap调用提供指针结果吗?我有一个场景,整个映射只需要一个指针结果。它是否可行?我已经有一段时间没有用
    mmap
    做任何事情了,但是其中一个参数不是可选的地址吗?是的,第一个参数。因此,您多次建议调用mmap,但从wards上的第二次调用开始,使用上一次调用的结果作为第一个参数?@OliCharlesworth进程空间中的线性访问是否会有问题..来自。。。内核将第一个参数作为映射位置的提示;在Linux上,映射将在附近的页面边界创建。如果在您销毁虚拟映射并意外选择这个漂亮的免费“洞”之后,您控制之外的另一个程序立即使用mmap,会发生什么?我认为这行不通reliably@sl0815:您正在映射到虚拟内存,不是吗?所以其他程序不会影响你。(然而,我不评论这一策略是否可靠……)我应该更仔细地阅读这些手册页@大家:忽略我上面愚蠢的评论。有用的提示:
    MAP\u FIXED
    使得调用
    munmap()
    变得不必要
    MAP\u FIXED
    标志忽略了通常的内核保留检查,因此您可以使用已经保留的地址来指定它,它只会隐式地删除先前映射到那里的内存。这是posix MAP_FIXED标准的一部分。@jstine证明这很重要,所以我将用这些信息编辑答案。感谢您提供这些额外的想法。我既不知道
    remap\u file\u pages()
    也不知道
    MAP\u NORESERVE
    。我希望,非常特定于Linux且不可移植:-)AFAIR,
    MAP\u NORESERVE
    在其他一些系统(可能是Solaris)上可用。但是,
    remap\u file\u pages
    确实非常特定于Linux。