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 令人惊讶的是,mmaping /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内存管理架构之四(mmap内存映射机制)

Linux 内核 内存管理内存映射相关数据结构 ⑥ ( 文件映射 虚拟内存区域 | vm_area_struct | vm_operations_struct | 匿名映射 虚拟内存区域 )

linux内核源码分析之虚拟内存映射

Linux 内核 内存管理内存管理系统调用 ① ( mmap 创建内存映射 | munmap 删除内存映射 | mprotect 设置虚拟内存区域访问权限 )

【深入浅出Linux】关于mmap的解析

mmap/munmap映射函数在windows下是啥?如何修改