读书频道 > 系统 > linux > 深度探索Linux操作系统系统构建和原理解析
2.1 编译过程
2013-09-28 11:40:35     我来说两句 
收藏    我要投稿   
全书一共8章:第1章介绍了如何准备工作环境。在第2章中构建了编译工具链,这是后面构建操作系统各个组件的基础。在这一章中,不仅详细讲解了工具链的构建过程,而且还通过对编译链接过程的探讨,深入讨论了工具链  立即去当当网订购

在Linux系统上,通常,只需使用gcc就可以完成整个编译过程。但不要被gcc的名字误导,事实上,gcc并不是一个编译器,而是一个驱动程序(driver program)。在整个编译过程中,gcc就像一个导演一样,编译过程中的每一个环节由具体的组件负责,如编译过程由cc1负责、汇编过程由as负责、链接过程由ld负责。

我们可以通过传递参数“-v”给gcc来观察一个完整的编译过程中包含的步骤,下面是一个典型的编译过程中gcc的输出信息,为了更清楚地看到编译过程中的主要步骤,对输出信息进行了适当删减。
root@baisheng:~/demo# gcc -v main.c
...
/usr/lib/gcc/i686-linux-gnu/4.7/cc1 -quiet -v –imultiarch
i386-linux-gnu main.c -quiet -dumpbase main.c -mtune=generic
-march=i686 -auxbase main -version -fstack-protector -o
tmp/ccYBInzt.s
...
as -v --32 -o /tmp/ccj54pkM.o /tmp/ccYBInzt.s
...
/usr/lib/gcc/i686-linux-gnu/4.7/collect2 --sysroot=/ --build-id
--no-add-needed --as-needed --eh-frame-hdr -m elf_i386
--hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 -z relro
usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o
/usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu/crti.o
/usr/lib/gcc/i686-linux-gnu/4.7/crtbegin.o
-L/usr/lib/gcc/i686-linux-gnu/4.7
-L/usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu
-L/usr/lib/gcc/i686-linux-gnu/4.7/../../../../lib
-L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu
-L/usr/lib/../lib -L/usr/lib/gcc/i686-linux-gnu/4.7/../../..
/tmp/ccj54pkM.o -lgcc --as-needed -lgcc_s --no-as-needed -lc –lgcc
--as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/i686-linux-gnu/4.7/crtend.o
/usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu/crtn.o

根据gcc的输出可见,对于一个C程序来说,从源代码构建出可执行程序经过了三个阶段:

(1)编译

gcc调用编译器cc1进行编译,产生的汇编代码保存在目录/tmp下的文件ccYBInzt.s中。

(2)汇编

gcc调用汇编器as,汇编编译过程产生汇编文件cca2nBio.s,产生的目标文件保存在目录/tmp下的文件ccj54pkM.o中。

(3)链接

我们看到,gcc并没有如我们想象的那样直接调用ld进行链接,而是调用collect2进行链接。实际上,collect2只是一个辅助程序,最终它仍将调用链接器ld完成真正的链接过程。举个例子,对于C++程序来说,在执行main函数前,全局静态对象必须构造完成。也就是说,在main之前程序需要进行一些必要的初始化,gcc就是使用collect2安排初始化过程中如何调用各个初始化函数的。根据链接过程可见,除了main.c对应的目标文件ccj54pkM.o外,ld也链接了libc、libgcc等库,以及所谓的包含启动代码(start code)的启动文件(start/startup file),包括crt1.o、crti.o、crtbegin.o、crtend.o和crtn.o。

事实上,对于C程序来说,编译过程也可以拆分为两个阶段:预编译(或称为编译预处理)和编译。所以,软件构建过程通常分四个阶段:预编译、编译、汇编以及链接,如图2-1所示。

在接下来讨论编译过程的章节中,如无特殊说明,都将以下面的程序为例。
foo1.c:
int foo1 = 10;
void foo1_func()
{
    int ret = foo1;
}
foo2.c:
int foo2 = 20;
void foo2_func(int x)
{
    int ret = foo2;
}
hello.c:
#include <stdio.h>
extern int foo2;
int main(int argc, char *argv[])
{
    foo2 = 5;
    foo2_func(50);
    return 0;
}

 

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:概述
下一篇:2.1.1 预编译
相关文章
图文推荐
3.3.6 GNOME的软件管
3.3.5 GNOME的文件管
3.3.4 GNOME的窗口管
3.3.3 收藏夹和快捷
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站