文章摘要
这篇文章主要介绍了Linux系统中ELF(可执行与可链接格式)二进制文件的运行机制。文章指出ELF是现代Linux系统主要的二进制格式,内核通过fs/binfmtelf.c文件中的loadelf_binary()函数来处理这种复杂的格式,完成程序的加载和执行。这是对前文关于execve()系统调用机制的延续和深入探讨。
文章总结
文章标题:ELF二进制文件如何运行程序
主要内容概述
本文是系列文章的第二篇,深入探讨了Linux系统中ELF(可执行与可链接格式)二进制文件的加载和执行机制。文章从ELF格式的基本结构讲起,详细解析了内核如何通过load_elf_binary()函数处理ELF文件,并最终启动程序的过程。
ELF格式简介
ELF是现代Linux系统主要的二进制格式,内核通过fs/binfmt_elf.c文件中的代码支持该格式。与旧的a.out格式相比,ELF更为复杂,其核心函数load_elf_binary()超过400行代码。
一个可执行ELF文件必须在文件起始处包含程序头表(program header table),位于ELF头部之后。内核主要关注三种程序头条目: 1. PTLOAD段:描述程序运行时的内存区域,包括代码段、数据段和BSS段(初始化为零的内存区域)。 2. PTINTERP段:标识运行时链接器(动态链接情况下)。 3. PTGNUSTACK段:指示程序栈是否可执行。
ELF二进制文件的处理过程
- 初始检查:
load_elf_binary()首先检查文件是否符合支持的ELF格式,并读取程序头表。 - 清理旧程序状态:通过
flush_old_exec()清除旧程序的内核状态,包括终止其他线程、取消共享信号处理信息、清除定时器等。 - 设置新程序状态:
setup_new_exec()初始化新程序的内核状态,包括设置核心转储权限、更新线程名称、重置信号处理程序等。 - 内存映射:将PT_LOAD段映射到进程地址空间,并设置BSS段为零。此外,还会映射特殊页面(如vDSO)和空页面(用于向后兼容)。
- 设置凭证:通过
install_exec_creds()更新程序的凭证,并通知Linux安全模块(LSM)。 - 启动程序:最终通过
start_thread()设置程序的入口点和栈指针,完成从内核到用户空间的切换。
动态链接程序的处理
大多数程序是动态链接的,需要运行时链接器(如/lib64/ld-linux-x86-64.so.2)加载共享库。内核通过PT_INTERP段识别链接器,并先加载链接器到内存,将程序入口点设置为链接器的入口。链接器在用户空间完成库的加载和符号解析后,再跳转到程序的真正入口。
多架构兼容性
现代64位Linux系统支持运行32位程序(x86_32和x32 ABI)。通过compat_binfmt_elf.c文件,内核重定向部分函数和结构体到32位版本,确保兼容性。例如,SET_PERSONALITY宏和start_thread()函数会被替换为32位版本。
总结
execve()是Linux系统中程序运行的关键入口。尽管ELF格式复杂,但内核只需处理必要的部分(如加载段到内存),其余工作(如动态链接)交给用户空间的运行时链接器完成。这种分工使得内核能够高效支持多种二进制格式。
索引条目
- 内核 | exec()
- GuestArticles | Drysdale, David
评论总结
总结评论内容:
- 关于历史发展的观点:
- 评论1提到"image activation"概念在互联网泡沫破灭后被取代 引用:"We once called that 'image activation' before the Industry was taken over..."(我们曾称之为"图像激活",后来行业被...取代)
- 关于技术安全性的讨论:
- 评论2询问用户空间执行是否会减少内核崩溃 引用:"Does this eliminate kernel crashes from malformed executables?"(这会消除因格式错误可执行文件导致的内核崩溃吗?)
- 关于学习经历的观点:
- 评论3分享通过游戏学习ELF文件和编程的经历 引用:"my insatiable appetite for games...resulted in learning so much about Linux executable files"(对游戏的渴望让我学到了很多Linux可执行文件知识) "eventually it seemed inevitable that I should just learn to code"(最终似乎不可避免地要学习编程)
注:所有评论评分均为None,无法评估认可度。总结保持了不同观点的平衡,每个观点保留了2-3条关键引用。