吕松鸿 原创作品转载请注明出处 《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000
一、预处理,编译,链接和目标文件格式
1.可执行程序是怎么得来的
c代码->预处理->汇编代码->汇编器->目标代码->链接成可执行文件->加载到内核执行
2.目标文件的格式ELF
符号修饰标准、变量内层布局、函数调用方式等这些跟可执行代码二进制兼容性相关的内容称为ABI(Application Binary Interface)
常见的ABI格式:
3.静态链接的ELF可执行文件和进程的地址空间
一般静态链接将会把所有代码放在同一个代码段。
动态连接的进程会有多个代码段。
二、可执行程序、共享库和动态链接
1.可执行程序的执行环境
命令行参数和shell环境,一般我们执行一个程序的Shell环境,我们的实验直接使用execve系统调用。 Shell本身不限制命令行参数的个数, 命令行参数的个数受限于命令自身。 shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数。 命令行参数和环境串都放在用户态堆栈中。
2.装载时动态链接和运行时动态链接应用举例
动态链接分为可执行程序装载时动态链接和运行时动态链接
三、可执行程序的装载
1. sys_execve内核处理过程
(1)新的可执行程序起点
一般是地址空间为0x8048000或0x8048300
(2)execve与fork
execve和fork都是特殊一点的系统调用:一般的都是陷入到内核态再返回到用户态。
-
fork两次返回,第一次返回到父进程继续向下执行,第二次是子进程返回到ret_from_fork然后正常返回到用户态。
-
execve执行的时候陷入到内核态,用execve中加载的程序把当前正在执行的程序覆盖掉,当系统调用返回的时候也就返回到新的可执行程序起点。
execve
- 执行到可执行程序 -> 陷入内核 - 构造新的可执行文件 -> 覆盖掉原可执行程序 - 返回到新的可执行程序,作为起点(也就是main函数) - 需要构造其执行环境;
- Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数,先函数调用参数传递,再系统调用参数传递。
(3)静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时不同
- 静态链接:elf_entry指向可执行文件的头部,一般是main函数,是新程序执行的起点。
2.动态链接的可执行程序的装载
- 动态链接库的依赖关系会形成一个图。
- load_elf_interp实际加载动态链接器,entry返回的是动态链接器的入口,根据需求加载动态链接库,根据库的需要再加载更多的库。
四、实验 Linux内核如何装载和启动一个可执行程序
1.下载新的代码文件
2.运行和gdb跟踪断点
来源:https://www.cnblogs.com/lv-20135229/p/5375478.html