Linux下GUN之GCC编译器

gcc是一款linux Gun计划当中的一款编译工具,用于编译C语言文件。
其显著特点就是可以交叉编译。
说道交叉编译
首先因为汇编语言的特点是,能够直接访问硬件,并且每款CPU都有自己的汇编语言。
由于嵌入式系统需要进行操作系统的移植,并且在主机上开发的软件程序需要跑到特点的嵌入式系统中,不同的嵌入式系统所用到的处理器也是不同的
如PC机CPU采用的是X86架构,即对应x86版汇编
手机大多数采用ARM体系架构 即对应 ARM汇编。
由此需要在当前CUP平台去编译出能在其它CPU平台所运行的程序时,就叫交叉编译。
此时就要安装交叉编译器(ARM-LINUX-GG等)。

在C语言源文件到可执行文件的过程经历:预处理->编译->汇编->链接 。
再次每个阶段完成的工作:
预处理:1.头文件展开 2. 宏替换 3.条件编译 可使用-E 选项在预处理完成后停止,从而生成.i文件
打开.i文件可以看到头文件被展开,以及定义的宏被替换,以及进行条件编译。
另外在C语言引入头文件方式有两种 “<>”, " ",两种方式,其中 <>在预处理进行头文件展开时,先去根目录下user/inlcude目录下去寻找头文件,再到当前目录找。而 " " 则相反。
当我们使用“ ”引入头文件时,如果头文件路径出现变化,可以通过 -I 选项指定头文件第三放搜索路径
如 gcc x.c -I …/include 就可以省去修改代码的时间

然后就是宏替换以及条件编译
在我们源文件定义一个宏时 #define max 100,生成的.i文件中max会自动替换成100

条件编译适用于开发过程中用户对功能的要求,可以选择大段注释 #ifndefine/#if … #enif再加上宏的定义来实现如 #ifndefi max 100
{
…代码块
}
#endif
{
…代码块
}
但是条件编译不能再源文件宏定义的上方,可以使用宏的定义判断实现宏定义。

由此gcc还提供在终端像源文件加入宏定义 如 gcc hello.c Dmax = 100
但是在预处理过程中不对源文件做语法检查,导致如果我们定义一些宏出现错误,还是一样傻瓜式去替换。

编译-c 在编译过程中停下生成 .o文件,此时进行语法检查,词法分析,还进行编译优化,去掉一些无用变量;

汇编-S 在汇编阶段停下,生成.s文件,将.o文件生成汇编文件,此时打开.o文件全为汇编代码
此时当我们对硬件访问时,C语言和汇编的选择:
汇编对硬件的访问速度快,到时C语言是高级语言有if while等语句,所有在对硬件做简单操作时,选用汇编语言,复杂操作时使用C语言

链接生成可执行文件 链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,最终生成可以在特定平台运行的可执行程序。
crt1.o、crti.o、crtbegin.o、crtend.o、crtn.o是gcc加入的系统标准启动文件,

一般应用程序才需要系统标准启动文件和标准库文件。、

裸机 /BootLoader、linux内核灯程序不需要启动文件、标准库文件。

其中链接方式有两种
动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加载所需的动态库才能巡行。

动态链接生成的程序体积较小,但是必须依赖所需的动态库,否则无法执行。

静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,

不过静态链接生成的程序比较大
如我们手机软件更新就链接动态库,而不是静态库,如果我们写一个已经功能不再更新完善的程序时使用静态库。

其它编译选项:
-w 关闭警告信息,不建议使用 -Wall 列出警告信息

-o 生成文件重命名

-o1, -o2, -o3 编译器优化选项
-O1:这是最基本的优化等级。编译器会在不花费太多编译时间的同时试图生成更快更小的代码。这些优化是非常基础的,但一般这些任务肯定能顺利完成。
-O2:-O1的进阶。这是推荐的优化等级,除非你有特殊的需求。-O2会比-O1启用多一些标记。设置了-O2后,编译器会试图提高代码性能而不会增大体积和大量占用的编译时间。
-O3:这是最高最危险的优化等级。用这个选项会延长编译代码的时间,并且在使用gcc4.x的系统里不应全局启用。自从3.x版本以来gcc的行为已经有了极大地改变。在3.x,-O3生成的代码也只是比-O2快一点点而已,而gcc4.x中还未必更快。用-O3来编译所有的软件包将产生更大体积更耗内存的二进制文件,大大增加编译失败的机会或不可预知的程序行为(包括错误)。这样做将得不偿失,记住过犹不及。在gcc 4.x.中使用-O3是不推荐的。
-O1
优化.对于大函数,优化编译占用稍微多的时间和相当大的内存.

