20135337朱荟潼 Linux第七周学习总结——可执行程序的装载

朱荟潼 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

第七周 Linux内核如何装载和启动一个可执行程序

1. 理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节;

(1) 可执行程序怎么来的?

  • linux系统中,可执行程序一般要经过预处理、编译、汇编、链接、执行等步骤。

(2) 目标文件的格式ELF

(3) 静态链接的ELF可执行文件与进程的地址空间

  • 一般静态链接会将所有代码放入一个代码段;
  • 动态链接的进程会有多个代码段;

2. 新的可执行程序是从哪里开始执行的?为什么execve系统调用返回后新的可执行程序能顺利执行?对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时会有什么不同?

(1) 新的可执行程序起点

一般是地址空间为0x8048000或0x8048300;

(2) execve系统调用返回后新的可执行程序能顺利执行

execve和fork都是特殊一点的系统调用:一般的都是陷入到内核态再返回到用户态。

fork父进程和一般进程调度一样,子进程返回到一个特定的点ret_from_fork,子进程是从ret_from_fork开始执行然后返回到用户态;

execve特殊:执行到可执行程序--陷入内核--构造新的可执行文件--覆盖掉原可执行程序--返回到新的可执行程序,作为起点(也就是main函数) ,需要构造他的执行环境;

(3) Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数,先函数调用参数传递,再系统调用参数传递。

(4) 静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时不同

1. 静态链接:elf_entry指向可执行文件的头部,一般是main函数;
2. 动态链接:elf_entry指向ld的起点;

3. 使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve;

(1)更新menu;

(2)把init 和 hello 放到了rootfs.img目录下,所以在执行exec命令的时候就相当于自动了加载了hello程序;

(3)gdb进行跟踪分析;

(4)设置断点后,在MenuOS中输入exec进行调试分析;

  • 通过po new_ip和新窗口的 readelf -h helloc查看入口地址
  • hello的入口地址和new_ip的值都是0x8048d0a

4. 分析exec*函数对应的系统调用处理过程

exec会调用sys_execve---调用do_execve,调用do_execve_common(会把函数参数和系统环境传进来进行相应的处理。)---调用exec_binprm(执行相应的程序,其中,会调用search_binary_handler,这个函数会调用各种不同的格式来识别相应的文件)

5. 总结——“Linux内核装载和启动一个可执行程序”

1. 创建新进程
2. 新进程调用execve()系统调用执行指定的ELF文件
3. 调用内核的入口函数sys_execve(),sys_execve()服务例程修改当前进程的执行上下文;
(以上系统调用终止后,新进程开始执行放在可执行文件中的代码。)

当ELF被load_elf_binary()装载完成后,函数返回至do_execve()在返回至sys_execve()。ELF可执行文件的入口点取决于程序的链接方式:
1. 静态链接:elf_entry就是指向可执行文件里边规定的那个头部,即main函数处。
2. 动态链接:可执行文件是需要依赖其它动态链接库,elf_entry就是指向动态链接器的起点。
原文地址:https://www.cnblogs.com/zzzz5/p/5352557.html