一、可执行文件的生成
进程的未运行时的载体是可执行文件,一般放在磁盘或者ROM中,也就是我们常说的bin文件,linux /usr/bin/目录下的常用系统命令如ps、top、ls等都是可执行bin文件。一个进程是通过终端或者脚本启动可执行文件,而可执行文件是由C 程序通过执行gcc命令,经历预处理、编译、汇编、链接四个过程形成的,如下图所示:
其中 test.c是main函数所在文件,test2.c是test.c所调用到的自定义函数所在文件,最终链接生成a.out可执行文件,注意单个过程gcc 选项。
1、预处理
预处理主要功能:
1.执行展开宏
2.展开头文件
3.删除所有注释
4.删除所有预处理指令:#if #else #endif 等等
有兴趣的同学可以简单的编写一个打印 hello world 程序,然后单步执行gcc -E test.c -o test.i 生成预处理后形成的文件,分析test.i文件,就会豁然开朗许多、由于文件太大仅仅在main函数中调用一行printf代码,生成的预处理文件的行数就将近一千行。
2、编译
主要功能:
1.语法分析
2.词法分析
3.生成汇编语言
gcc -S test.i 生成test.s
3、汇编
主要功能:
1.转换成机械码也就是16进制文件
2.生成object file
3.此时已经是人类无法看懂的binary了
四、链接
主要功能:
1.链接生成可执行文件a.out
2.地址如函数地址重定位
二、链接方式
1. 静态链接:
i.生成方式 需要加上 -static选项:
ii.链接及映射到虚拟内存过程
2.动态链接:
i.生成方式,默认生成:
ii.链接及映射到虚拟内存过程
三、两者对比:
大小对比,如下图:
静态链接方式将目标文件main.o 与libc.a通过静态链接全部存储在a.out 中,然后映射在虚拟内存中的代码段与数据段等。这样的结果就是a.out占用磁盘空间大比动态的大100多倍,而动态链接是在程序运行时加载到虚拟内存中的,占用空间小,映射的虚拟内存位置也不同。