简体   繁体   English

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

[英]linux - map nonlinear parts of file

I have a scenario where I need to map non-linear parts of a file, linearly in a process space. 我有一个场景,我需要在一个进程空间中线性地映射文件的非线性部分。

For example, if file is 10 pages, I may need to map first 3, skip 4, and last 3. The mapping should be linear, st incremental access in process space allows to go to page 8 of file after page 3, as page 4,5,6 & 7 were not mapped. 例如,如果文件是10页,我可能需要先映射3,跳过4和最后3.映射应该是线性的,进程空间中的st增量访问允许转到第3页后的文件的第8页,作为页面没有映射4,5,6和7。

I want to know if this is possible in Linux. 我想知道这是否可以在Linux中使用。

Thanks. 谢谢。

The strategy to call mmap() multiple times using MAP_FIXED to specify a fixed address for the second and subsequent mappings should work, but the problem is that if there was anything already mapped into the memory immediately after the first mapping, it will get clobbered, because MAP_FIXED automatically unmaps whatever used to be there before making the new mapping. 使用MAP_FIXED多次调用mmap()为第二次和后续映射指定固定地址的策略应该有效,但问题是如果在第一次映射之后有任何事物已经映射到内存中,它将被破坏,因为MAP_FIXED会在制作新映射之前自动取消映射过去的内容。

I took a look at the layout of some mappings in the address space on a Linux system here, and I observed that, at least some of the time, the addresses chosen by the kernel for memory mappings grow downward from a high address to a low address. 我在这里看了一下Linux系统地址空间中一些映射的布局,我观察到,至少在某些时候,内核为内存映射选择的地址从高地址向下增长到低地址。 That is, a new mapping is given the address space immediately below the address space used by the most recent existing mapping. 也就是说,新映射被赋予紧邻最近现有映射所使用的地址空间下方的地址空间。 Under that strategy, when you make your first mapping, it is virtually guaranteed that the address space immediately following that mapping is already occupied by something else (and it's probably something important, too, like a system library). 根据该策略,当您进行第一次映射时,几乎可以保证紧跟在该映射之后的地址空间已被其他东西占用(并且它可能也很重要,就像系统库一样)。 Other systems (different kernel version, different architecture, or non-Linux, etc...) might use different address space allocation strategies that don't make this problem unlikely, but you should assume that it can happen and guard against it by using the following technique. 其他系统(不同的内核版本,不同的体系结构,或非Linux等等)可能会使用不同的地址空间分配策略,这些策略不会使这个问题变得不可能,但您应该假设它可以发生并通过使用来防范它以下技术。

  1. First make a dummy mapping that is the sum of the size of all of the mappings you want to construct. 首先创建一个虚拟映射,它是要构造的所有映射的大小的总和。 So if you want to map the first 3 pages of the file, then skip 4, then map three more, make a dummy mapping of 6 pages. 因此,如果要映射文件的前3页,则跳过4,然后再映射三个,进行6页的虚拟映射。

    For this dummy mapping, you can just map anonymous memory ( MAP_ANONYMOUS ). 对于此虚拟映射,您只需映射匿名内存( MAP_ANONYMOUS )。 Thanks to Basile Starynkevitch for the suggestion to also use MAP_NORESERVE for this mapping. 感谢Basile Starynkevitch建议也使用MAP_NORESERVE进行此映射。

  2. Replace this dummy mapping piece by piece with the mappings of the file you actually want, using MAP_FIXED to specify the precise address you would like each mapping to appear at. 将这个虚拟映射逐条替换为您实际需要的文件的映射,使用MAP_FIXED指定您希望每个映射显示的精确地址。

    EDIT: I originally suggested destroying the dummy mapping with munmap() before reusing the address space for new mappings, but thanks to jstine for pointing out that this is unnecessary (and it introduces a race condition if your program is multithreaded). 编辑:我最初建议在重新使用地址空间进行新映射之前使用munmap()销毁虚拟映射,但是由于jstine指出这是不必要的(如果你的程序是多线程的,它会引入竞争条件)。

    For the first mapping, use the start address by the dummy mapping. 对于第一个映射,请使用虚拟映射的起始地址。 Calculate the address for the second mapping as the start address of the dummy mapping plus the size of the first mapping. 计算第二个映射的地址,作为虚拟映射的起始地址加上第一个映射的大小。 This should place the second mapping right after the end of the first mapping. 这应该在第一个映射结束后立即放置第二个映射。 And so on for the third and fourth mappings. 等等第三和第四个映射。 In your scenario, everything is page-sized and page-aligned, so there will be no gaps due to alignment. 在您的方案中,所有内容都是页面大小和页面对齐的,因此不会因对齐而产生间隙。

After you finish making all of the mappings in step 2, there should be nothing left of the original dummy mapping. 在完成步骤2中的所有映射之后,原始虚拟映射应该没有任何内容。

In addition of previous answer by Celada, you might also be interested by the Linux specific remap_file_pages(2) syscall after your mmap(2) . 除了Celada 以前的回答之外,您可能还会对mmap(2)之后的特定于Linux的remap_file_pages(2)系统调用感兴趣。

And the first mmap might use MAP_NORESERVE to avoid spending swap space (and just reserve the address space, not the data). 并且第一个mmap可能使用MAP_NORESERVE来避免花费交换空间(并且只保留地址空间,而不是数据)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM