我正在调查将两个依赖于同一共享对象的进程容器化对内存的影响。我的主要问题是共享对象是否会在内存中加载两次。
这个问题之前已经有人问过了,但是答案并不完整,而且与我的实验相矛盾。我将引用我已经遇到的情况:
共享库的加载和 RAM 的使用--> 对 .so 使用 -fPIC
docker 容器是否共享从同一层但不同映像映射的文件内存的 RAM? --> 是的,但取决于您的设置。您可以通过检查已加载共享对象的设备和 inode id 来证明这一点。没有指示要使用什么设置。
https://stackoverflow.com/questions/35863608/shared-library-in-containers --> 是的,取决于您的存储驱动程序。aufs、overlay 或 overlay2 存储驱动程序支持此功能。
https://stackoverflow.com/questions/63145223/about-loading-dynamic-library-in-container --> 每个容器都是自己的执行单元。不发生共享。与前文相矛盾。
我使用了以下设置:
- 基础层 --> 包含操作系统和两个共享对象 (G 和 S - 使用 -fPIC 预编译)
- DependsOnG 层 --> 从基础层开始,包含仅依赖于 G 的可执行文件(预编译)
- DependsOnGandS 层 --> 从基础层开始,包含依赖于 G 和 S 的可执行文件(预编译)
存储驱动程序:Overlay
下面您可以看到来自 grep glib /proc/PID/maps 的信息。PID 是容器内可执行文件的进程。
| /proc/17/maps:7efd3b630000-7efd41980000 | r-xp | 00000000 | 00:a2 | 16802420 | /app/libglib.so |
| /proc/17/maps:7efd41980000-7efd41b7f000 | ---p | 06350000 | 00:a2 | 16802420 | /app/libglib.so |
| /proc/17/maps:7efd41b7f000-7efd41b80000 | r--p | 0634f000 | 00:a2 | 16802420 | /app/libglib.so |
| /proc/17/maps:7efd41b80000-7efd41b81000 | rw-p | 06350000 | 00:a2 | 16802420 | /app/libglib.so |
| /proc/39/maps:7fca97208000-7fca9d558000 | r-xp | 00000000 | 00:bb | 16802420 | /app/libglib.so |
| /proc/39/maps:7fca9d558000-7fca9d757000 | ---p | 06350000 | 00:bb | 16802420 | /app/libglib.so |
| /proc/39/maps:7fca9d757000-7fca9d758000 | r--p | 0634f000 | 00:bb | 16802420 | /app/libglib.so |
| /proc/39/maps:7fca9d758000-7fca9d759000 | rw-p | 06350000 | 00:bb | 16802420 | /app/libglib.so |
如果我正确地解释了结果,那么两个进程将查看完全不同的文件(设备 ID 不同),因此共享对象将在内存中加载两次(似乎与我使用 free 命令看到的一致)。
根据我在网上找到的信息,这种情况不应该发生。
我有以下问题:
- 共享对象是否应该仅加载一次?
- 覆盖存储驱动程序是否支持此功能?
- 我应该以不同的方式构建我的图像/容器吗?(我使用卷而不是公共层进行了相同的实验,并且文件确实是相同的,但这并不是我想要的)
提前致谢!