- 写代码
- 编译成 ELF 格式的二进制文件, 有三种格式(可重定位 .o 文件; 可执行文件; 共享对象文件 .so)
- 可重定位 .o 文件(ELF 第一种格式)
- .h + .c 文件, 编译得到**可重定位** .o 文件
- .o 文件由: ELF 头, 多个节(section), 节头部表组成(每个节有一项纪录); 节表的位置和纪录数由 ELF 头给出.
- .o 文件只是程序部分代码片段
- .rel.text 和 .rel.data 标注了哪些函数/数据需要重定位
- 要函数可被调用, 要以库文件的形式存在, 最简单是创建静态链接库 .a 文件(Archives)
- 通过 ar 创建静态链接库, 通过 gcc 提取库文件中的 .o 文件, 链接到程序中
- 链接合并后, 就可以定位到函数/数据的位置, 形成可执行文件
- 可执行文件(ELF 第二种格式)
- 链接合并后, 形成可执行文件
- 同样包含: ELF 头, 多个节, 节头部表; 另外还有段头表(包含段的描述, p_vaddr 段加载到内存的虚拟地址)
- ELF 头中有 e_entry , 指向程序入口的虚拟地址
- 共享对象 .so 文件(ELF 第三种格式)
- 静态链接库合并进可执行文件, 多个进程不能共享
- 动态链接库-链接了动态链接库的程序, 仅包含对该库的引用(且只保存名称)
- 通过 gcc 创建, 通过 gcc 链接
- 运行时, 先找到动态链接库(默认在 /lib 和 /usr/lib 找)
- 增加了 .interp 段, 里面是 ld_linux.so (动态链接器)
- 增加了两个节 .plt(过程链接表)和 .got.plt(全局偏移表)
- 一个动态链接函数对应 plt 中的一项 plt[x], plt[x] 中是代理代码, 调用 got 中的一项 got[y]
- 起始, got 没有动态链接函数的地址, 都指向 plt[0], plt[0] 又调用 got[2], got[2]指向 ld_linux.so
- ld_linux.so 找到加载到内存的动态链接函数的地址, 并将地址存入 got[y]
- 加载 ELF 文件到内存
- 通过系统调用 exec 调用 load_elf_binary
- exec 是一组函数
- 包含 p: 在 PATH 中找程序
- 不包含 p: 需提供全路径
- 包含 v: 以数字接收参数
- 包含 l: 以列表接收参数
- 包含 e: 以数字接收环境变量
- 进程树
- ps -ef: 用户进程不带中括号, 内核进程带中括号
- 用户进程祖先(1号进程, systemd); 内核进程祖先(2号进程, kthreadd)
- tty ? 一般表示后台服务
展开