运行Linux可执行文件的过程

3

在Linux中运行可执行文件时,有没有好的文档记录发生了什么。例如:我启动./a.out,那么可能会运行一些引导程序汇编(与c运行时一起?),它会在程序中找到起始符号,进行动态重定位,最后调用main

我知道上面的不正确,但我正在寻找详细的文档,说明这个过程是如何发生的。你能解释一下,或者指向链接或书籍吗?


http://linux.die.net/man/8/ld-linux以及其他相关信息页面可能会有所帮助。 - Torp
2个回答

5
对于动态链接的程序,内核会检测ELF文件中的PT_INTERP头部,并先将动态链接器(/lib/ld-linux.so.2或类似文件)映射到内存,并从动态链接器的主ELF头部的e_entry地址开始执行。栈的初始状态包含动态链接器需要找到主程序二进制文件(已经在内存中)的信息。它负责读取此信息并查找必须加载的所有其他库,加载它们,进行重定位,并跳转到主程序的e_entry地址。
对于静态链接的程序,内核直接使用主程序的ELF头部中的e_entry地址。
在任一情况下,主程序都以传统上称为_start的汇编例程开始(但名称不重要,只要其地址在ELF头部的e_entry字段中)。它使用初始堆栈内容来确定argcargvenviron等,并调用正确的实现内部函数(通常是用C语言编写的)来运行全局构造函数(如果有)和执行在进入main之前所需的任何libc初始化。这通常以调用exit(main(argc, argv));或等效函数结束。

谢谢,R,但内核如何知道程序是动态链接还是静态链接的呢?并且不是所有的Linux程序都是动态链接的吗?(至少使用libc是这样的吧?) - zaharpopov
尽管Drepper希望您必须动态链接所有内容,但不,没有必要使用动态链接。gcc -static会生成静态链接的二进制文件。内核通过ELF中存在或不存在PT_INTERP程序头来区分差异。 - R.. GitHub STOP HELPING ICE
R.. - 我在哪里可以找到动态链接器的源代码来学习?我的意思是 ld-linux 的源代码。 - zaharpopov
1
这是glibc的一部分,阅读起来相当笨拙... uClibc带有一个更简单的版本,可能更适合阅读和学习。 - R.. GitHub STOP HELPING ICE

1
一本名为“Linker and Loader”的书详细描述了加载过程,或许它能对你的问题有所帮助。

但它是否涉及现代Linux? - zaharpopov
它更多地讲述了一般原则。你可以按照@Torp的建议找到与Linux相关的文档。 - Summer_More_More_Tea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接