Linux下链接动态库静态库的理解

来源:互联网 发布:中文域名骗局 编辑:程序博客网 时间:2024/04/28 20:59

Linux程序GCC编译基本过程

一个程式从原始码到可执行文件(或共享库文件),一般都要经过预处理、编译、汇编和链接这四个步骤。

编译过程扫描头文件的搜索路径顺序

gcc 在编译时如何去寻找所需要的头文件 :

※所以header file的搜寻会从-I开始

※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH

※再找内定目录

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

库文件但是如果装gcc的时候,是有给定的prefix的话,那么就是

/usr/include

prefix/include

prefix/xxx-xxx-xxx-gnulibc/include

prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include

尤其注意链接过程是本文要重点讨论的:

链接步骤要经历链接内部库(即当前程序源码编译而成的.a,.o,.so)和外部库(依赖的外部静态lib.a、动态库lib.so)

外部库

外部库有两种: (1)静态连接库lib.a

       (2)共享连接库lib.so

共同点:

.a, .so都是.o目标文件的集合,这些目标文件中含有一些函数的定义(机器码),而这些函数将在连接时会被最终的可执行文件用到。

区别:

静态库.a  : 当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中。

共享库.so : 与共享库连接的可执行文件只包含它需要的函数的表,而不是所有的函数代码,在程序执行之前,那些需要的函数代码被拷贝到内存中,这样就使可执行文件比较 小,节省磁盘空间(更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用)。共享库还有个优点:若库本身被更新,不需要重新编译与 它连接的源程序。

Linux下库是如何产生的

静态库的后缀是.a,它的产生分两步

Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表

Step 2.ar命令将很多.o转换成.a,成文静态库

动态库的后缀是.so,它由gcc加特定参数编译产生。

例如:

$ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.

Linux下库文件是如何命名的,如何存放

静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称

动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号

Linux下,库文件一般放在/usr/lib /lib下,

如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下

1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

2.运行ldconfig,该命令会重建/etc/ld.so.cache文件

Linux中有关编译链接要是用的库扫描路径,与有关环境变量

静态库链接时搜索路径顺序:

1.ld会去找GCC命令中的参数-L

2.再找gcc的环境变量LIBRARY_PATH

3.再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

1.编译目标代码时指定的动态库搜索路径;

2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;

4.默认的动态库搜索路径/lib;

5.默认的动态库搜索路径/usr/lib。

有关环境变量:

LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径

LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

链接过程

 建立静态库方法(包括静态内部库和动态外部库)

gcc -c fun.c

ar cqs libfun.a fun.o

 编译中使用静态库方法

gcc call.c -static -L. -lfun -o fun_static_call

 建立动态库(包括动态内部库和动态外部库)

gcc fun.c -fPIC -shared -o libfun.so

 编译中使用动态库方法

gcc call.c -L. -lfun -o fun_dyn_call

编译器会先在path文件夹下搜索libxxx.so文件,如果没有找到,继续搜索libxxx.a(静态库)。

执行过程

 无论是使用动态库还是外部库链接时都是使用的ld连接器;

 使用动态库的程序执行时使用动态加载器。在Linux 下,加载器是/lib/ld-Linux.so.X(X是版本号)。然后加载器搜索、加载程序所要使用的动态链接库。搜索顺序见上。

原创粉丝点击