可执行文件的装载与进程

本文详细介绍了可执行文件在进程中的装载过程,包括进程虚拟地址空间的分配、PAE扩展、装载方式(覆盖装入与页映射)、从操作系统角度的可执行文件装载步骤,以及进程虚存空间的分布。讨论了Linux内核如何装载ELF文件,并解释了堆和栈在进程地址空间中的位置。通过深入理解这些概念,读者可以更好地了解操作系统如何管理和执行程序。
摘要由CSDN通过智能技术生成

可执行文件的装载与进程

进程虚拟地址空间

程序与进程的区别?

  • 程序是一个静态的概念,就是一些预先编译好的指令和数据集合的一个文件

  • 进程则是一个动态的概念,它是程序运行时的一个过程,很多时候吧动态库也叫作运行时

每个程序被运行起来以后,它将拥有自己独立的虚拟地址空间(Virtual Address Space),这个虚拟地址空间的大小由计算机的硬件平台决定,**具体地说是由CPU的位数决定的。硬件决定了地址空间的最大理论上限,即硬件的寻址空间大小,**比如32位的硬件平台决定了虚拟地址空间的地址为0到232-1,即0x00000000~0xFFFFFFFF,也就是我们常说的4GB虚拟空间大小;而64位的硬件平台具有64位寻址能力,它的虚拟地址空间达到了264字节,即0x0000000000000000~0xFFFFFFFFFFFFFFFF,总共17179869184GB。

从程序的角度看,我们可以通过判断C语言程序中的指针所占的空间来计算虚拟地址空间的大小。一般来说,C语言指针大小的位数与虚拟地址空间的位数相同,如32位平台下的指针为32位,即4字节;64位平台下的指针为64位,即8字节。当然有些特殊情况下,这种规则不成立。

那么32位平台下的4GB虚拟空间,我们的程序是否可以任意使用呢?不行。因为程序在运行的时候处于操作系统的监管下,操作系统为了达到监控程序运行等一系列目的,进程的虚拟空间都在操作系统的掌握之中。进程只能使用那些操作系统分配给进程的地址,如果访问未经允许的空间,那么操作系统就会捕获到这些访问,将进程的这种访问当作非法操作,强制结束进程。我们经常在Windows下碰到”进程因非法操作需要关闭”或Linux下的”Segmentation fault”很多时候是因为访问了未经允许的地址。

图1.png
那么这4GB的进程虚拟地址空间是怎样的分配状态?以Linux OS为例子,默认下,Linux操作系统将进程的虚拟地址空间做了如下分配:

编译与链接

整个4GB被划分成两个部分,其中操作系统占用了一部分,从地址0xC0000000到0xFFFFFFF,共计1GB,剩下3GB给进程使用

PAE

在32位CPU下,程序的使用空间能不能超过4GB?

两个角度:

  • 空间指虚拟地址空间

那么不能,因为32位的CPU只能使用32位的指针,它的最大寻址范围为0 到 4GB

  • 空间指计算机的内存空间

那么可以,Intel从1995年CPU开始采用36位的物理地址,可以访问高达64GB的无压力内存

从硬件层面,原先32位地址线只能访问最大4GB的物理内存,但是只从扩展至36位地址线后,Intel修改了页映射的方式,使得新的映射方式可以访问到更多的物理内存,Intel把这个地址扩展方式叫做PAE

对于普通应用程序来说正常情况下感觉不到它的存在,因为这主要是操作系统的事,在应用程序里,只有32位的虚拟地址空间。那么应用程序该如何使用这些大于常规的内存空间呢?一个很常见的方法就是操作系统提供一个窗口映射的方法,把这些额外的内存映射到进程地址空间中来。在Windows下,这种访问内存的操作方式叫做AWE(Address Windowing Extensions);而像Linux等UNIX类操作系统则采用mmap()系统调用来实现。

装载的方式

程序执行时所需要的指令和数据必须在内存中才能够正常运行,最简单的方法就是将程序运行所需要的指令和数据全都装入内存中,这样程序就可以顺利运行,这就是最简单的静态装入的方法。但是很多情况下程序所需要的内存数量大于物理内存的数量,当内存的数量不够时,根本的解决办法就是添加内存。程序运行时是有局部性原理,所以我们可以将程序最常用的部分驻留在内存中,而将一些不太常用的数据存放在磁盘里面,这就是动态装入的基本原理。

覆盖装入(Overlay)和页映射(Paging)是两种很典型的动态装载方法,它们所采用的思想都差不多,原则上都是利用了程序的局部性原理。动态装入的思想就是程序用到哪个模块,就将哪个模块装入内存,如果不用就暂时不装入,存放在磁盘中。

覆盖装入

覆盖装入:在没有发明虚拟存储之前使用比较广泛,现在已经几乎被淘汰了。覆盖装入的方法把挖掘内存嵌入的任务交给了程序员,程序员在编写程序的时候必须手工将程序分割成若干块,然后编写一个小的辅助代码来管理这些模块何时应该驻留内存而何时应该被替换掉。这个小的辅助代码就是所谓的覆盖管理器(Overlay Manager)。覆盖装入是典型的利用时间换取空间的方法。

如下,一个程序有主模块main,main分别调用A和B模块。但是AB之间不会互相调用,三个模块大小:1024字节,512字节,256字节

不考虑内存对齐,装载地址限制的情况,理论上运行这个程序需要1792个字节的内存

采用覆盖装入办法,这样安排:

图2.png

由于AB之间相互调用依赖关系,可以把AB在内存中相互覆盖,两个模块共享内存,当main调用A,覆盖管理器保证将A从文件中读入内存,当main调用B,则覆盖管理器将B从文件中读入内存

页映射

页映射:是虚拟存储机制的一部分,它随着虚拟存储的发明而诞生。与覆盖装入的原理相似,页映射也不是一下子就把程序的所有数据和指令都装入内存,而是将内存和所有磁盘中的数据和指令按照”页(Page)”为单位划分成若干个页,以后所有的装载和操作的单位都是页。硬件规定页的大小有4096字节、8192字节、2MB、4MB等。

假设32位机器有16kb内存,每个页大小4096字节,共4个页

设程序所有指令与数据总和32kb,那么程序总共分为8个页,编号为P0-P7,那么16kb内存无法同时将32kb程序装入,那么就按照动态装入原理来进行

图示:<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值