【问题标题】:Why code segment is common for different instances of same program为什么代码段对于同一程序的不同实例很常见
【发布时间】:2010-12-02 06:39:36
【问题描述】:

我想知道为什么代码段对于同一程序的不同实例是通用的。

例如:考虑程序 P1.exe 正在运行,如果 P1.exe 的另一个副本正在运行,则两个运行实例的代码段将是通用的。为什么会这样?

【问题讨论】:

  • 我在这里删除了cc++ 标签,因为它们似乎不相关。如果有人想再次重新编辑标签,请做我的客人——这不是我的领域。

标签: memory-management process operating-system executable


【解决方案1】:

如果相关代码段是从 DLL 加载的,则可能是操作系统很聪明并重用了已加载的库。这是使用动态加载库代码的核心点之一,它允许代码在多个进程之间共享。

不确定 Windows 是否足够聪明地使用常规 EXE 文件的代码部分来执行此操作,但如果可能的话,它会有意义。

也可能是虚拟内存在欺骗你;两个进程看起来在同一个地址上拥有相同的东西,但该地址是虚拟的,所以它们实际上只是显示物理内存的映射。

【讨论】:

  • 当然 Windows 足够聪明。但是,如果 DLL 能够在其所需的 基地址 处加载,则 DLL 只能在多个进程之间共享。如果它必须加载到其他地方,它不会被其他进程重用。这就是为什么最好rebase DLL,以便它们都配置了唯一的基地址。搜索 dll rebase 可获得大量信息。
  • 啊,我明白你的意思是处理 EXE 文件是否足够聪明。我在上面的评论是想你的意思是 Windows 是否足够聪明,而不是 Linux 或 Solaris。
【解决方案2】:

代码通常是只读的,因此制作多个副本会很浪费。

另外,Windows(至少,我不能代表这个级别的其他操作系统)使用分页基础结构直接从可执行文件中分页进出代码,就好像它是一个分页文件一样。由于您处理的是同一个可执行文件,因此它是从同一个位置分页到同一个位置。

现代操作系统实际上不再支持自修改代码。可以生成新代码(通过在分配内存时设置正确的标志),但这与原始代码段是分开的。

【讨论】:

  • 在相邻的句子中从“不再支持”变为“可能”是一项了不起的壮举。现代操作系统绝对支持自修改代码。
  • 操作系统和硬件保护使修改代码段变得如此困难,以至于不再值得。在新分配的内存块(标记为“可执行”)中动态创建代码是一个完全不同的想法。
【解决方案3】:

代码段是(假定是)静态的(不会更改),因此没有理由不将其用于多个实例。

【讨论】:

    【解决方案4】:

    只是从基础开始,Segmentation 只是一种实现内存隔离和分区的方法。 Paging 是实现此目的的另一种方法。在大多数情况下,您可以通过分段实现的任何事情,都可以通过分页来实现。因此,x86 上的大多数现代操作系统完全放弃使用分段,而是完全依赖分页工具。

    正因为如此,所有进程通常都会在(Base = 0,Limit = 4GB,Privilege level = 3)的平凡段下运行,这意味着代码/数据段寄存器在确定物理地址时没有实际作用, 只是用来设置进程的权限级别。所有进程通常会以相同的权限运行,因此它们在段寄存器中的值都应该相同。

    编辑

    也许我误解了这个问题。我以为问题作者在问为什么两个进程在代码段寄存器中具有相同的值。

    【讨论】:

      猜你喜欢
      • 2021-08-12
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多