不使用`-O’选项时,编译器的目标是减少编译的开销,使编译结果能够调试.语句是独立的:如果在 两条语句之间用断点中止程序,你可以对任何变量重新赋值,或者在函数体内把程序计数器指到其他语句,以及从源程序中 精确地获取你期待的结果.

不使用-O'选项时,只有声明了register的变量才分配使用寄存器.编译结果比不用-O’选项的PCC要略逊一筹.

使用了`-O’选项**,编译器会试图减少目标码的大小和执行时间.**

如果指定了-O'选项,-fthread-jumps’和-fdefer-pop'选项将被 打开.在有delay slot的机器上,-fdelayed-branch’选项将被打开.在即使没有帧指针 (frame pointer)也支持调试的机器上, `-fomit-frame-pointer’选项将被打开.某些机器上 还可能会打开其他选项.

-O2

多优化一些**.除了涉及空间和速度交换的优化选项,执行几乎所有的优化工作.**例如不进行循环展开(loop unrolling)和函数内嵌(inlining).和-O选项比较,这个选项既增加了编译时间,也提高了生成代码的 运行效果.

-O3

优化的更多.除了打开-O2所做的一切,它还打开了-finline-functions选项.

查看一个程序运行的时间time指令

1)实际时间(real time): 从command命令行开始执行到运行终止的消逝时间;

2)用户CPU时间(user CPU time): 命令执行完成花费的用户CPU时间,即命令在用户态中执行时间总和;

3)系统CPU时间(system CPU time): 命令执行完成花费的系统CPU时间,即命令在核心态中执行时间总和。

其中,用户CPU时间和系统CPU时间之和为CPU时间,即命令占用CPU执行的时间总和。实际时间要大于CPU时间,因为Linux是多任务操作系统,往往在执行一条命令时,系统还要处理其它任务。

另一个需要注意的问题是即使每次执行相同命令,但所花费的时间也是不一样,其花费时间是与系统运行相关的。

例如:
$ time foo
real 0m0.003s
user 0m0.000s
sys 0m0.004s$

也可以这么理解
real time是时钟走过的时间,user time 是程序在用户态的cpu时间,sys time 为程序在核心态的cpu时间。
我来讲一下用户态和核心态:
核心态(Kernel Mode):
在内核态,代码拥有完全的,不受任何限制的访问底层硬件的能力。可以执行任意的CPU指令,访问任意的内存地址。内核态通常情况下都是为那些最底层的,由操作系统提供的,可信可靠的代码来运行的。内核态的代码崩溃将是灾难性的,它会影响到整个系统。

—– In Kernel mode, the executing code has complete and unrestricted access to the underlying hardware. It can execute any CPU instruction and reference any memory address. Kernel mode is generally reserved for the lowest-level, most trusted functions of the operating system. Crashes in kernel mode are catastrophic; they will halt the entire PC.

用户态(User Mode):
在用户态,代码不具备直接访问硬件或者访问内存的能力,而必须借助操作系统提供的可靠的、底层的API来访问硬件或者内存。由于这种隔离带来的保护作用,用户态的代码崩溃(Crash),系统是可以恢复的。我们大多数的代码都是运行在用户态的。

—– In User mode, the executing code has no ability to directly access hardware or reference memory. Code running in user mode must delegate to system APIs to access hardware or memory. Due to the protection afforded by this sort of isolation, crashes in user mode are always recoverable. Most of the code running on your computer will execute in user mode.

发布了23 篇原创文章 · 获赞 9 · 访问量 1694

猜你喜欢

转载自blog.csdn.net/weixin_42590177/article/details/88971115