Linux 可执行对象文件和虚拟内存

Linux 可执行对象文件和虚拟内存,linux,linker,operating-system,executable,virtual-memory,Linux,Linker,Operating System,Executable,Virtual Memory,我是Linux和虚拟内存的初学者,仍然在努力理解虚拟内存和可执行对象文件之间的关系 假设我们有一个可执行的对象文件a.out存储在硬盘上,并且假设最初a.out有一个.data部分,带有一个值为2018的全局变量。 当加载程序运行时,它分配一个连续的虚拟页面块,将它们标记为无效(即未缓存),并将它们的页面表条目指向a.out中的适当位置。加载程序从不将任何数据从磁盘复制到内存中。第一次引用每个页面时,虚拟内存系统会根据需要自动将数据分页 我的问题是:假设程序在运行时将全局变量的值从2018更改为

我是Linux和虚拟内存的初学者,仍然在努力理解虚拟内存和可执行对象文件之间的关系

假设我们有一个可执行的对象文件a.out存储在硬盘上,并且假设最初a.out有一个.data部分,带有一个值为2018的全局变量。 当加载程序运行时,它分配一个连续的虚拟页面块,将它们标记为无效(即未缓存),并将它们的页面表条目指向a.out中的适当位置。加载程序从不将任何数据从磁盘复制到内存中。第一次引用每个页面时,虚拟内存系统会根据需要自动将数据分页

我的问题是:假设程序在运行时将全局变量的值从2018更改为2019,并且似乎包含全局变量的虚拟页面最终将分页到磁盘,这意味着.data部分的全局变量现在为2019,所以我们改变了不应该改变的可执行对象文件?否则,每次完成并再次运行程序时,我们都会得到不同的值?

通常(不是专门针对Linux)

启动可执行文件时,操作系统(内核)创建一个虚拟地址空间和一个(最初为空)进程,并检查可执行文件的头。可执行文件的头描述了“节”(例如
.text
.rodata
.data
.bss
,等等),其中每个节都有不同的属性-节的内容是否应该放在虚拟地址空间中(例如,是符号表或在运行时未使用的东西),内容是否为文件的一部分(例如
.bss
),以及该区域是否应为可执行、只读或读/写

通常,可执行文件的(使用部分)由虚拟文件系统缓存;VFS缓存中已经存在的文件片段可以映射(作为“写时复制”)到新进程的虚拟地址空间中。对于不在VFS缓存中的部分,这些文件片段可以作为“需要获取”映射到新进程的虚拟地址空间

然后启动进程(给定CPU时间)

如果进程从尚未加载的页面读取数据;操作系统(内核)暂停进程,将页面从磁盘上的文件提取到VFS缓存中,然后还将页面映射为“写时复制”到进程中;然后允许进程继续(允许进程重试读取未加载的页面,该操作将在页面加载后生效)

如果进程写入的页面仍然是“写时复制”;操作系统(内核)暂停进程,分配一个新页面并将原始页面的数据复制到其中,然后用进程自己的副本替换原始页面;然后允许进程继续(允许进程重试写入操作,该操作将在进程拥有自己的副本后生效)

如果进程从尚未加载的页面写入数据;操作系统(内核)结合了前面的两种功能(将原始页面从磁盘提取到VFS缓存中,创建一个副本,将进程的“副本”映射到进程的虚拟地址空间)

如果操作系统开始耗尽可用RAM;然后:

  • VFS缓存中的文件数据页,但没有作为“写时复制”与任何进程共享,可以在VFS中释放,而无需执行任何其他操作。下次使用该文件时,这些页面将从磁盘上的文件中提取到VFS缓存中

  • VFS缓存中的文件数据页以及与任何进程共享为“写时复制”的文件数据页可以在VFS中释放,并且任何/所有进程中的副本标记为“尚未获取”。下次使用文件时(包括进程访问“尚未获取”页面时),这些页面将从磁盘上的文件获取到VFS缓存中,然后在进程中映射为“写入时复制”)

  • 已修改的数据页(可能是因为它们最初是“写时复制”但被复制的,也可能是因为它们根本不是可执行文件的一部分-例如,
    .bss
    节、可执行文件的堆空间等)可以保存为交换空间,然后释放。当进程再次访问该页时,将从交换空间获取这些页

注意:如果可执行文件存储在不可靠的介质上(例如,可能被刮伤的CD),则“比一般更智能”的操作系统可能会在最初将整个可执行文件加载到VFS缓存和/或交换空间中;因为在进程使用文件时,除了使进程崩溃(例如,
SIGSEGV
)并使其看起来像可执行文件有错误外,没有合理的方法来处理“从内存映射文件读取错误”,并且因为这提高了可靠性(因为您依赖更可靠的交换,而不是不太可靠的刮擦CD)。此外,如果操作系统防止文件损坏或恶意软件(例如,在可执行文件中内置CRC或数字签名),则操作系统可能(应该)将所有内容加载到内存(VFS缓存)在允许执行可执行文件之前检查CRC或数字签名,以及(对于安全系统,如果在可执行文件运行时修改了磁盘上的文件)释放RAM时,可能会将未修改的页面存储在“更可信”的交换空间中(与页面被修改时相同),以避免从原始页面获取数据“不太可信”文件(部分原因是您不希望每次从该文件加载页面时都执行整个数字签名检查)

我的问题是:假设程序在运行时将全局变量的值从2018更改为2019,并且似乎包含全局变量的虚拟页面最终将分页到磁盘,这意味着