【问题标题】:When is a shared library considered to be "the same" for the purpose of sharing?出于共享的目的,何时将共享库视为“相同”?
【发布时间】:2011-08-25 07:38:32
【问题描述】:

我想知道...当我启动一个使用共享库 A 的程序 X 时,当程序运行时,我修改了磁盘上的共享库,并运行另一个依赖于该共享库的程序 Y共享库。该程序 Y 将使用共享库的已在内存中的版本,还是会加载具有后续修改的共享库的不同实例?

如何确定是否共享已加载的库或从磁盘重新加载?

【问题讨论】:

    标签: unix posix shared-libraries


    【解决方案1】:

    动态加载器只执行常规的旧 open(2)mmap(2) 调用,并且内存映射会像打开的 fd 一样增加 inode 引用计数。因此,如果您对库执行通常的原子文件替换技巧,将您的更改写在文件的新副本中,然后 rename(2) 覆盖旧名称,此后开始的任何内容都将获取新的 inode和新的内容,但是运行的程序会继续使用旧的inode和旧的内容。

    如果您就地修改库,那么在write 调用之后启动的任何程序自然都会获取您的更改。更有趣的问题是已经映射的进程会发生什么。答案可能是“系统不会让你这样做”或“未指定,取决于页面缓存实现的细节”。随便戳一下 Linux 实现(这是我必须要做的):glibc 动态加载器对其所有共享库映射使用MAP_DENYWRITE,这没有记录,但听起来就像它的意思是“制作这个映射存在时文件不可修改”。但是,我在内核源代码中找不到任何使MAP_DENYWRITE 任何事情的东西;它可能是历史遗迹之类的。

    它也使用MAP_PRIVATEhttp://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html 表示“未指定在建立 MAP_PRIVATE 映射后对基础对象所做的修改是否可以通过 MAP_PRIVATE 映射可见。”因此,您可能会也可能无法修改正在运行的进程下的共享库图像,具体取决于页面缓存实现的细节。

    【讨论】:

      【解决方案2】:

      动态加载器使用mmap(2) 来加载共享库,所以所有的魔法都在mmap(2) 中。

      在Linux的特定情况下,文件映射调用fs特定的mmap()操作,通常连接到mm/filemap.c:generic_file_mmap(),它将文件映射的vm_ops.fault设置为mm/filemap.c:filemap_fault(),所以神奇的是延迟到缺页时间。 filemap_fault() 尝试使用 find_lock_page() 在页面缓存中查找页面。

      mmap() → fs_file_ops.mmap() → generic_file_mmap() → file_vm_ops.fault = filemap_fault()
      page fault → filemap_fault() → find_lock_page()
      

      【讨论】:

      • 这实际上并没有回答问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 2017-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多