ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:25.23KB ,
资源ID:2027564      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-2027564.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Lib库使用学习笔记.docx)为本站会员(b****1)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

Lib库使用学习笔记.docx

1、Lib库使用学习笔记Lib库使用学习笔记一、Chapter1.为什么使用库文件我们在实际编程工作中肯定会遇到这种情况:有几个项目里有一些函数模块的功能相同,实现代码也相同,也是我们所说的重复代码。比如,很多项目里都有一个用户验证的功能。代码段如下: /UserLogin.h文件,提供函数声明 int IsValidUser(char* username, int namelen); /UserLogin.c文件,实现对用户信息的验证 int IsValidUser(char* username, int namelen) int IsValid = 0; /*下面是具体的处理代码,略去*/ r

2、eturn IsValid; 如果每个项目都保存着这两个UserLogin.h和UserLogin.c文件,会有以下几个弊端:1.每个项目里都有重复的模块,造成代码重复。2.代码的重用性不好,一旦IsValidUser的代码发生了变化,为了保持设计的一致性,我们还要手工修改其他项目里的UserLogin.c文件,既费时又费力,还容易出错。 库文件就是对公共代码的一种组织形式。为了解决上面两个弊端,就提出了用库文件存放公共代码的解决方案,其要点就是把公共的(也就是可以被多次复用的)目标代码从项目中分离出来,统一存放到库文件中,项目要用到这些代码的时候,在编译或者运行的时候从库文件中取得目标代码即

3、可。库文件又分两种:静态库和动态库。二、Chapter2.静态库和动态库简单的说,如果程序是在编译时加载库文件的,就是使用了静态库,静态库的文件名格式是lib*.a。如果是在运行时加载目标代码,就成为动态库,动态库的文件名格式是lib*.so.*。换句话说,如果是使用静态库,则静态库代码在编译时就拷贝到了程序的代码段,程序的体积会膨胀。如果使用动态库,则程序中只保留库文件的名字和函数名,在运行时去查找库文件和函数体,程序的体积基本变化不大。静态库的原则是“以空间换时间”,增加程序体积,减少运行时间;动态库则是“以时间换空间”,增加了运行时间,但减少了程序本身的体积。在附录的PIC部分,也会做一

