一、什么是开放源码、编译程序和可执行文件
1、可执行文件
Linux系统上真正识别的可执行文件其实是二进制文件,例如/usr/bin/passwd这些文件即为二进制程序代码。
或许你会说shell script不是也可以执行么?其实shell scrpit只是利用shell这个程序的功能进行一些判断式,而最终执行的除了bash提供的功能外,仍是调用一些已经编译好的二进制程序来执行的呢。
如何知道一个文件是否为二进制呢?使用file命令
file /bin/bash
如果是二进制程序而且是可以执行的,它就会显示可执行文件类( ELF 64-bit LSB executable),同时会说面是否使用共享库(shared libs)。
2、编译程序
既然linux操作系统真正执行的是二进制程序,那么我是如何做出这样的一个二进制的程序呢?
- 首先,我们必须要写程序,用什么东西写程序呢?就是一般的文本处理器啊。写完的程序就是所谓的源代码。这个程序代码文件其实就是一般的纯文本文件。
- 在完成这个源码文件的编写之后,再来就是要将这个文件”编译“成为操作系统看得懂的二进制程序。而要编译自然就需要”编译程序“来操作,经过编译程序的编译与连接之后,就会生成一个可以执行的二进制程序。
事实上,在编译的过程中还会生成所谓的目标文件(object file),这些文件是以*.o的扩展名形式存在的。至于C语言的源代码文件通常以*.c作为扩展名。
此外,有的时候,我们会在程序当中引用、调用其他的外部子程序,或者是利用其他软件提供的”函数功能“,这个时候,我们就会必须要在编译的过程当中将函数库加进去,如此一来,编译程序就可以将所有的程序代码与函数库做一个链接(link)以生成正确的执行文件。
总结:
- 开放源码:就是程序代码,写给人类看的程序语言,但机器并不认识,所以无法执行;
- 编译程序:将程序代码转译为机器看得懂的语言,就类似翻译者的角色;
- 可执行文件:经过编译程序变成二进制程序后机器看得懂所以可以执行的文件。
二、什么是函数库
Linux 系统中存在大量的函数库。简单来讲,函数库就是一些函数的集合,每个函数都具有独立的功能且能被外界调用。我们在编写代码时,有些功能根本不需要自己实现,直接调用函数库中的函数即可。
需要注意的是,函数库中的函数并不是以源代码的形式存在的,而是经过编译后生成的二进制文件,这些文件无法独立运行,只有链接到我们编写的程序中才可以运行。
Linux 系统中的函数库分为 2 种,分别是静态函数库(简称静态库)和动态函数库(也称为共享函数库,简称动态库或共享库),两者的主要区别在于,程序调用函数时,将函数整合到程序中的时机不同:
- 静态函数库在程序编译时就会整合到程序中,换句话说,程序运行前函数库就已经被加载。这样做的好处是程序运行时不再需要调用外部函数库,可直接执行;缺点也很明显,所有内容都整合到程序中,编译文件会比较大,且一旦静态函数库改变,程序就需要重新编译。
- 动态函数库在程序运行时才被加载(如图 1 所示),程序中只保存对函数库的指向(程序编译仅对其做简单的引用)。
-
使用动态函数库的好处是,程序生成的可执行程序体积比较小,且升级函数库时无需对整个程序重新编译;缺点是,如果程序执行时函数库出现问题,则程序将不能正确运行。
Linux 系统中,静态函数库文件扩展名是 ".a",文件通常命令为 libxxx.a(xxx 为文件名);动态函数库扩展名为 ".so",文件通常命令为 libxxx.so.major.minor(xxx 为文件名,major 为主版本号,minor 为副版本号)。
目前,Linux 系统中大多数都是动态函数库(主要考虑到软件的升级方便),其中被系统程序调用的函数库主要存放在 “/usr/lib” 和 “/lib” 中;Linux 内核所调用的函数库主要存放在 “/lib/modules” 中。
注意,函数库(尤其是动态函数库)的存放位置非常重要,轻易不要做更改。
如果需要在自己的代码中使用这类静态库,则只要在自己的源代码中include进这些静态库所对应的.h文件(头文件)即可
,然后在链接的时候(编译的时候有.h文件就够了,还用不到静态库文件)指定好所用到的静态库文件,就会将这些静态库一起链接进来,生成最终的可执行文件.
三、什么是configure与make
源码的安装一般由3个步骤组成:配置(configure)、编译(make)、安装(make install)。
Configure是一个可执行脚本,它有很多选项,在待安装的源码路径下使用命令./configure –help输出详细的选项列表。其中–prefix选项是配置安装的路径,如果不配置该选项,安装后可执行文件默认放在/usr /local/bin,库文件默认放在/usr/local/lib,配置文件默认放在/usr/local/etc,其它的资源文件放在/usr /local/share,比较凌乱。如果配置–prefix,如:./configure --prefix=/usr/local/test可以把所有资源文件放在/usr/local/test的路径中,不会杂乱。用了—prefix选项的另一个好处是卸载软件或移植软件。当某个安装的软件不再需要时,只须简单的删除该安装目录,就可以把软件卸载得干干净净;移植软件只需拷贝整个目录到另外一个机器即可(相同的操作系统)。当然要卸载程序,也可以在原来的make目录下用一次make uninstall,但前提是make文件指定过uninstall。
make
当执行make时,make会在当前目录下搜索Makefile这个文本文件,而makefile里面则记录了源码如何编译的详细信息。make会自动判别源码是否经过变动了而自动更新执行文件。
make是一个程序,会去找makefile文件。那makefile怎么写呢?这里就涉及到configure了
configure
configure是检测用户的操作环境的程序。为什么要检测操作环境呢?需要检测该操作系统平台有没有提供合适的编译程序才行。
一般来说,检测程序会检测的数据大约有下面这些:
- 是否有适合的编译程序可以编译本软件的程序代码;
- 是否已经存在本软件所需要的函数库或者其他需要的相关软件;
- 操作系统平台是否适合本软件,包括linux的内核版本;
- 内核的头定义文件(header include)是否存在(驱动程序必须要的检测)
这一步一般用来生成 Makefile,为下一步的编译做准备,你可以通过在 configure 后加上参数来对安装进行控制,比如代码:./configure –prefix=/usr 意思是将该软件安装在 /usr 下面,执行文件就会安装在 /usr/bin (而不是默认的 /usr/local/bin),资源文件就会安装在 /usr/share(而不是默认的/usr/local/share)。同时一些软件的配置文件你可以通过指定 –sys-config= 参数进行设定。有一些软件还可以加上 –with、–enable、–without、–disable 等等参数对编译加以控制,你可以通过允许 ./configure –help 察看详细的说明帮助。