15-MAP_FIXED标记
49.10 MAP_FIXED标记
在mmap() flags参数中指定MAP_FIXED标记会强制内核原样地解释addr中的地址,而不是只将其作为一种提示信息。如果指定了MAP_FIXED,那么addr就必须是分页对齐的。
一般来讲,一个可移植的应用程序不应该使用MAP_FIXED,并且需要将addr指定为NULL,这样就允许系统选择将映射放置在哪个地址处了。之所以需要这样做的原因与48.3节中解释在使用shmat()附加一个System V共享内存段时通常倾向于将shmaddr指定为NULL的原因是一样的。
然而,还是存在一种可移植应用程序需要使用MAP_FIXED的情况。如果在调用mmap()时指定了MAP_FIXED,并且内存区域的起始位置为addr,覆盖的length字节与之前的映射的分页重叠了,那么重叠的分页会被新映射替代。使用这个特性可以可移植地将一个文件(或多个文件)的多个部分映射进一块连续的内存区域,如下所述。
1. 使用mmap()创建一个匿名映射(参见49.7节)。在mmap()调用中将addr指定为NULL并且不指定MAP_FIXED标记。这样就允许内核为映射选择一个地址了。
2. 使用一系列指定了MAP_FIXED标记的mmap()调用来将文件区域映射(即重叠)进在上一步中创建的映射的不同部分中。
尽管可以忽略第一个步骤而直接使用一系列mmap() MAP_FIXED操作来在应用程序选中的地址范围内创建一组连续的映射,但这种做法的可移植性与上面这种两步式做法相比就要差一些了。上面提及过,一个可移植的应用程序应该避免在固定的地址处创建新映射。上面的第一步避免了移植性问题的出现,因为这一步让内核选择了一个连续的地址范围,然后在该地址范围中创建新映射。
从Linux 2.6开始,使用remap_file_pages()系统调用(下一节介绍)也能够取得同样的效果,但使用MAP_FIXED的可移植性更强,因为remap_file_pages()是Linux特有的。