为什么需要学习静态库和动态库:
当我们工作是,要把自己写的代码给别人用,但是又不能给源代码,这是就需要生成库
静态链接是在形成可执行程序前进行文件链接,而动态链接的进行则是在程序执行时进行文件链接,下面来详细介绍这两种链接方式。
一、静态链接
1.为什么要进行静态链接
在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个*.c文件会形成一个*.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。(独立编译,相互链接)这个链接的过程就是静态链接
静态链接缺点:
一是浪费空间,因为每个可执行程序中对所有需要的目标文件都要有一份副本,
二是更新比较困难,因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。
优点:快
在可执行程序中已经具备了所有执行程序所需要的任何东西
2.动态链接
动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。
我们平时编译程序的链接默认都是动态链接
静态链接和动态链接的区别
1,链接阶段:静态链接是链接阶段就把静态库中需要的函数链接到可执行程序中了;动态库是运行阶段才进行链接,但是并不是将需要的文件和函数加载到可执行程序-----从这可以知道:静态库的缺点是如果静态库改变了,就需要程序生成可执行文件,而动态库和其他目标文件是独立的,即使动态库被修改,不一定要重新生成可执行文件;静态库如果被删除不会影响可执行程序的运行,但是动态库删除会影响可执行程序的运行。
2,链接的原理:静态链接是在链接阶段把需要的静态库中的头文件和函数链接到可执行程序中了,那么静态库中的相同文件和函数如果使用到多次,那就会有多份,在链接阶段进行重定位分配虚拟内存的时候,同一条指令因为使用多次,就会有多个虚拟内存,同样加载程序到物理内存的时候同一条指令也会各自占用一个物理内存。而动态库是在运行阶段把需要的动态库加载到物理内存,那么这个动态库就只有一份,然后利用可执行程序的虚拟内存中的文件映射区映射动态库的物理地址,这样即使动态库中的指令即使使用多次也只一个虚拟内存和物理内存------从这个过程可以知道静态链接需要耗费更多的虚拟内存和物理内存,而且动态库加载到物理内存可以实现多个程序对这个动态库的共享。
静态库:
命名规则:
前缀:lib
库名;xx
后缀:.a
eg: libtest.a
静态库生成:
1,使用gcc -c命令将所有原文件生成.o文件;(gcc -c是汇编阶段生成目标文件)
eg:gcc -c add.c -o add.o
2,用打包工具ar将所有.o文件打包生成libxx.a的静态库
ar需加上参数:rcs
r:更新
c:创建
s:建立引索
eg: ar -rcs libtest.a add.o mul.o div.o sub.o
静态库的使用:
工作中我们需要将.a文件和头文件一起发给用户
使用:
程序主文件:test.c
eg: gcc test.c -L./ -l test -o test.out
-L:指定静态库的目录
-l: 链接
注意:链接静态库时,前缀lib和后缀.a都不要
动态库(共享库):
命名规则:
前缀:lib
库名;xx
后缀:.so
eg: libtest.so
动态库生成:
1,用gcc -fpic -c add.c将所有原文件自动生成.o
-fpic或者-fPIC:创建与地址无关的编译程序
2,使用gcc -share来将所有.o文件生成共享库
eg: gcc -share add.o sub.o mul.o div.o -o libtest.so
生成之后可以通过nm命令来查看生成的库:
eg: nm libtest.so
eg:nm libtest.so | grep add
动态库的测试:
在测试库之前需要对库的存在做一些配置,才可以测试:
1,打开文件:~/.bashrc,在文件最后添加:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库的绝对路径
保存退出
2,运行:source ~/.bashrc
使环境变量生效
3,编译:gcc test.c -L./ -l test -o test.out
或者:gcc test.c -L. -I. -l test -o test.out
第一个I是大i,指定头文件路径
4,运行:./test.out