Linux 等操作系统如何将可执行文件加载到虚拟内存中?

问题描述

我已从以下链接阅读此声明:

Executable Object Files and Virtual Memory

一个可执行文件启动时,操作系统(内核)会创建一个虚拟地址空间和一个(最初为空的)进程,并检查可执行文件的头。

但我不明白 examines the executable file's header 是如何发生的?

在操作系统检查可执行文件的头文件之前,不应该首先将二进制文件加载到内存中吗? cpu不能直接在硬盘上运行指令。

我猜加载器应该能够在编译期间看到分配给二进制文件的地址并将它们映射到新创建的虚拟内存。

另外,如果操作系统加载了二进制文件,坐会完全加载吗?或者它会延迟加载并根据需要加载页面。最初会加载多少?

解决方法

在操作系统检查可执行文件的头文件之前,不应该首先将二进制文件加载到内存中吗?

好吧,这一步只需要将二进制文件的加载到内存中。内核加载头文件并检查它以查看如何为二进制文件的各个部分设置映射。例如,标头可能会说“将二进制文件的 4096-65535 字节映射到地址 0x12345000 处的内存中,只读且可执行”; “在地址 0xdeadf000 处映射 16384 字节的零初始化内存,读写”等。设置这些映射后,内核不再需要在内存中保留二进制文件的头文件,并且可以释放该空间。

此外,如果操作系统加载了二进制文件,它是否会完全加载?

没有

或者它会延迟加载并在之后根据需要加载页面。

是的。

最初会加载多少?

可能根本没有。当进程实际访问内存时,它可以依赖页面错误处理程序来执行此操作。在这种情况下,sysret 或内核用于将控制转移到程序入口点的任何指令本身都会导致页面错误,此时包含入口点第一条指令的页面将从由该地址的映射指定的二进制文件。当故障处理程序返回时,第一条指令将在内存中并被执行。随着进程执行更多涉及更多内存的指令,将加载越来越多的页面。

作为一种优化,内核可以根据对哪些页面可能在不久的将来被访问的猜测,将其中一些页面预置到内存中。我不知道具体到什么程度。