Windows DLL实际上是如何共享的?

2024-01-25

通过检查 Windows 计算机中的几个 DLL(例如 KERNEL32.DLL),我注意到它们的任何部分(甚至只读数据部分)都没有设置 IMAGE_SCN_MEM_SHARED 标志。

DLL 是从 .dll 文件映射的,因此只有当您读取文件的一页时,它才会被复制到物理内存,但如果进程 A 和进程 B 都访问 kernel32.dll 的同一页,则该页将被复制到物理内存中。在物理内存中存在两次。我想知道最后这句话的真实性。

如果共享 .text 或 .rodata 段,即使启用了 ASLR,它们也只会被复制到物理内存一次,因为 ASLR 的作用是在首次加载模块时随机化模块的基址(应用了相应的重定位),但加载此模块的下一个进程直到系统重新启动都会在同一地址获取该模块,因此 .text 和 .rodata 可以以相同的方式共享。

这些都是我的猜测,请指正。

Thanks!


操作系统肯定能够将多个虚拟地址映射到同一物理内存页面,只要页面内容不(需要)改变[针对不同进程以不同的方式]。但是,如果代码使用绝对地址(DLL 内部或外部),例如 vtable/函数指针、指向全局数据(常量或非常量)的指针或使用绝对地址的简单函数调用,则该地址必须是修改以匹配操作系统给该内存部分的实际地址。这就是所谓的“搬迁”。

因此,至少在理论上,即使地址空间随机化,您也可以共享相同的 DLL,它只需要编译器和/或程序员做更多的工作。特别是,它要求没有重定位(在大块代码中)。如果代码具有根据代码地址重定位的绝对地址,则每个 DLL 需要有一份副本。

我其实不know操作系统如何处理这个问题。一个简单的解决方案显然是每个 DLL 仅随机化一次地址(直到卸载该特定 DLL),无论有多少应用程序使用相同的 DLL。它仍然使外人很难知道 DLL 加载到哪个地址,因为每次第一次加载时它都会加载到不同的地址(更重要的是,它不会是所有机器的静态值)使用相同版本的操作系统,如果没有此功能,就会出现这种情况)。然而,它确实意味着可以通过从具有已知内容的堆栈中复制内容来“检查”长时间运行的进程。 Web 服务器、数据库服务器和系统服务通常是长时间运行的进程,因此只有当系统“关闭”(或至少重新启动长时间运行的进程)时才会有不同的地址。

第二个稍微棘手的版本是检查特定页面(通常是 4KB 内存区域)是否有重定位,并共享所有没有重定位的页面。重定位页面的每个基地址需要有一份副本。通常在 DLL 的一个块中包含“对外部资源的所有引用”(“thunk 部分”),因此无论代码的基地址是什么,DLL 的典型大部分都不会,这意味着绝对是一个可行的解决方案。

如果这些方案在操作系统中都“不起作用”,那么您必须多次加载相同的 DLL。无论如何,从操作系统的角度来看,这显然是有效的,与 ASLR 之前一样,如果两个 DLL 尝试加载到同一地址(例如由不同供应商生产的 DLL,碰巧为代码选择了相同的基地址,或者经典且常见的“我从未给出基地址,因此它使用默认地址”) - 操作系统将通过更改加载的基地址来解决此类冲突第一的。