4、些说明。从文件的格式角度讲,静态库的本质是一种档案文件(.o文件的集合),其中包含了一个内容索引 (也可以不包含,但没有索引的静态库不能用来链接,在附录的ar和各个模块既.o文件;而动态库是ELF格式的文件,可以被用来加载和执行,而静态库不可以。还有一种库文件,共享库。看到网上有些资料说,动态库就是共享库的一种变种, 由于没有使用到,没有详细研究。有时候,会在目录中看到以.la或.lo结尾的文件,这些是GNU的工具libtool生成和使用的文件, 用来说明实际库文件的使用信息和以来关系,详细的内容会在以后automake autoconf and libtool的文档中介绍。三、Chapter

5、3.静态库的生成和使用3.1.制作最简单的静态库文件编写如下两个文件,放在同一目录中: mylib.h /静态库头文件 void test(); mylib.c /静态库实现文件 #include void test() printf(hello world./n); 使用下边的命令生成静态库: gcc -c mylib.c ar rc libmy.a mylib.o 这样就生成了静态库libmy.a,注意一定要以lib*.a这样的格式命名,否则链接器ld不能识别。 使用命令file libmy.a看看它的格式,是一个档案文件。我们可以使用nm查看它的内部构成: root Benson lib

6、test# nm libmy.a libmy.o: U printf 00000000 T test 这表示静态库有模块libmy.o,在使用的时候,gcc会根据需要将函数名得到模块,然后从静态库中 提取出对应的.o文件的内容,然后用来链接,就是使用单独的.o文件一样。3.2.使用库文件编写一个测试程序main.c,内容为: #include mylib.h int main(void) test(); return 0; 由于需要调用libmy.a中的test函数,所以在编译时,需通过-L -l参数指定链接这个库: gcc -I./ -o main main.c -L./ -lmy 通过-I

7、和-L参数制定了gcc的头文件和库文件搜索路径为当前目录,也可以根据需要指定为其他目录。生成执行文件main后,执行命令file main,可以看到: root Benson libtest# file main main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, staticlly linked (uses shared libs), not stripped 运行,看到结果,成功。四、Chapter4.动态库的生成和使用4.1.制作最简单的动态库文件我们同样使用上边的myl

8、ib.h和mylib.c文件,但使用不同的命令生成库文件: gcc -fpic -shared libmy.so libmy.c 这样就生成了动态库文件libmy.so,-fpic这个选项指定是否使用PIC,这个选项的使用需要系统平台的支持,一般建议添加,如果不支持,gcc会报错。生成libmy.so后,使用file libmy.so命令,可以看到是一个ELF格式的文件,这说明共享库的 使用需要通过符号解析和重定位加载入内存才能使用。4.2.动态库的隐式调用动态库有两种使用方法,隐式调用和显示调用。隐式调用的方法跟静态库的使用方法一样,都是通过 gcc的-I -L参数指定库文件的路径,如果同一

9、个库文件,在系统中同时存在静态库和动态库,默认情况下 gcc主动链接动态库。但也可以通过gcc的-static选项,强制指定使用静态库。 gcc -I./ -o main main.c -L./ -lmy # 使用动态库生成main gcc main.c ./libmy.so -o main # 使用动态库生成main,不同的地方在于指定了libmy.so 的加载路径,这种用法很少用。详细的内容附录ld.so gcc -static -I./ -o main main.c -L./ -lmy # 使用静态库生成main 输入file main命令,可以看到: root Benson libte

10、st# file main main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped 运行程序,报错: root Benson libtest# ./main ./main: error while loading shared libraries: libmy.so: cannot open shared object file: No such file or director

11、y 没有找到libmy.so这个动态库,我这个库文件就在当前目录下?4.3.使动态库被系统共享的方法前边已经说过动态库需要加载到内存中,才能使用。注意,链接和加载是两码事, 链接发生在生成可执行程序的阶段,加载发生在运行阶段。gcc的-I -L参数只是保证在链接阶段 指定文件路径,和加载无关,当然也有办法可以使链接阶段的路径信息在加载阶段起作用, 这些涉及到gcc的详细用法,和可执行文件的格式,附录中会简单介绍一些。运行时的加载的工作 不是由main完成的,而是由/lib/ld.so(不同平台会有些出入)完成。他有自己的查找动态连接库的规则, 所以在不更新ld.so的查找路径的情况下,会出现上

12、边的错误。根据ld.so的man手册,ld.so共有六种方式查找需要的动态库,这里只介绍常用的三种方式,详细的 内容见附录ld.so1.按照环境变量LD_LIBRARY_PATH的内容查找(setuid类的程序排除)2.在库高速缓存文件ld.so.conf中给出的路径查找3.在/lib,/usr/lib目录下查找相对应的,可以分别通过设置环境变量LD_LIBRARY_PATH,通过在ld.so.conf文件中添加路径和将 动态库文件复制到/lib、/usr/lib目录下,使动态库可以在加载时被找到。 root Benson libtest# export LD_LIBRARY_PATH=$LD

13、_LIBRARY_PATH:/pwd root Benson libtest# cat pwd /etc/ld.so.conf ; ldconfig root Benson libtest# cp libmy.so /lib -f 以上三种方式都可以工作。关于ldconfig的使用详解,见附录ldconfig此时再执行main,可以正常运行了。通过ldd命令,可以看到main程序依赖于libmy.so。 root Benson libtest# ldd main libtest.so = not found libc.so.6 = /lib/tls/libc.so.6 (0x42000000)

14、 /lib/ld-linux.so.2 = /lib/ld-linux.so.2 (0x40000000) 4.4.动态库的显式调用动态库的显示调用,也需要库文件被加载到内存中。但是使用方法和静态库完全不同。需要系统 调用dlopen dlsym dlclose dlerror 的支持。可以使用同一个libmy.so文件,但是需要新的测试文件 : /* main.c 测试动态库显式调用的程序 */ #include /用于动态库管理的系统头文件 #include libmy.h /要把函数的头文件包含进来,否则编译时会报错 int main(void) /* 声明对应的函数的函数指针 */ v

15、oid (*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(p

16、szErr != NULL) printf(%s/n, pszErr); dlclose(pdlHandle); return -1; /* 实现函数调用 */ pTest (); /*程序结束时关闭动态库 */ dlclose(pdlHandle); return 0; 编译时需要加入-ldl选项: root Benson libtest# gcc -ldl -o main main.c 运行程序,成功。这种方式,不需要在链接阶段指定动态库的位置。在运行阶段,调用要使用的函数通过ldd命令,可以看到main程序不再依赖于libmy.so,转为 依赖libdl.so libdl.so.2 =

17、/lib/libdl.so.2 (0x40034000) libc.so.6 = /lib/tls/libc.so.6 (0x42000000) /lib/ld-linux.so.2 = /lib/ld-linux.so.2 (0x40000000) Chapter5.链接时同时使用动态库和静态库当一个执行程序链接时需要多个库文件时,通常情况下,我们要么统一采用静态链接,要么统一采用动态链接。 实际上,我们可以通过gcc的选项分别指定每种库的链接方式:-Wl -Bstatic;-Wl -Bdynamic。 gcc -o main main.c -Wl -Bstatic -lc -Wl -Bdy

18、namic -test 上边这个例子中制定了静态链接libc和动态连接libtest。而实际上gcc选项-Wl表示将后边的参数传给链接器 ,-Bstatic和-Bdynamic是ld的选项。AppendixA.附 录A.1.ldconfigldconfig用来维护ld.so加载的动态库的路径信息和依赖信息,路径信息存放在/etc/ld.so.conf中 ,/etc/ld.so.cache中存放了/lib /usr/lib 和/etc/ld.conf包含的路径内的所有库信息。 可以通过ldd命令查看动态库的依赖信息。ldconfig有两种常用的使用方法:1.将需要查找的目录加入/etc/ld.s

19、o.conf,然后运行ldconfig更新,更新结果永久有效2.ldconfig + 路径,这种方式能直接更新指定的目录,但是结果在下次执行ldconfig 时,将会失效。ldconfig的选项比较有用的是-v和-n,其他的可参考man手册:-v 或 -verbose 详细的显示扫描的目录及搜索到的动态连接库,还有它所创建的 链接的名字-n 使扫描时,不扫描默认目录/lib、/usr/lib和/etc/ld.so.conf包含的路径A.2.lddldd命令很简单,用来显示文件所依赖的动态库文件,同样-v选项显示详细信息。A.3.arar命令用来创建归档文件,修改归档文件,和提取归档文件中的模块

20、。这里归档文件就是静态库, 模块就是里边的各个.o文件。在静态库中每个.o文件的内容,权限,时间戳,文件所有者,文件所属组 都将被保留,并且可在提取时回复。ar通过在静态库中创建模块列表来维护内容结构。可以通过nm -s 命令查看这个列表内容。ar命令的选项很多,可通过查看man手册获取全部内容,这里我举几个例子来说明 它的主要功能:1.创建静态库文件:2. ar -rc libtest.a libmy.o libtest.o 选项分为r 和 c。-r 表示将后边的.o模块加入库文件中;-c 表示当库文件不存在时创建。 同样,向存在的库文件添加新的模块时,只需要-r 选项即可。3.查看静态库中

21、的模块:4. root Benson libtest# ar -t libtest.a5. libmy.o6. libtest.o 7.删除静态库中的模块:8. ar -d libtest.a libmy.o 此时在查看库的模块,libmy.o就不存在了。9.提取静态库中的模块:10. root Benson libtest# ls 11. libtest.a12. root Benson libtest# ar -x libtest.a libmy.o ; ls13. libtest.a libmy.o 从libtest.a中提取出了libmy.o文件A.4.nmnm 命令用来查看目标文件中

22、的符号信息,nm命令对每个符号显示如下内容:每个符号的值。当指定-S选项时,显示函数符号对应的函数体的大小。每个符号的类型,如,U表示该符号没有在库中定义;T表示该符号在库中定义。还有其他的内容涉及 到目标文件的格式,这里就不详细介绍。每个符号的名字。nm的选项中,-s选项用来显示静态库文件的列表信息。其他选项可查看man手册。A.5.ranlib为静态库生成索引信息,并将索引信息保存在静态库文件中,它是ar -s命令的变形。带有索引的 静态库能够加快连接速度,并允许库中的函数相互调用,而不需要考虑函数位置的先后。A.6.PICPIC(Position Independent Code),位置

23、无关编码。是一种库文件的编码组织方式, 其特点是方便系统装载。是否支持这种格式的动态库,与硬件系统平台有关。简单的说,这种格式的库文件包含两个符号GOT(_GLOBAL_OFFSET_TABLE_)和PLT (Procedure Linkage Table)。调用函数实际调用的是PLT里的地址,访问全局变量通过GOT里边的地址 这些地址在未运行时不确定,在加载运行后,才被解析出来,所以可以加载到进程地址空间的任何地方。摘自网络的一篇文章,含有更多信息:PIC code radically differs from conventional code in the way it calls fu

24、nctions and operates on data variables.It will access these functions and data through an indirection table, the Global Offset Table (GOT), by software convention accessible using the reserved name _GLOBAL_OFFSET_TABLE_.The exact mechanism used for this is hardware architecture dependent, but usuall

25、y a special machine register is reserved for setting up the location of the GOT when entering a function.The rationale behind this indirect addressing is to generate code that can be independently accessed of the actual load address.In a true PIC library without relocations in the text segment, only

26、 the symbols exported in the Global Offset Table need updating at run-time depending on the current load address of the various shared libraries in the address space of the running process.Likewise, procedure calls to globally defined functions are redirected through the Procedure Linkage Table (PLT

27、) residing in the data segment of the core image. Again, this is done to avoid run-time modifications to the text segment.The linker-editor allocates the Global Offset Table and Procedure Linkage Table when combining PIC object files into an image suitable for mapping into the process address space.

28、 It also collects all symbols that may be needed by the run-time link-editor and stores these along with the images text and data bits. Another reserved symbol, _DYNAMIC is used to indicate the presence of the run-time linker structures. Whenever _DYNAMIC is relocated to 0, there is no need to invok

29、e the run-time link- editor. If this symbol is non-zero, it points at a data structure from which the location of the necessary relocation- and symbol information can be derived. This is most notably used by the start-up module, crt0, crt1S and more recently Scrt1. The _DYNAMIC structure is conventi

30、onally located at the start of the data segment of the image to which it pertains.On most architectures, when you compile source code to object code, you need to specify whether the object code should be position independent or not. There are occasional architectures which dont make the distinction,

31、 usually because all object code is position independent by virtue of the Application Binary Interface (ABI), or less often because the load address of the object is fixed at compile time, which implies that shared libraries are not supported by such a platform). If an object is compiled as position independent code (PI

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2