前言:要学习linux底下的库,那么我们肯定是先要了解到底什么是库?
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行,就是将源代码转变成二进制格式的源代码,这就是相当于是对这部分的代码进行了加密,别人可以使用这个库,但是看不见库里面的内容。
库也叫程序函数库,那么使用库的好处是什么呢,其实跟上一节的分文件编程的思想是几乎是一样的。
程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级。
一、库的分类
静态函数库(static libraries),共享函数库(shared libraries),
动态加载函数库(dynamically loaded libraries)
由于共享函数库也叫动态加载函数库,所以在本文只介绍静态函数库和动态加载函数库
二、库存在的意义
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
现在少用静态库,多用动态库,但有些场景也会用到静态库。
三、库的详解
a. 静态库
静态函数库:是在目标程序执行前(编译的时候)就加入到目标程序中去了。
优点:
1)静态库在编译的时候就被打包到应用程序中,所以其加载的速度快
2)发布程序的时候无需提供静态库,因为已经在app中,移植方便
缺点:
1)链接时完整的拷贝到可执行文件中,被多次使用就会有多份冗余拷贝
2) 更新,部署,发布麻烦
b. 动态库
动态加载函数库:是在目标程序执行时动态(临时)由目标程序去调用
优点:
1)链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存
2)程序升级简单,因为app中没有库的源代码,升级之后只要库的名字不变,函数名与及参数不变,只是做了优化,就能加载成功
缺点:
1)加载速度比静态库慢
2)发布程序时需要提供依赖的动态库
四、库的制作与使用
a. 静态库的制作和使用
(1)命名的规则
静态库文件名的命名方式是“libxxxxx.a”
,库名前加“lib”
,后缀用“.a”
,“xxxxx”
为静态库的真实名字
(2)制作的步骤
原材料:.c
或.cpp
文件
a. 首先将.c
文件生成.o
文件,通过 gcc xxxx.c -c
生成
b. 将.o
文件进行打包成后缀为.a
的静态库文件
通过 ar rcs libxxx.a xxx.o
的方式进行打包
(3)静态库的使用
gcc calculator.c -lmystatic -L ./ -o mainSatic
-l
(小写的L
):指定要用的静态库,库名要看头去尾(即要去掉lib
和后缀.a
),(-lmystatic)
-L
(大写的L
):告诉gcc
编译器从-L
指定的路径去找静态库,如果没有指定,则默认从/usr/lib
或/usr/local/lib
去找 ,则这里有指定./
,-L ./
的意思就是从当前路径去找
-o
(小写的O
):指定生成的可执行文件
运行:直接像我们平时运行一样./mainStatic
b. 动态库的制作和使用
(1)命名规则
动态库的命名方式静态库的命名方式相似,前缀一样,都为“lib”
,静态库的后缀是.a
,而动态库的后缀变成.so
(2)制作步骤
原材料:.c
或.cpp
文件
a.首先将.c
文件生成.o
文件(需要加一个参数-fpic
),通过gcc xxx.c -c -fpic
来生成
b.将.o
文件打包成后缀为.so
动态库文件,通过 gcc -shared xxx.o -o libxxx.so
进行打包
c.其实是可以将上述两个步骤合成一个步骤来完成的,通过gcc -shared -fpic xxx.c -o libxxx.so
来跳过第一个步骤直接生成.so
文件
-fpic
:使用 -fPIC
选项,会生成 PIC
代码。.so
要求为 PIC
,以达到动态链接的目的,否则,无法实现动态链接
在这里解释一下在linux
中什么是PIC
代码
答案:“在linux中,pic的中文意思为“位置无关代码”,是指代码无论被加载到哪个地址上都可以正常执行。
PIC用于生成位置无关的共享库,所谓位置无关,指的是共享库的代码断是只读的,存放在代码段,多个进程可同时公用这份代码段而不需要拷贝副本。
-shared:
指定生成动态库
(3)动态库的使用
gcc calculator.c -lmyDy -L ./ -o mianDy
-l
(小写的L
),-L
(大写的L
),-o
(小写的O
),这几个参数在静态库的使用那里已经有,动态库跟静态库是一模一样的
动态库的运行:
这里要注意了,动态库跟静态库的运行不一样,如果还是像静态库一样用./mainDy
的方式来进行运行的话是会报错的, No such file or directory
这里要回到静态库跟动态库的区别,静态库是在程序编译的时候就加到目标程序中去,而动态库是在目标程序在执行的时候由目标程序临时的去调用
(4)动态库的指定位置的搜索
在这里主要介绍两个方法,其实方法有很多
方法一:通过环境变量LD_LIBRARY_PATH
指定动态库搜索路径
方法二:在编