AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 780505
Accepted
A.G
A.G
Asked: 2024-07-21 02:10:36 +0800 CST2024-07-21 02:10:36 +0800 CST 2024-07-21 02:10:36 +0800 CST

不同容器中的可执行文件是否共享在同一个公共图像层中定义的共享对象?

  • 772

我正在调查将两个依赖于同一共享对象的进程容器化对内存的影响。我的主要问题是共享对象是否会在内存中加载两次。

这个问题之前已经有人问过了,但是答案并不完整,而且与我的实验相矛盾。我将引用我已经遇到的情况:

共享库的加载和 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 命令看到的一致)。

根据我在网上找到的信息,这种情况不应该发生。

我有以下问题:

  1. 共享对象是否应该仅加载一次?
  2. 覆盖存储驱动程序是否支持此功能?
  3. 我应该以不同的方式构建我的图像/容器吗?(我使用卷而不是公共层进行了相同的实验,并且文件确实是相同的,但这并不是我想要的)

提前致谢!

kernel
  • 2 2 个回答
  • 109 Views

2 个回答

  • Voted
  1. Philip Couling
    2024-07-22T01:57:15+08:002024-07-22T01:57:15+08:00

    您对这个话题感到困惑有两个原因:

    • Docker 是可配置的。因此,如果你给出明确的“是”或“否”,几乎肯定会有人找到插件或晦涩难懂的配置来证明你错了。
    • 有些人误解容器更接近虚拟机,并认为它们比实际上更加孤立。

    简单的答案是,默认情况下,当文件来自同一层时,docker 会在容器之间共享同一文件的内存。更改 sorage 驱动程序可能会导致它执行其他操作(如此处指出的那样)。


    如果我正确解释结果,这两个进程查看完全不同的文件(设备 ID 不同)

    不,事实并非如此。 提示:两个相同的文件在两个不同的文件系统上偶然具有相同的 inode 编号的可能性很小。

    您现在看到的行为记录在覆盖下:

    https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#inode-properties

    在所有覆盖层都位于同一底层文件系统的特殊情况下,所有对象都将报告来自覆盖文件系统的 st_dev 和来自底层文件系统的 st_ino。这将使覆盖挂载更符合文件系统扫描仪的要求,并且覆盖对象将与原始文件系统中的相应对象区分开来。

    我不知道在Stephen Kitt回答之后这种情况是如何/何时发生变化的。我知道我当时检查了结果。

    由于 docker 镜像的层和可写层都位于同一个文件系统上,因此即使同一个底层文件系统对象只映射过一次,您也应该期望不同的设备 (st_dev)。这是因为每个容器都有自己的可写层,因此 Docker 将为每个容器安装一个新的覆盖层。

    但覆盖只是简单地传递到底层文件系统上未修改的文件。

    文档

    https://docs.docker.com/storage/storagedriver/overlayfs-driver/#the-image-layers

    镜像层目录包含该层特有的文件以及与下层共享的数据的硬链接。这样可以高效利用磁盘空间。

    我没有检查结果,但由于图像是通过硬链接合成的,您应该能够调查图像层的内容并使用简单的stat <file>命令确认它们是相同的文件。

    因此,使用覆盖时,文件内容将是存储在磁盘上同一位置的同一文件,而不是副本。这样磁盘缓存只需加载一次。

    • 1
  2. Best Answer
    Erik Sjölund
    2024-07-29T19:56:06+08:002024-07-29T19:56:06+08:00

    Podman 目前正在添加对composefs的支持。该集成尚未完全投入生产,因为我发现最近几周(2024 年 7 月)有一些错误正在修复。

    希望在运行 rootful podman 时,对 composefs 的支持能够带来以下功能:

    • 相同文件共享磁盘空间
    • 相同文件的共享页面缓存

    (相同的文件不需要属于同一层)

    有关 composefs 的介绍,请参阅此演示文稿(视频 + 幻灯片) https://fosdem.org/2024/schedule/event/fosdem-2024-3250-composefs-and-containers/

    目前正在进行开发,开始在基于镜像的操作系统(例如 Fedora Silverblue、Fedora CoreOS)中使用 composefs。将来,甚至可能在主机和容器之间共享相同文件的磁盘空间和页面缓存。

    • 0

相关问题

  • /proc/net/wireless 如何是 /proc/net/dev 的“克隆”?

  • Linux Mint 内核损坏

  • Linux 内核开发人员如何处理数百万行代码的工作?他们是一种方法吗?[关闭]

  • 通过标签将根文件系统传递给linux内核

  • 以 root 用户身份访问文件系统

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve