在hust的nss实验室已经有一段时间了,期间主要做了,1)比较详细的学习了linux的配置与使用(但是离心目中的高手差距还是很大,以后还需要在正则表达式和shell编程上苦下工夫);2)比较努力的学习了linux内核,linux内核太神秘和博大精深了,以后的读研期间还应花费大量精力;3)移植了一个有关声卡的驱动程序,从intel 的mainstone上移植到上海一家公司的ivp上。实践不仅是检验真知的唯一方法而且也是学习真知的好方法。期间编写了不大不小的程序,linux下不象windows下有很多IDE开发平台(visual c++).但linux下的gcc真的很完美,它编译出的程序效率很高。正是因为linux下没有IDE,你不能象在windows下那样,用鼠标点下,一个程序就被编译出来了。IDE的出现虽然减轻了某些人的负担,但是它也隐藏了一个程序到底是怎么被编译出来的细节。而这隐藏的东西,我认为却是一个良好的程序员所必须理解并掌握的,否则他不是一个良好的程序员,至少不是我心目中的程序员。而linux下的gcc给我提供了这样的一个机会去了解它编译的宏观过程(抛开编译原理中的词法分析、语法分析等等,如果不是开发编译器我认为暂时可不需了解)。经验记录下来了才容易不被遗忘。以下就是所得。
#include<xxx.h> 与 #include"xxx.h"
这两种最基本包含头文件预定义,linux下<>包含的头文件通常在 /usr/include ; /usr/local/include;以""包含的头文件在当前目录下寻找。
linux下gcc的工作过程要经过预处理(preprocessing),编译(compilation),汇编(assembly)和连接(linking).源文件后缀名标识源文件的 语言,而对gcc来说,后缀名控制着缺省设定(.c .cxx .h .S 等等代表着c源程序、c++源程序、头文件、汇编程序)。而这四部分可以通过向gcc传递参数来分别执行。
-c 编译或汇编源文件,但是不作连接.编译器输出对应于源文件的目标文件
-S 编译后即停止,不进行汇编.对于每个输入的非汇编语言文件,输出文件是汇编语言文件.
-E 预处理后即停止,不进行编译.预处理后的代码送往标准输出.
-o file 指定输出文件为file.
在这里我要特别说明的是连接,为什么要连接,出现连接这种技术到底有什么用?对于cpu来说他就是不停的执行 取指令、分析指令、执行指令。而这些指令的逻辑顺序则是由程序员或者说是程序指定的。所谓c语言它仅仅是一种语言和所有的其他语言一样它仅仅是程序员用来和计算机交流的工具而已。当然程序员并不是和cpu直接交流的(机器语言时代早就过去了)程序员的思想用某种语言表达出来如c。编译器最终在把它编译出cpu能看懂的机器指令。
时间局部性、空间局部性是计算机世界中根古不变的基本定理。计算机大牛们总是以创造性的思想创造着和改变着计算机的世界。在诸多的程序中肯定有很多是相似的:基本上所有的程序都有输入、输出。输入输出的处理如果每个人都在自己的程序中来实现是非常不现实的:1)这通常要和硬件打交道,不是没个人都很好的操作硬件。2)即使每个人都牛到可以应用自如的来操作硬件,这些输入输出出现了很大的冗余(每个人都实现了一遍当然有很多冗余)。出现了冗余当然要消耗大量的存贮设备。3)一旦硬件发生了改变,所有依赖这些硬件工作的程序都要down掉 (how terrible).4)等等。。。如此看来迫切需要大牛们来创造性的解决这些问题。如此连接技术就应运而生了。一些基本的,诸多程序都要使用的功能,通常都有编译器的开发大牛们把他们实现并作成一个库。当然库也有,静态库、动态库。区分主要是一个在连接中连接到程序中,一个是在执行程序过程中才连接到程序中。后者更能节约存储资源。毕竟并不是所有的程序都在同时执行的(加载到内存)。后来又出现了更牛x的库,共享库。程序中有很多if,else语句,只有这些条件成立,在执行中对应的库才会动态加载。爱因斯坦说过时空是不可分离的。既然后者节约了空间,当然要浪费些时间。一句话:静态库(静态连接)浪费了空间,但是可以节约时间(在执行过程中省去了加载过程);动态库(动态连接)节约了空间但是要浪费点时间。
研究库的内容会发现主要是些符号(symbol)的实现:全局变量、函数。而连接的过程就是把某个源程序中对这些符号的引用对应起来。(有点表达不清楚了)。
基于这样的构想……待续 要去吃饭了:)
基于这样的思想。
作者在实验室学习了Linux配置与使用、Linux内核,移植声卡驱动程序。介绍了Linux下gcc编译器,它编译效率高,能让人了解编译宏观过程。还讲解了gcc工作过程,包括预处理、编译、汇编和连接,阐述了连接技术的作用及静态库、动态库的特点。
1338

被折叠的 条评论
为什么被折叠?



