linux中匿名内存映射映射到哪个文件?
Posted
技术标签:
【中文标题】linux中匿名内存映射映射到哪个文件?【英文标题】:Which file is an anonymous memory mapping mapped to in linux? 【发布时间】:2020-05-29 20:17:43 【问题描述】:我的问题是,当我们创建匿名内存映射时,被映射到进程地址空间的文件是什么。我知道匿名映射保证用零填充。那么是 /dev/zero 文件吗?据我了解,只有在参与进程的地址空间内映射了某些文件之后,才能进行进程间通信……无论是 tmpfs 中的文件还是普通文件系统中的文件。我是Inter Process Communication的新手,如果您发现我的理解有任何缺陷,请纠正。
【问题讨论】:
您无法写入 /dev/zero。匿名 mmap 没有文件支持。 @stark 令人惊讶的是,mmap
ing /dev/zero
实际上确实生成了一个有用的地图,就像匿名地图一样工作。
@stark 好吧,它必须映射到正确的位置。否则如何实现父进程和子进程之间的 IPC。 Child 不能直接访问 parent 的地址空间......或者可以吗?
【参考方案1】:
来自man mmap
:
MAP_ANONYMOUS
映射没有任何文件支持; [...]
它只是分配和初始化内存。在调用mmap
之前,由于虚拟内存未映射到真实内存,您会在尝试访问内存时遇到保护违规(SIGSEGV)。 (嗯,这就是在具有虚拟内存的系统中发生的情况。)
【讨论】:
【参考方案2】:我的问题是,当我们创建匿名内存映射时,映射到进程地址空间的文件是什么。
没有文件。
我知道匿名映射可以保证用零填充。然后是 /dev/zero 文件吗?
没有。
不过,从历史上看,MAP_ANONYMOUS
标志是比mmap
本身更新的发明。在此之前,如果您想要一块充满零且没有任何常规文件支持的内存,您确实可以打开/dev/zero
并映射它。这由操作系统作为一种特殊情况处理,并有效地为您提供匿名映射;创建/dev/zero
映射的不同进程不会看到彼此的数据,即使他们使用MAP_SHARED
。我相信引入MAP_ANONYMOUS
标志是为了简化此过程并避免打开和关闭/dev/zero
的额外系统调用。
据我了解,进程间通信是不可能的,除非有一些文件被映射到参与进程的地址空间中......无论是 tmpfs 中的文件还是普通文件系统中的文件。
嗯,那不是真的; MAP_ANONYMOUS | MAP_SHARED
是一个反例。如果您的进程使用MAP_ANONYMOUS | MAP_SHARED
创建映射,那么在该点之后使用fork()
创建的任何子进程(及其子进程等)都将继承该映射,并且内存将在所有进程和父进程之间共享。所有这些进程都可以看到任何这些进程对该内存的任何写入。
这确实意味着您只能将其用于“相关”进程之间的 IPC,即创建映射的共同祖先的后代(除非有我不知道的聪明技巧可以访问不相关的进程)。映射实际文件(/dev/zero
除外)没有此限制。
当然还有其他完全不涉及文件的 IPC 机制,例如POSIX 共享内存(shmget
和朋友)。
【讨论】:
那么匿名映射是如何为父母和孩子工作的。 Child 是否可以访问 Parent 的地址空间? @ShayakSarkar:孩子从fork()
返回,并带有父母地址空间的精确副本。其中大部分是写时复制,因此一个进程稍后所做的更改不会被另一个进程看到。但是共享的 mmap,包括匿名的,实际上是共享的;孩子写的东西可以被父母读,反之亦然。这是否是孩子可以访问父母的地址空间,反之亦然,或者两者都没有,这是一个视角问题。以上是关于linux中匿名内存映射映射到哪个文件?的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理内存映射相关数据结构 ⑥ ( 文件映射 虚拟内存区域 | vm_area_struct | vm_operations_struct | 匿名映射 虚拟内存区域 )
Linux 内核 内存管理内存管理系统调用 ① ( mmap 创建内存映射 | munmap 删除内存映射 | mprotect 设置虚拟内存区域访问权限 )