我一直在研究mmap函数的不同标志,即MAP_FIXED、MAP_SHARED、MAP_PRIVATE。有人能解释一下MAP_FIXED的目的吗?毕竟并不能保证地址空间会被使用。
MAP_FIXED
是内存映射的dup2
,在与文件描述符中dup2
相同的情况下非常有用:当您想要执行一个替换操作时,该操作可以原子地重新分配资源标识符(在MAP_FIXED
的情况下是内存范围,在dup2
的情况下是fd),以引用新资源,而无需担心可能会出现的竞争条件,在这种情况下,如果您首先释放旧资源,然后尝试为新资源恢复它。
例如,考虑加载共享库(由动态加载器)。它由至少三种类型的映射组成:程序代码和来自可执行文件的只读数据的读取+执行映射,已初始化数据的读写映射(也来自可执行文件,但通常具有不同的相对偏移量),以及读写零初始化的匿名内存(对于.bss
)。将它们作为单独的映射创建将无法工作,因为它们必须相对于彼此保持固定的相对地址。因此,您首先创建所需总长度的虚拟映射(此映射的类型无关紧要),而不使用MAP_FIXED
仅仅是为了在内核分配的位置上保留足够数量的连续地址范围,然后使用MAP_FIXED
根据需要覆盖此范围的部分,以创建所需的三个或更多映射。
另外,请注意,始终将MAP_FIXED
与硬编码地址或随机地址一起使用是错误的。正确使用MAP_FIXED
的唯一方法是替换先前成功调用mmap
而没有使用MAP_FIXED
分配地址的现有映射,或以其他方式您感到可以安全地替换整个页面。这方面也完全类似于dup2
;如果调用者没有针对目标fd打开文件并打算替换该文件,则始终将dup2
用于该情况是一个错误。
不可重定位的可执行文件必须在固定地址加载。
共享内存可能包含指针。
使用预绑定的可执行文件将尝试在预定的内存位置加载动态库作为优化,但如果使用不同位置(或库已更改),则会回退到正常加载技术。
MAP_FIXED
不是典型的用法。
MAP_FIXED
将所需的三个或更多映射与此范围的部分重叠。在使用MAP_FIXED
进行第二次映射后,原始虚拟映射是否可以立即释放? - user3882729