购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.3 程序的装载与调度执行

2.3.1 可执行文件的装载

在shell提示符下运行可执行文件时,实际上相当于调用了execve()函数。此时操作系统会调用程序装载器。程序装载器会首先读取可执行文件并生成一个进程,并初始化对应的命令、数据和进程栈页表以及寄存器,然后执行一条跳转命令跳转到程序的第一条命令或程序入口点(_start符号的地址)开始执行Prog程序。

在32位Linux系统下,可执行文件装载进内存运行的镜像如图2.15所示。

图2.15 在32位Linux系统下可执行文件装载进内存运行的镜像

说明:

(1)可执行文件被装载的代码段起始地址。在默认情况下,32位Linux系统下可执行文件被装载的代码段起始地址为0x8048000,64位的Linux系统的起始地址为0x400000。可以使用如下命令查看:

如果要改变可执行文件被装载的代码段起始地址,如设置为0x80000,可以在链接阶段增加如下选项进行修改:

.bss和.data的选项依次为-Tbss org和-Tdata org。其中org是一个以十六进制数字表示的地址。

(2).data和.bss为静态数据区,当可执行文件被调度运行时,该文件会被复制到内存区域。堆和栈为动态数据区,其中,栈会根据函数的调用与返回动态变化,堆会根据用户的malloc()、free()函数动态变化。

(3).data以及其他段的地址。.data的起始地址是从代码段后的下一个4 KB对齐的地址。在运行可执行文件时,堆从接下来的下一个4 KB对齐的地址开始。堆之后有一个专门为共享库预留的段。在运行可执行文件时,用户栈从高地址往低地址增长。栈上的预留段供操作系统内核使用。 MhHeSO/CIwtqkU+CpU8ZvFU6A2fjPzN9z9NsJfk20CU/KPy97l8CLFgLRVWQtA3P



2.3.2 可执行文件调度运行的过程

可执行文件在被调度运行时需要读取ELF文件的头,操作系统内核只关心头中的三种类型条目:

(1)第一种条目是PT_LOAD,用于描述可执行文件被装载程序装载到内存后的运行区域,包括可执行文件的.text和.data以及.bss的大小,.bss将用0填充(因此只需将其长度存储在可执行文件中)。

(2)第二种条目是PT_INTERP,用于标识链接完整程序所需的运行时链接器名字,即动态链接器的名字。

(3)第三种条目是PT_GNU_STACK,如果该条目存在,则操作系统内核可以从该条目获取一个信息位,该信息位用于指示程序的栈是否可执行。

在Linux下可执行文件被调度运行的过程如图2.16所示:

第一步将可执行文件的PT_LOAD段装载进内存,创建程序的内存镜像,将.bss全部用0填充。

第二步检索头的PT_INTERP以及PT_GNU_STACK,使用PT_INTERP标识的动态链接器,如/lib64/ld-linux-x86-64.so.2,读取可执行文件依赖的所有库信息,在磁盘上搜索这些库,并将它们装载到内存中。

第三步执行重定位。需要执行重定位操作的有两个:

①共享库刚开始被装载到不确定的地址,需要重定位以确定其绝对地址。

图2.16 在Linux下可执行文件被调度运行的过程

②在多模块的工程中,一个目标文件对其他目标文件的引用也需要进行重定位,以确定其地址。

第四步调用注册在.preinit_array、.init、.init_array中的共享库初始化函数。

第五步将控制权传递给原始二进制文件的入口点,使用户感觉二进制文件是直接从exec传递过来的。 nbqPV3QHlnG5+ueEgrk0iqlDHMFrsaRreupj/Pr2oHygfq5wA8peORWnn7Hg9x1D



2.3.3 进程的虚拟地址空间及其访问

进程的虚拟地址空间(见图2.17)和体系结构有关。64位Linux系统的进程的虚拟地址空间大小为2 64 B。

图2.17 64位Linux的进程的虚拟地址空间

在Linux下,用户可以使用proc文件系统查看进程的虚拟地址空间。proc文件系统是一个伪文件系统,提供了访问内核数据结构的一个接口。

(1)/proc/[pid]/mem:进程的内存镜像,可以通过open()、read()和lseek()函数对该文件进行打开、读和查找操作。

(2)/proc/[pid]/maps包含进程的当前内存镜像以及各个区的访问权限。

下面举例说明proc文件系统的使用,被测的应用源码如Listing 2.22所示。

Listing 2.22 进程虚拟地址空间测试的应用源码loop.c

(1)访问进程空间的脚本文件:其功能是在进程的堆中搜索要查找的字符串,若找到,则用另一字符串进行替换,代码如Listing 2.23所示。

Listing 2.23 读取进程虚拟地址空间的脚本,read-write-heap.py

(2)脚本文件的运行,命令如下:

上述命令的作用是在进程4618的虚拟内存空间中查找字符串“Holberton”,找到后使用“Fun w vm!”进行替换。 nbqPV3QHlnG5+ueEgrk0iqlDHMFrsaRreupj/Pr2oHygfq5wA8peORWnn7Hg9x1D

点击中间区域
呼出菜单
上一章
目录
下一章
×