读书-程序员的自我修养-链接、封装与库(14: 第六章:可执行文件的装载与进程(2)从操作系统角度看可执行文件的装载

1. 从操作系统角度看可执行文件的装载

1.1 进程建立的三个步骤

从操作系统角度看,一个进程最关键的特征就是它拥有独立的虚拟地址空间。这使得它有别于其他进程。
但是一个进程的建立需要三个步骤

1.1.1 创建一个独立的虚拟地址空间

虚拟地址空间由一组页映射函数将虚拟空间的各个页映射到相应的物理地址。
创建虚拟地址空间的本质是:创建映射函数需要的数据结构。

1.1.2 建立虚拟空间和可执行文件的映射关系

其实这个关系就是:发生页错误时,OS应该知道程序当前需要的页在可执行文件中的哪一个位置。

映像文件(Image):
因为可执行文件在被装载时是被映射到虚拟地址空间的,所以很多时候可执行文件又被叫做映像文件。
这种映射关系也是保存在OS中的一个数据结构中的。

虚拟内存区域(VMA: Virtual Memory Area):
linux将进程虚拟空间中的一个段叫做虚拟内存区域。windows叫做虚拟段。

1.1.3 将cpu的指令寄存器设置为可执行文件的入口地址,执行它

可执行文件的入口地址就是elf的入口地址
Entry point address就是入口地址

root@ubuntu-admin-a1:/home# readelf -h simple.o
ELF Header:
……
Entry point address:               0x0
Start of program headers:          0 (bytes into file)
Start of section headers:          1056 (bytes into file)
……

1.2 为什么需要虚拟地址空间?

因为早期的计算机运行方式是直接将程序运行在物理内存上。这就存在三个问题:
问题1. 地址空间不隔离
所有进程都直接访问物理地址,程序使用的物理空间不是隔离的;
问题2. 运行效率低
监控程序直接将整个程序装入内存进行执行
问题3. 运行地址不确定
因为每次执行装入的物理地址是不确定的。

为了解决以上三个问题,增加了一个中间层,用来解决上面的问题。
那就是给出一个虚拟地址,然后通过一种映射关系,将其与物理地址进行映射,将虚拟地址转换成物理地址。
这样就能解决存在的问题1和问题3,问题2需要页映射来解决。

这个可以看之前的博客介绍。
https://blog.csdn.net/lqy971966/article/details/99533610

1.3 页错误

1.3.1 页错误定义

当cpu执行进程的某个页面时,发现这个虚拟空间中的页没有映射到内存中,而导致的中断。

1.3.2 页错误的处理

  1. 页错误发生后,操作系统去查询保存可执行文件和其进程虚拟空间映射关系的数据结构
  2. 找到空页面所在的VMA虚拟内存区域。然后通过它VMA计算出空页面在可执行文件中偏移
  3. 然后再物理内存中分配一个物理页面,并将该物理页和虚拟空间中虚拟页建立映射关系。
  4. 最后将cpu控制权返还给进程,从刚才页错误的地方继续执行。

如果这个页错误看不懂,没关系,请看我的页错误专门的一篇。相信可以帮助你。
https://blog.csdn.net/lqy971966/article/details/106910442

猜你喜欢

转载自blog.csdn.net/lqy971966/article/details/106910746