计算机那些事(6)——可执行文件的装载与运行

本文详细解析了在Linux系统中执行ELF可执行文件的过程,包括创建新进程、检查文件类型、搜索装载处理过程及最终的装载执行。通过深入探讨ELF文件的装载机制,帮助读者理解Linux环境下程序执行的底层原理。

当我们在 Linux 的 bash 中输入命令执行某个 ELF 可执行文件时,如下所示。

1
$ ./hello.out

那么,Linux 系统是如何装载该 ELF 文件并执行的呢?这个过程可以分为以下这些步骤:

  • 创建新进程
  • 检查可执行文件类型
  • 搜索匹配装载处理过程
  • 装载执行可执行文件

创建新进程

首先在用户层面,bash 进程会调用 fork() 系统调用创建一个新的进程。其次,新的进程通过调用 execve() 系统调用来执行指定的 ELF 文件。原先的 bash 进程继续返回并等待刚才启动的新进程结束,之后继续等待用户输入命令。

execve() 系统调用被定义在 unistd.h,其原型如下所示。其中的三个参数分别对应被执行程序的 程序文件名执行参数环境变量

1
int execve(const char *filename, char *const argv[], char *const envp[]);

 

检查可执行文件类型

当进入 execve() 系统调用之后,Linux 内核就开始进行真正的装载工作。在内核中,execve() 系统调用相应的入口是 sys_execve()sys_execve() 进行一些参数的检查复制之后,调用 do_execve()do_execve() 会首先查找被执行的文件,如果找到文件,则读取文件的前 128 个字节。

为什么要先读取文件的前 128 个字节?这是因为Linux支持的可执行文件不止 ELF 一种,还包括 a.outJava 程序以 #! 开头的脚本程序do_execve()通过读取前 128 个字节来判断文件的格式。每种可执行文件格式的开头几个字节都是很特殊的,尤其是前4个字节,被称为 魔数(Magic Number)。比如:ELF的可执行文件格式的头 4 个字节为 0x7Felf;Java的可执行文件格式的头 4 个字节为 cafe;如果是解释型语言的脚本,则第一行通常是 #!/bin/sh 或 #!/user/bin/python,其中 # 和 ! 构成了魔数,系统一旦判断到这两个字节,就对后面的字符串进行解析,以确定具体的解释程序的路径。

搜索匹配装载处理过程

当 do_execve() 读取了128个字节的文件头部之后,调用 search_binary_handle() 去搜索和匹配合适的可执行文件装载处理过程。Linux 中所有被支持的可执行文件格式都有相应的装载处理过程search_binary_handler() 会通过判断头部的魔术确定文件的格式,并且调用相应的装载处理过程。常见的可执行程序及其装载处理过程的对应关系如下所示.

  • ELF 可执行文件:load_elf_binary()
  • a.out 可执行文件:load_aout_binary()
  • 可执行脚本程序:load_script()

装载执行可执行文件

以 ELF 的装载处理过程 load_elf_binary() 为例,其所包含的步骤如下图所示:

  1. 操作系统读取可执行文件 ELF 的 Header,检查文件的有效性。
  2. 操作系统读取可执行文件 ELF的 Program Header Table 中读取每个 Segment 的虚拟地址、文件地址、属性等。
  3. 操作系统根据 Program Header Table 将可执行文件 ELF 映射至内存。
  4. 如果是静态链接的情况,则直接跳转至第 7 步;如果是动态链接的情况,操作系统将查找 .interp 节,找到 动态链接器(Dynamic Linker) 的位置,并启动动态链接器。在 Linux 下,动态链接器 ld.so 是一个共享对象,操作系统同样通过映射的方式将它加载到进程的地址空间。操作系统在加载完后,将控制权交给动态链接器的入口。
  5. 动态链接器获得控制权后,开始执行一系列初始化操作。
  6. 动态链接器根据当前的环境参数,对可执行文件进行动态链接工作。
  7. 控制权被转交到可执行文件的入口地址,程序开始正式执行。

参考

  1. 《程序员的自我修养——链接、装载与库》
  2. 《深入理解计算机系统》

(完)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值