Windows DLL实际上如何共享
How are windows DLL actually shared?
通过检查Windows机器中的几个dll(例如kernel32.dll),我注意到它们的部分都没有,甚至没有读取数据部分都没有image_scn_mem_shared标志设置。
dll是从.dll文件映射的,因此只有在您读取文件的一页时,它将被复制到物理内存,但是如果同一个页面,请说kernel32.dll均通过过程A和Process B访问,然后该页面将在物理内存中两次存在。我要求最后一个语句的真实性。
如果.Text或.rodata段共享共享它们只能将其复制到物理内存中,即使启用ASLR时,ASLR首次加载时ASLR的作用是随机化模块的基数(应用了相应的重新定位,)但是,加载此模块的下一个过程重新启动系统将在同一地址获得模块,以便以相同的方式共享.Text和.rodata。
这些都是我做出的假设,请纠正我。
谢谢!
,只要页面内容不(需要)[以不同的方式,用于不同的过程],OS肯定能够将多个虚拟地址映射到同一物理内存页面上。。但是,如果代码使用绝对地址(在内部或外部对DLL上使用),例如VTable/function Pointers,对全局数据(常数或非恒定恒定)的指针,或者简单地使用绝对地址函数函数,则地址必须是修改以匹配OS给出的实际地址与该内存的那部分。这称为"搬迁"。
因此,至少从理论上讲,即使在地址空间随机化中,您也可以共享相同的DLL,它只需要编译器和/或程序员的更多工作即可。特别是,它要求没有重新定位(在代码的大部分中)。如果代码具有基于代码地址重新定位的绝对地址,则需要每个DLL副本。
我实际上不知道 OS如何处理此问题。一个简单的解决方案显然是每个DLL仅随机将地址随机化一次(直到该特定的DLL卸载),无论使用多少应用程序使用相同的DLL。它仍然使局外人很难知道DLL已加载的地址,因为每次第一次加载它会加载不同的地址(更重要的是,它并不是所有机器的静态值使用相同版本的OS,没有此功能)。但是,这确实意味着可以通过复制来自已知内容的堆栈来"检查"长期运行的过程。Web服务器,数据库服务器和系统服务通常是长期运行的过程,因此,仅当系统"关闭"(或至少重新启动长期运行过程)时才具有不同的地址。
第二个更棘手的版本是检查特定页面(通常是4KB的内存区域)是否具有重新定位,并共享所有没有重新定位的页面。重新安置的页面需要每个基础地址一个副本。典型的是在DLL(" thunk aftern")的一个块中具有"所有参考外部资源",因此,DLL的典型大部分不会不管代码的基础地址如何,这意味着那是绝对是可行的解决方案。
如果这些方案在操作系统中都没有"工作",则必须多次加载相同的DLL。无论如何,从操作系统的角度来看,这显然可以起作用,因为在ASLR之前,如果两个DLL试图在同一地址加载时,则需要移动同一dll的基本地址(例如,DLL由不同的供应商生成,恰好选择代码的相同基础地址,或经典和常见的"我从未给出基本地址,因此使用默认地址") - OS将通过更改加载的一个基础地址来解决此类冲突首先。
关于IMAGE_SCN_MEM_SHARED
的含义,我认为开发人员会请求此问题,其中DLL中的页面共享是自动完成的。换句话说,IMAGE_SCN_MEM_SHARED
将由特定DLL或EXE的开发人员设置,以表示内容应与同一内容的其他用户共享在没有内容的用户的情况下完成的"完成"(当然共享代码是这种情况,并且(可写的)数据通常不会在dll之间共享。只要没有重新搬迁,只要读取数据就可以隐含地共享[该内容的用户无法分辨出它是否共享]。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 在cuda线程之间共享大量常量数据
- 如何从具有移动语义的类对象中生成共享指针
- 在c代码之间共享数据的最佳方式
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 将静态库链接到不带-fPIC的共享库中
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用Boost Interprocess创建托管共享内存需要很长时间
- 无法在Ubuntu上将共享库与Eclipse链接
- 从python调用openMP共享库时,未定义opnMP函数
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 为什么主可执行文件和 dlopen 加载的共享库共享命名空间静态变量的一个副本?
- 如何测试共享对象/共享库已正确编译
- 调试和发布配置 (c++) 中内置的共享库之间的用法有何区别?
- 使用Windows共享内存共享小数据
- 将单一实例共享到共享库而不将其导出
- 从托管代码到非托管代码跨共享内存共享整数数组
- Xcode不与共享库共享静态变量
- 跨共享内存共享 std::字符串