经过长时间学习linux库文件的概念,今天小编也给大家搜集了关于库的概念以及作用,希望大家看后会有很多收获。
1.什么是linux库
在windows平台和linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于windows和linux的本质不同,因此二者库的二进制是不兼容的。本文仅限于介绍linux下的库。
2.linux库的种类
linux库有两种:静态库和共享库。二者的不同点在于代码被载入的时刻不同。静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
3.库存在的意义
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
4.库文件是如何产生的在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 *.
5.linux库文件是如何命名的,有没有什么规范
在linux下,库文件一般放在/usr/lib /lib下,静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号
6.如何知道一个可执行程序依赖哪些库
ldd命令可以查看一个可执行程序依赖的共享库,例如# ldd /bin/lnlibc.so.6
=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
=> /lib/ld- linux.so.2 (0×40000000)
可以看到ln命令依赖于libc库和ld-linux库
7.可执行程序在执行的时候如何定位共享库文件
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径此时就需要系统动态载入器(dynamic linker/loader)对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录找到库文件后将其载入内存
8.在新安装一个库之后如何让系统能够找到他
如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
2.运行ldconfig,该命令会重建/etc/ld.so.cache文件
以上给大家讲解的是linux库文件的概念。
静态库:
对于Linux系统你了解么?目前,Linux系统越来越受到电脑用户的欢迎,于是很多人开始学习Linux时,在这期间,你可能会遇到Linux静态库的编写和使用问题,这里将介绍Linux静态库的编写和使用问题的解决方法,在这里拿出来和大家分享一下。
1、概述
静态库文件的扩展名一般为.a,其编写步骤很简单。
⑴编写函数代码
⑵编译生成各目标文件
⑶用ar文件对目标文件归档,生成静态库文件。
注意归档文件名必须以lib打头。
使用要点:
⑴在gcc 的-I参数后加上静态库头文件的路径。
⑵在gcc 的-L参数后加上库文件所在目录
⑶在gcc 的-l参数后加上库文件名,但是要去掉lib和.a扩展名。
比如库文件名是libtest.a 那么参数就是 -l test
2、编写最简单的静态库文件
编写如下两个文件,注意放在同一目录中
myalib.h//静态库头文件
myalib.c//静态库实现文件
//myalib.h 文件的内容
void test();
//myalib.c 文件的内容
- #inlcude <stdio.h>
- void test()
- {
- printf("test/n");
- }
3、制作库文件
⑴生成目标文件
gcc -c myalib.c
执行完后会生成一个myalib.o文件
⑵用ar命令归档,格式为ar -rc <生成的档案文件名> <.o文件名列表>
再次提醒,归档文件名一定要以lib打头, .a结尾。
ar -rc libtest.a myalib.o
执行完后会生成一个libtest.a文件
4、使用库文件
⑴编写一个测试程序main.c,内容为
//main.c 测试静态库调用的程序
#include "myalib.h"//要把函数的头文件包含进来,否则编译时会报错
- int main(int argc,char* argv[])
- {
- test();
- return 0;
- }
⑵编译目标文件,注意要把静态库头文件的路径加到-I参数里面
gcc -I /root/exercise -o main.o -c main.c
现在生成了一个main.o文件
⑶生成可执行文件,注意要把静态库文件的路径加到-L参数里面,
把库文件名(去掉打头的lib和结尾的.a)加到-l参数后面。如下面所示
gcc -o main -L/root/exercisemain.o -ltest
此时就会生成一个名为main的可执行文件
另外,注意- l参数好象应该加到输入文件名的后面,否则会报错。
比如gcc -o main -L/root/exercise-ltest main.o就会提示
- main.o(.text+0x11): In function `main':
- : undefined reference to `test'
- collect2: ld returned 1 exit status
原因我还不清楚:-)
⑷执行可执行文件查看效果
执行./main, 输出
test
说明执行成功。以上就是Linux静态库的编写和使用的简介。
动态库:
目前,Linux系统越来越受到电脑用户的欢迎,于是很多人开始学习Linux时,在这期间,你可能会遇到Linux动态库的编写的知识,这里将介绍Linux动态库的编写知识,希望能学会。
四、动态库的编写
1、概述
动态库一般以.so结尾,就是shared object的意思.
其基本生成步骤为
⑴编写函数代码
⑵编译生成动态库文件,要加上 -shared 和 -fpic 选项 , 库文件名以lib开头, 以.so 结尾。
使用方式分为两种: 隐式调用和显示调用
隐式调用类似于静态库的使用,但需修改动态链接库的配置文件/etc/ld.so.conf;显示调用则是在主程序里使用dlopen、dlsym、dlerror、dlclose等系统函数。具体的调用方式会在 "五、动态库的调用" 中详细说明.
2、编写最简单的动态库文件
为了便于对照, 我们仍然采用静态库中的文件做例子.
编写如下两个文件,注意放在同一目录中
- myalib.h//静态库头文件
- myalib.c//静态库实现文件
- //myalib.h 文件的内容
- void test();
- //myalib.c 文件的内容
- #inlcude <stdio.h>
- void test()
- {
- printf("test/n");
- }
3、编译生成动态库 ,库文件名以lib开头, 以.so 结尾。
gcc -fpic -shared -o libtest.so myalib.c
此时就生成一个libtest.so文件,以上就是Linux动态库的编写的知识。
动态库的隐式调用:
十多年Linux的发展,Linux已经越来越接近微软,你了解Linux系统么?你是Linux系统的应用者么?这里为你讲解inux动态库的隐式调用,为你在学习Linux动态库的隐式调用时起一定的作用。
隐式调用的含义是代码里不出现库文件名,就是说这个代码和
调用静态库的代码是类似的。
1、编写测试文件
- //main.c 测试动态库隐式调用的程序
- #include "myalib.h" //要把函数的头文件包含进来,否则编译时会报错
- int main(int argc,char* argv[])
- {
- test();
- return 0;
- }
2、 编译测试程序,与静态库类似,要把头文件的路径加到-I参数里面
gcc -I /root/exercise -o main.o -c main.c
现在生成了一个main.o文件
3、连接生成测试程序
gcc -o main -L/root/exercise main.o -ltest
现在生成了一个main文件
4、执行测试程序
./main
此时出现提示
./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory。
这个原因就是程序运行时并不知道动态库所在的路径,因此自然找不到。以上就是Linux动态库的隐式调用的讲解。
动态库被系统共享的三种方法:
又过去了一年,也许有人会说Linux很多方面不如Windows,这是你不懂Linux,如果你想知道Linux态库被系统共享的三种办法,这里会将教会你Linux动态库被系统共享的三种办法。
(再次说明: 本节参考了计算机世界网雨亦奇的文章"LINUX动态链接库高级应用"
地址)
(1)拷贝动态链接库到系统共享目录下,或在系统共享目录下为该动态链接库
建立连接(硬连接或符号连接均可,常用符号连接).这里说的系统共享目录,
指的是LINUX动态链接库存放的目录,包括
/lib,/usr/lib以及/etc/ld.so.conf文件内所列的一系列目录.
实例:执行
# cp libtest.so /lib
# ldconfig
或:
# ln -s `pwd`/libtest.so /lib
# ldconfig
注意pwd前后有两个反引号`,其目的是取得pwd命令的输出,即当前目录.
此时再执行main,即可成功.
(2)将动态链接库所在目录名追加到动态链接库配置文件/etc/ld.so.conf中.
# pwd >> /etc/ld.so.conf
# ldconfig
此时再执行main,即可成功.
(3)利用动态链接库管理命令ldconfig,强制其搜索指定目录,并更新缓存文件,便于动态装入.
# ldconfig `pwd`
此时再执行main,即可成功.
要注意,第三种方法虽然有效,但效果是暂时的,供程序测试还可以,一旦再度运行ldconfig,则缓存文件内容可能改变,所需的动态链接库可能不被系统 共享了.而且无论哪种办法,其实质都是用ldconfig命令把动态库文件所在路径加入到系统库列表中,(前两种永久,第三种临时)
ldconfig是一个动态链接库管理命令
为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig
ldconfig 命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态 链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为 /etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令.
ldconfig命令行用法如下:
ldconfig [-v|--verbose] [-n] [-N] [-X] [-f CONF] [-C CACHE] [-r ROOT] [-l] [-p|--print-cache] [-c FORMAT] [--format=FORMAT] [-V] [-?|--help|--usage] path...
ldconfig可用的选项说明如下:
(1) -v或--verbose : 用此选项时,ldconfig将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字.
(2) -n : 用此选项时,ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib,/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录.
(3) -N : 此选项指示ldconfig不重建缓存文件(/etc/ld.so.cache).若未用-X选项,ldconfig照常更新文件的连接.
(4) -X : 此选项指示ldconfig不更新文件的连接.若未用-N选项,则缓存文件正常更新.
(5) -f CONF : 此选项指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf.
(6) -C CACHE : 此选项指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,此文件存放已排好序的可共享的动态链接库的列表.
(7) -r ROOT : 此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的).选择此项时,系统默认的配置文件 /etc/ld.so.conf,实际对应的为 ROOT/etc/ld.so.conf.如用-r /usr/zzz时,打开配置文件 /etc/ld.so.conf时,实际打开的是/usr/zzz/etc/ld.so.conf文件.用此选项,可以大大增加动态链接库管理的灵活性.
(8) -l : 通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接.选择此项时,将进入专家模式,需要手工设置连接.一般用户不用此项.
(9) -p或--print-cache : 此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字.
(10) -c FORMAT 或 --format=FORMAT : 此选项用于指定缓存文件所使用的格式,共有三种: ld(老格式),new(新格式)和compat(兼容格式,此为默认格式).
(11) -V : 此选项打印出ldconfig的版本信息,而后退出.
(12) -? 或 --help 或 --usage : 这三个选项作用相同,都是让ldconfig打印出其帮助信息,而后退出.
这样你就了解了Linux动态库被系统共享的三种办法。
动态库的显式调用:
显式调用的含义是代码出现库文件名,用户需要自己去打开和管理库文件。其要点为:
⑴把dlfcn.h系统头文件包含进来
⑵用dlopen函数打开库文件,并指定打开方式
dllope的的第一个参数为共享库的名称,将会在下面位置查找指定的共享库。
①环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。
②文件/etc/ld.so.cache中找到的库的列表,由ldconfig命令刷新。
③目录usr/lib。
④目录/lib。
⑤当前目录。
第二个参数为打开共享库的方式。有两个取值
①RTLD_NOW:将共享库中的所有函数加载到内存
②RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数
⑶用dlerror()函数测试是否打开成功,并进行错误处理;
⑷用dlsym获得函数地址,存放在一个函数指针中
⑸用获得的函数指针进行函数调用。
⑹程序结束时用dlclose关闭打开的动态库,防止资源泄露。
⑺用ldconfig工具把动态库的路径加到系统库列表中
1、编写测试文件
- //main.c 测试动态库显式调用的程序
- #include<dlfcn.h> //用于动态库管理的系统头文件
- #include "myalib.h"//要把函数的头文件包含进来,否则编译时会报错
- int main(int argc,char* argv[])
- {
- //声明对应的函数的函数指针
- void (*pTest)();
- //加载动态库
- void *pdlHandle = dlopen("libtest.so", RTLD_LAZY);
- //错误处理
- if(pdlHandle == NULL ){
- printf("Failed load library/n");
- return -1;
- }
- char* pszErr = dlerror();
- if(pszErr != NULL)
- {
- printf("%s/n", pszErr);
- return -1;
- }
- //获取函数的地址
- pTest = dlsym(pdlHandle, "test");
- pszErr = dlerror();
- if(pszErr != NULL)
- {
- printf("%s/n", pszErr);
- dlclose(pdlHandle);
- return -1;
- }
- //实现函数调用
- (*pTest)();
- //程序结束时关闭动态库
- dlclose(pdlHandle);
- return 0;
- }
2、编译测试文件
使用-ldl选项指明生成的对象模块需要使用共享库
gcc -o main -ldl main.c
执行完后就生成了一个main文件
3、执行测试程序
执行 ./main
输出
test
说明成功。这就是Linux动态库的显式调用的介绍。