Linux内核如何装载和启动一个可执行程序
摘要: mqy + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
可执行文件的格式
在 Linux 平台下主要有以下三种可执行文件格式:
1、a.out(assembler and link editor output 汇编器和链接编辑器的输出)
2、COFF(Common Object File Format 通用对象文件格式)
3、ELF(Executable and Linking Format 可执行和链接格式)。
在本课程中,主要介绍的是ELF文件。ELF 文件又分为三种类型:共享目标文件(库文件,后缀为.so)、可执行文件、可重定位文件(目标文件,后缀为.o)。
可执行文件的创建过程
从 C/C++ 源文件生成一个可被系统加载和启动的可执行文件,需要经过预处理、编译和链接这几个过程。
预处理:把include 的文件包含进来,进行宏替换等。
编译:编译器将预处理文件编译成汇编代码;汇编器将汇编代码编译成目标代码
链接:将目标代码链接为可执行文件。根据链接方式的不同,可分为静态链接与动态链接。动态链接又可分为可执行程序装载时动态链接与运行时动态链接。
预处理:加入头文件执行宏替换等操作 gcc -E hello.c -o hello.i
编译:检查无误后转为汇编语言 gcc –S hello.i –o hello.s
汇编:转为二进制 gcc –c hello.s –o hello.o
链接:生成可执行文件 gcc hello.o –o hello
一步完成的命令为:gcc hello.c -o hello
elf文件分为可重定位文件、可执行文件、共享文件等
查看elf文件的文件头可以用readelf
程序的入口地址是0x8048000
可执行文件(ELF文件)的装载与启动过程
一个可执行文件是由 shell 程序启动的。在 shell 环境下,用户输入可执行程序名及其参数后,shell 程序会调用 execve 将命令行参数和环境参数传递给可执行程序的main函数。通过以下层层调用,最终完成可执行程序的启动过程:
do_execve-->do_execve_common-->exec_binprm-->search_binary_handler-->load_elf_binary-->start_thread
实验:
gdb跟踪内核函数sys_execve处理过程
内核准备
执行exec
gdb调试
执行结果
单步运行,可以看到do_execv函数
执行到start_thread查看入口地址
与readelf的结果一致