Linux内核分析第七周总结

第七章 可执行程序的装载

可执行程序的生成

可执行程序的生成:
c语言代码--->通过编译器的预处理--->编译成汇编代码--->由汇编器编译成目标代码--->连接成可执行文件
shell

预处理负责把include的文件包含进来及宏替换等工做函数

以HelloWorld.c文件做为例子:
操作系统

目标文件的格式

目标文件:命令行

  • 以".o"做为后缀的文件
  • 可执行文件

经常使用的目标文件格式:
3d

PE文件:Windos操做系统
ELF文件:Linux操做系统(可执行,可连接)指针

以ELF文件为例:(目标文件)blog

  • 可重定位文件(.o文件)
  • 可执行文件
  • 共享目标文件

静态连接的ELF可执行文件与进程的地址空间

默认从0x8048000处开始加载
可执行文件加载到内存中开始执行的第一行代码
通常静态连接会将全部代码放在一个代码段
动态连接的进程会有多个代码段进程

装载可执行程序以前的工做

可执行程序的执行环境
内存

命令行参数:编译器

  • shell命令行
  • main函数的参数
  • execve的参数

命令行参数和环境串都放在用户态堆栈中

在建立一个新的用户态堆栈的时候,其实是把命令行参数的内容和环境变量的内容经过指针的方式传递到系统调用的内核处理函数的,内核处理函数在建立一个新的可执行堆栈的时候会将命令行参数的内容和环境变量的内容拷贝到用户态堆栈里面来初始化新的可执行程序执行的上下文环境
shell程序 -> execve -> sys_execve
先函数调用参数传递,在系统调用参数传递

装载时动态连接和运行时动态连接应用举例

动态连接分为可执行程序装载时动态连接和运行时动态连接,以下代码演示了这两种动态连接。

  • 准备.so文件
  • 编译成libshlibexample.so文件
  • 编译成libdllibexample.so文件
  • 分别以共享库和动态加载共享库的方式使用libshlibexample.so文件和libdllibexample.so文件
  • 编译main

可执行程序的装载

  • 可执行程序的装载相关关键问题分析
    sys_execve内部会解析可执行文件格式
    do_execve -> do_execve_common -> exec_binprm

sys_execve的内部处理过程

装载和启动一个可执行程序依次调用如下函数:
sys_execve() -> do_execve() -> do_execve_common() -> exec_binprm() -> search_binary_handler() -> load_elf_binary() -> start_thread()

实验

总结:

当前进程的正文、数据、堆和栈段被exec覆盖了,当进程调用一种exec函数时,该进程执行的程序彻底替换为新程序,而新程序则从其main函数开始执行。 由于调用exec并不建立新进程,因此先后的进程ID并未改变。

相关文章
相关标签/搜索