至于意义IMAGE_SCN_MEM_SHARED,我本以为开发人员会要求这样做,其中 DLL 中的页面共享是自动完成的。换句话说IMAGE_SCN_MEM_SHARED由特定 DLL 或 EXE 的开发人员设置以表示内容should与相同内容的其他用户共享,而不是“如果可以在内容用户不注意的情况下完成,操作系统就可以共享它”(共享代码当然就是这种情况,并且(可写)数据通常不共享DLL之间。只读数据,只要它没有重定位,当然可以隐式共享[该内容的用户无法判断它是否被共享]。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows DLL实际上是如何共享的? 的相关文章

  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • 将类对象放置在向量中?

    我注意到我可以将一个类放置在一个向量中 这是我的程序 我收到以下错误 out blackjack exe blackjack obj blackjack obj error LNK2019 unresolved external symbo
  • Rx.NET 中是否有一个Subject 实现,其功能类似于BehaviourSubject,但仅在值发生更改时才发出?

    有没有Subject https learn microsoft com en us previous versions dotnet reactive extensions hh229699 v vs 103 Rx NET 中的实现在功能
  • 按扩展名过滤搜索文件返回太多结果

    我正在开发一个 C 控制台应用程序 它必须管理 Windows 操作系统上的文件 我需要获取具有特定扩展名的文件名 列表 我找到了很多解决方案 最建议的是以下一种 HANDLE hFind WIN32 FIND DATA data hFin
  • MVC3中设置下拉列表中的所选项目

    我必须为视图中的下拉列表设置所选项目 但它不起作用 View div class editor label Html LabelFor model gt model Gender div div class editor field Htm
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 如何将 SOLID 原则应用到现有项目中

    我对这个问题的主观性表示歉意 但我有点卡住了 我希望之前处理过这个问题的人能够提供一些指导和建议 我有 现在已经成为 一个用 C 2 0 编写的非常大的 RESTful API 项目 并且我的一些类已经变得巨大 我的主要 API 类就是一个
  • java中如何重新初始化int数组

    class PassingRefByVal static void Change int pArray pArray 0 888 This change affects the original element pArray new int
  • 有些有助于理解“产量”

    在我不断追求少吸的过程中 我试图理解 产量 的说法 但我不断遇到同样的错误 someMethod 的主体不能是迭代器块 因为 System Collections Generic List 不是迭代器接口类型 这是我被卡住的代码 forea
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 语音识别编程问题入门

    所以 你们可能都看过 钢铁侠 其中托尼与一个名为贾维斯的人工智能系统进行交互 演示剪辑here http www youtube com watch v Go8zsh1Ev6Y 抱歉 这是广告 我非常熟悉 C C 和 Visual Basi
  • 如何使用 ASP.NET Core 获取其他用户的声明

    我仍在学习 ASP NET Core 的身份 我正在进行基于声明的令牌授权 大多数示例都是关于 当前 登录用户的 就我而言 我的 RPC 服务正在接收身份数据库中某个用户的用户名和密码 我需要 验证是否存在具有此类凭据的用户 获取该用户的所
  • 获取没有显式特征的整数模板参数的有符号/无符号变体

    我希望定义一个模板类 其模板参数始终是整数类型 该类将包含两个成员 其中之一是类型T 另一个作为类型的无符号变体T 即如果T int then T Unsigned unsigned int 我的第一直觉是这样做 template
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 已发布的 .Net Core 应用程序警告安装 .Net Core,但它已安装

    我制作了一个 WPF 和控制台应用程序 供某人在我无法访问的私人服务器上使用 我使用 Visual Studio 2019 的内置 发布向导 来创建依赖于框架的单文件应用程序 当该人打开 WPF 应用程序时 他们会看到标准警告 他们单击 是
  • 从 C# 使用 Odbc 调用 Oracle 包函数

    我在 Oracle 包中定义了一个函数 CREATE OR REPLACE PACKAGE BODY TESTUSER TESTPKG as FUNCTION testfunc n IN NUMBER RETURN NUMBER as be
  • 如果输入被重定向则执行操作

    我想知道如果我的输入被重定向 我应该如何在 C 程序中执行操作 例如 假设我有已编译的程序 prog 并且我将输入 input txt 重定向到它 我这样做 prog lt input txt 我如何在代码中检测到这一点 一般来说 您无法判
  • 使动态创建的链接标签在 Winforms 中可点击

    我正在制作一个程序 允许用户单击由动态链接标签创建的公司名称 在我想知道如何做到这一点之前 我从未在 C 中使用过链接标签 可为特定用户生成的业务数量各不相同 因此每个用户的链接标签数量并不相同 然后我想捕获业务 ID 以进行 Json 调
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • MySqlConnectionStringBuilder - 使用证书连接

    我正在尝试连接到 Google Cloud Sql 这是一个 MySql 解决方案 我能够使用 MySql Workbench 进行连接 我如何使用 C 连接MySqlConnectionStringBuilder 我找不到提供这三个证书的

随机推荐