我有一个场景,我需要在一个进程空间中线性地映射文件的非线性部分.
例如,
如果文件是10页,我可能需要先映射3,跳过4和最后3.
映射应该是线性的,s.t.进程空间中的增量访问允许转到第3页之后的文件的第8页,如第4,5,6页和第4页所示. 7没有映射.
我想知道这是否可以在Linux中使用.
谢谢.
解决方法:
使用MAP_FIXED多次调用mmap()为第二次和后续映射指定固定地址的策略应该有效,但问题是如果在第一次映射之后有任何事物已经映射到内存中,它将被破坏,因为MAP_FIXED会在制作新映射之前自动取消映射过去的内容.
我在这里看了一下Linux系统地址空间中一些映射的布局,我观察到,至少在某些时候,内核为内存映射选择的地址从高地址向下增长到低地址.也就是说,新映射被赋予紧邻最近现有映射所使用的地址空间下方的地址空间.根据该策略,当您进行第一次映射时,几乎可以保证紧跟在该映射之后的地址空间已被其他东西占用(并且它可能也很重要,就像系统库一样).其他系统(不同的内核版本,不同的体系结构,或非Linux等等)可能会使用不同的地址空间分配策略,这些策略不会使这个问题变得不可能,但您应该假设它可以发生并通过使用来防范它以下技术.
>首先创建一个虚拟映射,它是要构造的所有映射的大小的总和.因此,如果要映射文件的前3页,则跳过4,然后再映射三个,进行6页的虚拟映射.
对于此虚拟映射,您只需映射匿名内存(MAP_ANONYMOUS).感谢Basile Starynkevitch的建议也使用MAP_NORESERVE进行此映射.
>使用MAP_FIXED指定您希望每个映射显示的精确地址,逐个替换此虚拟映射与您实际需要的文件的映射.
编辑:我最初建议在重新使用地址空间进行新映射之前使用munmap()销毁虚拟映射,但是由于jstine指出这是不必要的(如果你的程序是多线程的,它会引入竞争条件).
对于第一个映射,请使用虚拟映射的起始地址.计算第二个映射的地址,作为虚拟映射的起始地址加上第一个映射的大小.这应该在第一个映射结束后立即放置第二个映射.等等第三和第四个映射.在您的方案中,所有内容都是页面大小和页面对齐的,因此不会因对齐而产生间隙.
在完成步骤2中的所有映射之后,原始虚拟映射应该没有任何内容.