x86 - Linux 等操作系统如何将可执行文件加载到虚拟内存中?
问题描述
我已从此链接阅读此声明:
当一个可执行文件启动时,操作系统(内核)创建一个虚拟地址空间和一个(最初为空的)进程,并检查可执行文件的头文件。
但我不明白这是怎么回事examines the executable file's header
?
在操作系统可以检查可执行文件的标头之前,不应该将二进制文件加载到内存中吗?CPU 不能直接在 HDD 上运行指令。
我猜加载器应该能够在编译期间看到分配给二进制文件的地址,并将它们映射到新创建的虚拟内存。
此外,如果二进制文件由操作系统加载,是否会完全加载?或者它会延迟加载并根据需要加载页面。最初会加载多少?
解决方案
在操作系统可以检查可执行文件的标头之前,不应该将二进制文件加载到内存中吗?
好吧,这一步只需要将二进制文件的头文件加载到内存中。内核加载头文件并检查它以查看如何为二进制文件的各个部分设置映射。例如,标头可能会说“将二进制文件的字节 4096-65535 映射到地址 0x12345000 的内存中,只读且可执行”;“在地址 0xdeadf000 处映射 16384 字节的零初始化内存,读写”,等等。建立这些映射后,内核不再需要将二进制文件的标头保存在内存中,并且可以释放该空间。
此外,如果二进制文件由操作系统加载,它会完全加载吗?
不。
或者它会延迟加载并在之后根据需要加载页面。
是的。
最初会加载多少?
可能根本没有。当进程实际访问内存时,它可以依赖页面错误处理程序来执行此操作。在这种情况下sysret
, 或者内核用来将控制权转移到程序入口点的任何指令本身都会导致页面错误,此时包含入口点处第一条指令的页面将从二进制文件中加载该地址的映射。当故障处理程序返回时,第一条指令将在内存中并被执行。随着进程执行更多涉及更多内存的指令,将加载越来越多的页面。
作为一种优化,内核可以根据对在不久的将来可能访问哪些页面的猜测,将其中一些页面预置到内存中。我不知道具体做到了什么程度。
推荐阅读
- c# - 读取 IP (UDP) 数据并保存为音频文件格式
- angular - 通过传递参数从 NGXS 中的状态中选择值
- mysql - 无法将数据从文本文件加载到 MySQL 表
- mysql - 使用多个选择连接表
- google-cloud-platform - 大查询:查询失败。未找到数据集
- sparql - 是否可以在 SPARQL 中获取嵌套的 json 输出?
- jakarta-mail - 春天邮件。javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接
- c - 使用枚举作为常量时 c 编译器的意外行为
- javascript - 在没有id和类的html表中创建行
- python-3.x - 未找到:关键变量_
在检查点找不到