苏州定制网站建设/seo建站优化推广
目录
怎么做静态库?
怎么做动态库?
知识补充
动态库 VS 静态库
ldd 命令:用于查看一个可执行程序所依赖的动态库。还可以用来识别一个可执行程序到底是进行的动态链接还是静态链接。
在 Linux 中,动态库文件的后缀一般是 .so ,静态库文件的后缀一般是 .a 。
在 Windows 中,动态库文件的后缀一般是 .dll ,静态库文件的后缀一般是 .lib 。
怎么做静态库?
第一步,先把你要包含的所有的 .c 文件全都编译成 .o 文件。
第二步,再用 ar -rc 命令进行打包。
补充:ar -rc libmyc.a *.o 这一句命令的作用是:把该目录下的所有 .o 文件打一个包,建立静态库。-- 注:ar是gnu归档工具(打包工具),rc表示(replace(如果这个 .o 存在了,就 replace) and create(如果这个 .o 不存在就 create))。
怎么做动态库?
第一步,也是要先把要包含的所有的 .c 文件全都编译成 .o 文件。
注:该过程命令中要多加一个 -fPIC 选项。
补充:fPIC:产生位置无关码(position independent code)。-- 这也是动态库可以被映射到虚拟地址空间的什么位置的原因。(只要知道起始地址和偏移量就够了)
第二步,直接用 gcc 命令将这些 .o 文件全部打包,形成库。-- ex:gcc -shared *.o -o libmyc.so
补充:shared: 表示生成共享库格式
补充:采用动态链接时,程序运行的时候还需要去找动态库,加载动态库并运行!(编译时,你只是把动态库的位置告诉了编译器,跟可执行程序有什么关系?)
补充:采用静态链接时,在编译期间,就已经将静态库中的代码拷贝到可执行程序内部了,加载就和库没关系了(不需要再去找了)!-- 注:这也导致静态链接形成的可执行程序占用的内存大。
问题:那么要怎么让可执行程序找到我们自己的动态库(第三方库)呢?
答:
- 第一种办法,就是直接强行将我们自己的动态库(第三方库)安装到系统用来存放库的路径下。-- 注:但这种方法很龊
- 第二种方法,给我们自己的动态库(第三方库)建立一个软链接,将这个软链接放到系统用来存放库的路径下。
- 第三种方法,往 LA_LABRARY_PATH 环境变量中添加自己的动态库(第三方库)的路径。ex:LA_LABRARY_PATH=$LA_LABRARY_PATH:动态库的绝对路径(这是临时的,要想变成永久的,需要去修改配置文件.bashrc)。
- 第四种方法,把你当前要用的动态库所处的路径添加到 /etc/ld.so.conf.d 这个配置文件里。-- 注:在这个配置文件里添加的文件都必须以 .conf 为后缀。然后在 root 权限下,将这个配置文件加载到系统里即可。命令:ldconfig(后面无需再加任何东西了)
知识补充
补充:头文件就像一个手册,提供函数的声明,告诉用户我们要怎么用。
问题:什么是库文件?
答:所谓的库文件就是把 .o 文件打包。
补充:一个库的真正的名字:ex:libmyc.a ,去掉前缀lib,去掉后缀.a,剩下的 myc 才是这个库的真正的名字。(动态库也一样,前缀lib,后缀.so)
补充:安装/卸载库 就是把对应的库文件 放到系统指定的路径下/从系统指定路径下移除。
注:非常不建议把自己或者他人(非高手)写的第三方库安装到系统指定存放库的路径下,因为太垃圾了(很龊)。
补充:gcc/g++ 默认是认识 C/C++ 的库的,但是别人写的(第三方提供)的库,gcc/g++ 默认是不认识的,要想使用这些第三方提供的库,就要在后面加个 -l 选项,然后在 -l 选项后面加上(有无空格都行)库的真正的名字。
问题:为什么要有库呢?
答:提高开发效率。
问题:那么我们该如何方便的直接使用这些第三方库呢?
答:gcc 有个 -I 选项(后面跟一个路径),该选项的作用就是:给编译器动态的指定一个头文件的搜索路径。有个 -L 选项(后面跟一个路径),该选项的作用就是:给编译器动态的指定一个库文件的搜索路径。有个 -l 选项(后面跟一个库的真正的名字),该选项的作用就是:告诉编译器到底要链接哪个库。
补充一个问题:为什么头文件不需要指定是哪个头文件呢?
答:.c 文件里最上面的 #include 就已经说明了需要哪些头文件了。
补充:用 <> 包含起来的头文件,编译器编译时只会去系统指定的路径下找,而用 "" 包含起来的头文件,编译器编译时会优先去系统指定的路径下找,找不到就还会在当前路径下找。
补充:80%以上的可执行程序采用的都是动态链接(因为静态链接形成的可执行程序内存大),所以动态库非常重要,一旦被误删了,很多程序就直接跑不了了(因为程序在运行时,需要加载动态库,而静态库则不需要加载(因为静态库的内容已经拷贝到了程序中了))。
补充:安装C和C++静态库的指令:sudo yum install -y glibc-static libstdc++-static
问题:为什么要有(动态/静态)库文件(打包)?
答:提高开发效率。
动态库 VS 静态库
编译器在链接时,优先进行动态链接,除非指明了要强制静态链接(就是在命令后面加上 -static)。
补充:
如果在链接时,没有加 -static 选项,并且你没有提供动态库,那么此时就进行静态链接。如果在链接时,加了 -static 选项,但是你没有提供静态库,那么就会报错。
补充:-static 选项的意义:必须强制的将我们的程序进行静态链接。这就要求我们所需链接的任何库都必须提供对应的静态库版本。
默认情况下,Linux上,一般静态库都是默认没有安装的。-- 从这里就能看出系统对于动态库和静态库的态度,建议使用动态库。
补充:
- 动态链接动态库加载及运行速度相较静态链接是较为不如的,因为动态库运行时加载,映射到虚拟地址空间后需要重新根据映射起始地址计算函数/变量地址。
- 静态链接,链接静态库,每个程序将自己在库中用到的指令代码单独写入自己可执行程序中,程序运行时无依赖,加载运行速度快,但是程序运行后有可能会有冗余代码在内存中。
- 动态链接的程序一旦库中代码发生改变,重新加载一次动态库即可,但是静态链接代码是写入程序中的,因此库中代码发生改变,必须重新链接生成程序才可以。
动态链接具有以下优缺点:
优点:
- 更加节省内存并减少页面交换;
- 库文件与程序文件独立,只要输出接口不变,更换库文件不会对程序文件造成任何影响,因而极大地提高了可维护性和可扩展性;
- 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个库函数;
- 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
缺点:
- 运行时依赖,否则找不到库文件就会运行失败。
- 运行加载速度相较静态库慢一些。
- 需要对库版本之间的兼容性做出更多处理。