写代码:用系统调用创建进程
产生代码.
进行编译:程序的二进制格式
.o
文件
ELF 的第一种类型,可重定位文件(Relocatable File).
- .text:放编译好的二进制可执行代码
- .data:已经初始化好的全局变量
- .rodata:只读数据,例如字符串常量、const 的变量
- .bss:未初始化全局变量,运行时会置 0
- .symtab:符号表,记录的则是函数和变量
- .strtab:字符串表、字符串常量和变量名
- Section Header Table: 保存各 section 的元信息
可重定位:
- 引入了其他文件, 位置不确定
可执行文件是 ELF 的第二种格式:
动态链接库,就是 ELF 的第三种类型,共享对象文件(Shared Object):
- 首先,多了一个.interp 的 Segment,这里面是 ld-linux.so,这是动态链接器,也就是说,运行时的链接动作都是它做的。
- 另外,ELF 文件中还多了两个 section,一个是.plt,过程链接表(Procedure Linkage Table,PLT),一个是.got.plt,全局偏移量表(Global Offset Table,GOT)。
运行程序为进程
exec 比较特殊,它是一组函数:
- 包含 p 的函数(execvp, execlp)会在 PATH 路径下面寻找程序;
- 不包含 p 的函数需要输入程序的全路径;
- 包含 v 的函数(execv, execvp, execve)以数组的形式接收参数;
- 包含 l 的函数(execl, execlp, execle)以列表的形式接收参数;
- 包含 e 的函数(execve, execle)以数组的形式接收环境变量。
进程树
你会发现,PID 1 的进程就是我们的 init 进程 systemd,PID 2 的进程是内核线程 kthreadd,这两个我们在内核启动的时候都见过。其中用户态的不带中括号,内核态的带中括号。