2011-08-24 156 views
7

我想知道...当我启动一个使用共享库A的程序X,并且在程序运行时,我修改了磁盘上的共享库,并运行另一个依赖于相同共享的程序Y图书馆。该程序是否会使用共享库的已有内存版本,或者是否会加载具有后续修改的共享库的不同实例?共享库何时被认为是共享的“相同”?

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

回答

4

动态加载程序只是做普通的旧open(2)mmap(2)电话,以及存储器映射颠簸的inode引用计数相同的方法,开放FD一样。因此,如果您为库执行通常的原子文件替换技巧,请在文件的新副本中写下更改,然后将其替换为旧的名称,在该点之后开始的任何内容都将拾取新的inode,并且新内容,但正在运行的程序将继续使用旧的inode和旧内容。

如果您修改了该库,那么在write调用之后启动的任何程序自然都会提取您的更改。更有趣的问题是已经映射的进程发生了什么。答案可能是“系统不会让你这样做”或“未指定,取决于页面缓存实现的细节”。在Linux执行过程中(这是我不得不手动)轻松地进行的:glibc动态加载程序对其所有共享库地图使用MAP_DENYWRITE,但没有记录,但听起来像,它的意思是“在映射存在时使该文件不可修改” 。然而,我在内核源代码中找不到任何东西可以使MAP_DENYWRITE;它可能是一个历史遗迹或其他类似的东西。它也使用MAP_PRIVATEhttp://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html表示“未确定MAP_PRIVATE映射建立后对底层对象所做的修改是否通过MAP_PRIVATE映射可见”。因此,您可能会也可能无法修改正在运行的进程下的共享库映像,具体取决于页面缓存实施的细节。

0

动态加载器使用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() 
+0

这实际上并没有回答问题 – zwol