可执行程序的生成:
c语言代码--->通过编译器的预处理--->编译成汇编代码--->由汇编器编译成目标代码--->连接成可执行文件
shell
预处理负责把include的文件包含进来及宏替换等工做函数
以HelloWorld.c文件做为例子:
操作系统
目标文件:命令行
经常使用的目标文件格式:
3d
PE文件:Windos操做系统
ELF文件:Linux操做系统(可执行,可连接)指针
以ELF文件为例:(目标文件)blog
默认从0x8048000处开始加载
可执行文件加载到内存中开始执行的第一行代码
通常静态连接会将全部代码放在一个代码段
动态连接的进程会有多个代码段进程
可执行程序的执行环境
内存
命令行参数:编译器
在建立一个新的用户态堆栈的时候,其实是把命令行参数的内容和环境变量的内容经过指针的方式传递到系统调用的内核处理函数的,内核处理函数在建立一个新的可执行堆栈的时候会将命令行参数的内容和环境变量的内容拷贝到用户态堆栈里面来初始化新的可执行程序执行的上下文环境
shell程序 -> execve -> sys_execve
先函数调用参数传递,在系统调用参数传递
动态连接分为可执行程序装载时动态连接和运行时动态连接,以下代码演示了这两种动态连接。
装载和启动一个可执行程序依次调用如下函数:
sys_execve() -> do_execve() -> do_execve_common() -> exec_binprm() -> search_binary_handler() -> load_elf_binary() -> start_thread()
当前进程的正文、数据、堆和栈段被exec覆盖了,当进程调用一种exec函数时,该进程执行的程序彻底替换为新程序,而新程序则从其main函数开始执行。 由于调用exec并不建立新进程,因此先后的进程ID并未改变。