我一直在查看mmap函数的不同标志,即MAP_FIXED,MAP_SHARED,MAP_PRIVATE。有人可以向我解释MAP_FIXED的目的吗?我们无法保证首先会使用地址空间。
答案 0 :(得分:9)
MAP_FIXED
对于内存映射是dup2
,并且在dup2
对文件描述符有用的情况下非常有用:当您想要执行替换时以原子方式重新分配资源标识符的操作(在MAP_FIXED
的情况下为内存范围,或在dup2
的情况下为fd)以引用新资源而不会出现可能重新分配的竞争的可能性如果您第一次发布旧资源,则尝试重新获取新资源。
作为示例,请加载共享库(通过动态加载程序)。它由至少三种类型的映射组成:read + exec-only程序代码映射和可执行文件中的只读数据,初始化数据的读写映射(也来自可执行文件,但通常具有不同的映射)相对偏移量)和读写零初始化匿名内存(用于.bss
)。将它们创建为单独的映射将不起作用,因为它们必须相对于彼此处于固定的相对地址。因此,您首先在没有MAP_FIXED
的情况下对所需的总长度进行虚拟映射(此映射的类型无关紧要),只是为了在内核分配的位置保留足够范围的连续地址,然后使用{ {1}}根据需要使用您需要创建的三个或更多映射来映射此范围的顶部部分。
此外,请注意,使用带有硬编码地址或随机地址的MAP_FIXED
始终是错误。使用MAP_FIXED
的唯一正确方法是替换现有映射,该映射的地址由之前成功调用MAP_FIXED
而没有mmap
的用户分配,或以其他方式替换为您认为安全的映射替换整页。这方面也完全类似于MAP_FIXED
;当调用者在目标fd上没有打开文件并且意图替换它时,使用dup2
始终是一个错误。
答案 1 :(得分:2)
如果要加载的文件包含指针,则需要将其加载到固定位置,以确保指针正确。在某些情况下,这只能是一种优化。
非位置无关的可执行文件必须以固定地址加载。
共享内存可能包含指针。
使用预绑定的可执行文件将尝试在预定的内存位置加载动态库作为优化,但如果使用不同的位置(或者库已更改),则会回退到正常的加载技术。
所以MAP_FIXED
不是典型用法。