静态库和动态库(Linux版)
1静态库和动态库概述
库是一种软件组件技术,库里面封装了数据和函数。库的使用可以使程序模块化。库有两种:静态库和动态库。Windows系统包括静态链接库(.lib文件)和动态链接库(.dll文件)。Linux通常把库文件存放在/usr/lib或/lib目录下。Linux库文件名由:前缀lib、库名和后缀3部分组成,其中动态链接库以.so作为后缀,静态链接库通常以.a作为后缀。
何为静态库和动态库?
静态库(Static library, Statically-linked library, LIB)或称静态链接库,是一个外部函数与变量的集合体。静态库的文件内容,通常包含一堆程序员自定的变量与函数,在编译期间由编译器与连接器将它集成至应用程序内,并制作成目标文件以及可以独立运作的可执行文件。而这个可执行文件与编译可执行文件的程序,都是一种程序的静态创建(static build)。其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。即静态库中的指令全部被直接包含在最终生成的可执行文件中。
动态库(Dynamic library, Dynamic-link library, DLL)或称动态链接库,是微软公司在微软视窗操作系统中实现共享函数库概念的一种实现方式。动态链接库可被多个程序同时使用。所谓动态链接,就是把一些经常会共用的代码(静态链接的OBJ程序库)制作成DLL档,当程序有需求时函数才进行链接。透过动态链接方式,存储器浪费的情形将可大幅降低。静态链接库则是直接链接到可执行文件。
一个程序编译成可执行的步骤:
静态库和动态库的区别在链接阶段如何处理库,如果将库链接到目标代码中则是静态库,而将库链接载入推迟到程序运行的时期则是动态库,可以实现进程之间的资源共享。2 Linux创建和使用静态库
前面已经介绍了静态库的概念,下面我们通过一个实例来看静态库的使用。2.1生成静态库
1)这里准备了两个库的源码st1 、st2用它们来制作库libmytest.a,如下
$ ls -l
$ cat st1.c #include void print1() { printf("Hello!I am st1! "); }
$ cat st2.c #include void print2() { printf("Hello!I am st2! "); }
$ cat main.c #include int main(int argc, const char *argv[]) { print1(); print2(); return 0; }
2) 生成libmytest.a文件
创建静态库用ar命令,它将很多.o转换成.a
$ gcc -c st1.c st2.c
$ ar crs libmytest.a st1.o st2.o
$ ls -l
$ file libmytest.a
静态库文件libmytest.a已经生成,用file命令查看其属性,发现它确实是归档压缩文件。用ar -t libmytest.a可以查看一个静态库包含了那些obj文件:
$ ar -t libmytest.a
2.2使用静态库
直接使用
$gcc -o test main.c libmytest.a
双L链接法
$gcc -o test main.c -lmytest -L.(库所在目录,.表示当前目录)
单L链接法(需要配置环境变量LIBRARY_PATH,把库放在所在目录配置)
$gcc -o test main.c -lmytest
前面我们已经写好了main.c,现在测试一下
$ gcc -o test main.c -L. -lmytest
$ ls -l
$ ./test
这里gcc的参数-L是告诉编译器库文件的路径是当前目录,-l是告诉编译器要使用的库的名字叫mytest。2.3静态库总结
在一个头文件中声明静态库所导出的函数。
在一个源文件中实现静态库所导出的函数。
编译源文件,生成可执行代码。
将可执行代码所在的目标文件加入到某个静态库中,并将静态库拷贝到系统默认的存放库文件的目录下。
下面通过一个例子来说明:
源文件:mylib.c#include void welcome(void) { printf("welcome to libmylib "); }
1>编译mylib.c生成目标文件:
$gcc -o mylib.o -c mylib.c
2>将目标文件加入到静态库中:
$ar -rcs libmylib.a mylib.o
【注】库文件名以lib开头,以.a结尾。
3>将静态库copy到Linux的库目录(/usr/lib或者/lib)下:(也可以不拷贝,注意配置环境变量)
$sudo cp libmylib.a /usr/lib/libmylib.a //管理员身份
编写调用库函数的测试程序test.c:#include int main(void) { printf("create and use library: "); welcome(); return 0; }
4>使用静态库编译:
$gcc -o test test.c -lmylib
这里注意,编译时无需带上前缀和后缀。
5>运行可执行程序test:
$./test
在Linux下,可以使用ar命令来创建和修改静态库。
这些在linux下man ar一下就可以得到参数,这里说明几个常用的
d:从库中删除成员文件。
r:在库中加入成员文件,若存在,则替换。
c:创建一个库。
s:无论ar命令是否修改了库内容,都强制重新生成库符号表。
其他的命令用时再man。
【注】gcc -static 文件.c [-o 文件]//全部使用静态库的方法3 Linux创建和使用动态库
动态库的基本概念
1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序。动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的。库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时形成。
2.动态链接库的名称有别名(soname), 真名(realname)和链接名(linker name)。别名由一个前缀lib,然后是库的名字,再加上一个后缀".so"构成("libxxx.so")。真名是动态链接库真实名称,一般总是在别名的基础加上一个小版本号,发布版本等构成。除此之外,还有一个链接名,即程序链接时使用的库的名字。
3.在动态链接库安装的时候,总是复制文件到某个目录下,然后用一个软连接生成别名,在库文件进行更新的时候,仅仅更新软链接即可。
下面我们通过一个实例来学习如何生成动态库和使用动态库。3.1生成动态库
1)当前文件夹下有下面四个文件
$ ls -l
文件内容分别为:
$ cat mylib.h #ifndef _MYLIB_H_ #define _MYLIB_H_ #include void print1(); void print2(); #endif
$ cat dy1.c #include "mylib.h" void print1() { printf("My first shared lib! "); }
$ cat dy2.c #include "mylib.h" void print2() { printf("My second shared lib! "); }
$ cat main.c #include "mylib.h" int main(int argc, char *argv[]) { print1(); print2(); return 0; }
2)这里我们将dy1.c与dy2.c用来创建动态库
$ gcc -fPIC -Wall -c dy1.c dy2.c
$ gcc -shared -o libtest.so dy1.o dy2.o
这里 -fPIC 创建与地址无关的编译程序,-shared指定生成动态链接库。
我们也可以一步到位
$ gcc -o libtest.so -fPIC -shared dy1.c dy2.c
我们可以看到下面已经生成了一个libtest.so
$ ls -l
3.2使用动态链接库
在编译程序时,使用动态链接库和静态库是一致的,使用"-l库名"的方式,在生成可执行文件的时候会链接库文件。使用如下命令:
$ gcc -o test main.c -L. -ltest
$ ls -l
这里 -L 指定动态链接库的路劲,-ldtest链接库函数test 。-ltest是动态库的调用规则。Linux系统下的动态库命名方式是lib*.so,而在链接时表示位-l*,*是自己命名的库名。
我们可以看到这里已经生成了test可执行文件,我们可以执行一下:
$ ./test
可以发现发生了错误,这是因为程序运行时没有找到动态链接库造成的。程序编译时链接动态库和运行时使用动态链接库的概念是不同的,在运行时,程序链接的动态链接库需要在系统目录下才行。
这就到了动态库的路径问题,有三种方法:
1)把库拷贝到/usr/lib和/lib目录下:
$ sudo cp libtest.so /lib
【注】这里要超级用户权限sudo
我们看一下执行结果:
$ ./test
这里执行结果正确。
2)在 LD_LIBRARY_PATH 环境变量中加上库所在路径
$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
我们可以看到:libtest.so 的路径已经存在
$ ldd test
我们可以看一下结果:
$ ./test
也能得到正确结果。
3)添加/etc/ld.so.conf.d/*.conf文件。把库所在的路径加到文件末尾,并执行ldconfig刷新。
$ cd /etc/ld.so.conf.d/
$ ls
$ sudo vi my.conf
$ cat my.conf /home/bruceou/demo/libtest.so
在/etc/ld.so.conf.d/下建立my.conf 里面只有一句/home/bruceou/demo/libtest.so即libtest.so的路径,然后执行ldconfig刷新即可。3.3动态库总结
1.编译动态库
方法一:
命令:gcc -fPIC -Wall -c .c
命令:gcc -shared -o lib.so .o
方法二:
命令:gcc .c .c .c -fPIC -shared -o lib.so
2.安装路径
命令:cp lib.so /usr/lib/lib.so//管理员身份
3.动态库的链接
命令:gcc -o .c -L. -l
或者:命令:gcc .c -L. -l -o
4.运行可执行程序
wxPython自定义控件实战wxPython系列051前面系列文章中,我们介绍了wxPython提供各种的各种控件,在一般情况下可以满足我们开发应用的各种需求。但是在一些情况下,比如对按钮的美化,一个可以
光刻机三年之约已过去三分之二,能否如期而至被推上风口浪尖在华为芯片被断供后,世界首富比尔盖茨曾预言对中企的打压会起反作用,激发中企的斗志,断了美企的独家赚钱之路。而华为老大任正非则表示未来美企会求着我们购买芯片,而我们却不需要了。他们都
2022年,7款中成药销售额超10亿元!制药网行业动态近年来,随着人口老龄化加剧,高血压糖尿病高血脂等慢病患者数量增加,以及消费不断升级,居民健康保健意识的增强,中成药需求持续扩张。据数据统计显示,2022E中国城市实体
碧桂园变相展期疑云,这笔信用债很招风来源地产密探(IDrealestatespy)编辑密探财经很多人都说,大象跳舞,难转身。纵览宇宙房企碧桂园,2022年预告业绩已创下史上最差,楼市低谷又遇上高负债,3月初创始人杨国
2023年退休,工龄36年,个人账户余额16万,能领多少养老金?2023年退休,工龄36年,个人账户余额16万,能领多少养老金?首先来看一位朋友发来的社保信息坐标山东,2023年1月份满60岁退休,工龄36年,个人养老保险平均缴费指数为1。5,
股票怎么才能盈利?别人恐惧我贪婪别人恐惧我贪婪,2023开年至今,一直满仓,从未撤退。始终相信价值投资,没有退路可言,看好大消费,看好通信,看好央企改革,看好核心资产。白酒没有泡沫,有泡沫的那是啤酒。1白酒不用说
金属软磁粉行业研究报告应用边界不断拓展,行业空间广阔(报告出品方作者国泰君安证券,李鹏飞,魏雨迪,王宏玉)1。金属软磁粉高速发展的新型软磁材料1。1。金属软磁粉新兴软磁材料磁性材料分为硬磁和软磁材料。通常能对磁场作出某种反应的材料称
3家公司申报创新层!新三板又现挂牌热点蓝字关注,不迷路来源北证资讯新三板再度迎来挂牌热潮,3月份还没过半,已经有21家公司挂牌新三板,日均挂牌企业超2家。创下最快过审纪录的朗诺股份,从挂牌申请获受理到正式挂牌,历时仅
美食推荐姜汁热碗鸡金汤龙虾球小炒南美参制作方法姜汁热碗鸡食材仔鸡1只,盐6克,料酒10毫升,胡椒粉0。5克,味精0。5克,红油15克,醋5毫升,酱油7毫升,淀粉4克,姜米2毫升,汤100克。制作1将仔鸡老加工后入汤锅煮到断生后
中外人士认为亚吉铁路极大促进非洲之角地区繁荣新华社亚的斯亚贝巴3月9日电(记者汪平)由中国企业承建的亚吉铁路运营5周年庆典活动日前在埃塞俄比亚首都亚的斯亚贝巴举行。出席活动的中国埃塞俄比亚和吉布提人士认为,亚吉铁路服务和盈利
青岛梅花节踏春赏梅李沧交警发布出行提示农视网三农头条山东讯春意萌动,梅花竞放。3月13日,青岛李沧区将迎来第二十三届中国青岛梅花节,持续至4月15日历时32天。伴随着游客前来踏春赏梅,届时十梅庵风景区周边将迎来交通高峰