问题描述
我有进程A和进程B。进程A打开一个文件,调用mmap并写入该文件,进程B进行相同的操作,但是在进程A完成写入后读取相同的映射区域。
使用mmap,假设进程A尚未调用munmap,则假定进程B从内存而不是磁盘读取文件。
如果我想将进程A和进程B部署到Kubernetes的同一容器中的不同容器中,内存映射IO是否应该以与初始示例相同的方式工作?容器B(进程B)是否应该像在我的常规Linux桌面中那样从内存中读取文件?
我们假设两个容器都在同一个容器中,并且正在从相同的持久卷中读取/写入文件。我是否需要考虑特定类型的卷才能实现mmap IO?
如果您有疑问,我正在使用Apache Arrow和pyarrow来读写这些文件并实现零拷贝读取。
解决方法
Kubernetes容器是一组在同一主机上一起部署的容器。 (reference)。因此,这个问题实际上是关于在同一主机上运行的多个容器会发生什么情况。
使用多种不同的技术将容器隔离在主机上。这里有两个可能相关。 都不是,它们在映射文件时会阻止来自不同容器的两个进程共享相同的内存。
要考虑的两件事是如何隔离文件系统以及如何对内存进行隔离(限制)。
如何隔离文件系统
使用的技巧是创建一个mount namespace,以便其他进程看不到任何新的挂载点。然后将文件系统安装到目录树中,最后该过程调用chroot将/
设置为该目录树的根。
这不会影响mmap文件的处理方式。这只是关于两个不同进程的文件名/文件路径如何工作的聪明技巧。
即使作为该设置的一部分,通过两个不同的过程从头开始安装了相同的文件系统,其结果也将与bind mount相同。这意味着在两个路径下存在相同的文件系统,但它是* 相同的文件系统,而不是副本。
在这种情况下,任何映射文件的尝试都将与同一名称空间中的两个进程相同。
如何应用内存限制?
这是通过cgroups完成的。 cgroup并没有真正隔离任何东西,它们只是限制了单个进程可以做什么。
但是有一个自然的问题要问,如果两个进程通过cgroup具有不同的内存限制,它们可以共享同一共享内存吗? Yes they can!
注意:文件和shmem可能在其他cgroup之间共享。在这种情况下, 仅当内存cgroup是页的所有者时,才会考虑appedd_file 缓存。
该参考文献有些晦涩,但描述了内存限制如何应用于此类情况。
结论
两个进程都将同一文件中的同一文件映射为同一主机上的不同容器,这两个进程的行为几乎完全相同,就像两个进程位于同一容器中一样。