动态库(共享库)的制作和使用

 Linux下的动态库为lib*.so格式的二进制文件(目标文件),对应于Windows下的.dll格式的文件。

1)命名规则

lib+库名+.so

2)动态库的制作

1)生成与位置无关的代码(.o)  2)将.o文件打包成动态库(共享库)

        仍然以上篇文章的代码为例。

[root@localhost src]# gcc -fPIC -c *.c 
[root@localhost src]# ls
add.c  add.o  div.c  div.o  mul.c  mul.o  sub.c  sub.o      //这几个.o文件已经是库函数了,它们是与位置无关的代码。PIC可以小写也可以大写,表示生成与位置无关的代码。

[root@localhost src]# gcc -shared *.o -o libMytest.so
[root@localhost src]# ls
add.c  add.o  div.c  div.o  libMytest.so  mul.c  mul.o  sub.c  sub.o   // 将所有.o文件打包到动态库libMytest.so中

3)发布和使用动态库(共享库)

ldd命令用来显示二进制代码文件动态库的链接情况,如:ldd foo。将生成的libMytest.so库文件和头文件head.h发送给客服,客服就可以根据头文件中的接口情况,来知道库文件的功能 (具体怎么实现的他也不知道),从而客服就可以使用库文件来完成自己的工作了(main.c):

[root@localhost Calc]# gcc -pedantic -Wall -pipe main.c -I include/ -L src/ -lMytest -o zsx   //等价于: gcc -pedantic -Wall -pipe main.c -I include/ src/libMytest.so -o zsx
[root@localhost Calc]# ls
include  lib  main.c  src  zsx
[root@localhost Calc]# ldd zsx
    linux-vdso.so.1 =>  (0x00007ffffa7e8000)
    libMytest.so => not found
    libc.so.6 => /lib64/libc.so.6 (0x00007f591dc98000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f591e078000)    //  ld-linux-x86-64.so.2为动态链接器库文件(二进制文件),程序在执行时,动态库的调用需要动态链接器(一个程序,二进制代码文件)来进行调用。动态链接器是按照一定的规则去查找动态库文件的,即按照动态库的环境变量中的每个路径依次进行查找。Linux系统的/lib中就存放了系统在启动时候就需要用到的一些动态库。由ldd zsx可以看出,动态链接器无法找到代码所需要的动态库文件,即该动态库文件不在动态链接器的搜索路径中,下面给出几种解决方法:

1.将库文件libMytest.so放在/lib中就可以了,这样链接器就可以找到该库文件。但是,不建议这样做,因为是系统的库文件目录,如果名字冲突就会发生故障。

2.设置环境变量LD_LIBRARY_PATH的值。

[root@localhost Calc]# echo $LD_LIBRARY_PATH

[root@localhost Calc]# export LD_LIBRARY_PATH=/mnt/hgfs/share/gcc/Calc/src/libMytest.so
[root@localhost Calc]# echo $LD_LIBRARY_PATH
/mnt/hgfs/share/gcc/Calc/src/libMytest.so

此时链接器会首先在环境变量LD_LIBRARY_PATH中查找库文件,没有在去其余环境变量中查找。该方法也只是临时有效,当关闭终端后,环境变量LD_LIBRARY_PATH的值又恢复了空值,因此又需要再次设置!这种方法仅适用于:在开发测试动态库过程中使用,因为仅仅临时有效。在测试开发完成后,就需要一种稳定的方法。

3.修改当前用户的bash配置文件:~/.bashrc  修改完成后,需要关闭终端然后再次启用终端,该配置才会生效。

[root@localhost ~]# vim ~/.bashrc

export LD_LIBRARY_PATH=/mnt/hgfs/share/gcc/Calc/src

重启终端:

[root@localhost ~]# echo $LD_LIBRARY_PATH
/mnt/hgfs/share/gcc/Calc/src
即:  该路径永久生效

4.修改动态链接器的配置文件:/etc/ld.so.conf。将动态库的路径写到配置文件中,将libMytest.so所在绝对路径追加入到/etc/ld.so.conf文件;使用ldconfig -v 更新,使配置生效。

[root@localhost ~]# vim /etc/ld.so.conf
/mnt/hgfs/share/gcc/Calc/src

[root@localhost ~]# ldconfig -v

总结:

1).放到系统的库目录中 -- 不允许使用

2).临时测试

环境变量: LD_LIBRARY_PATH=将动态库的路径设置给该变量

将设置的值, 导入到系统环境变量中: export LD_LIBRARY_PATH

当终端关闭, 设置会失效

3).不常用的方法(永久设置):

在家目录的 .bashrc文件 中添加一句话: export LD_LIBRARY_PATH=动态库目录的绝对路径

.bashrc修改完成, 需要重启终端

4).常用的方法(永久设置)

1. 需要找动态连接器的配置文件 --  /etc/ld.so.conf

2. 动态库的路径写到配置文件中

3. 更新 ldconfig –v  v参数表示显示更新过程的详细信息

(4)动态库的优缺点

优点:执行程序体积小;动态库更新了,在接口不变的情况下,不需要重新编译程序,只需要保证新库跟旧库名称一样,接口一样,且新库能够被链接器找的到;

缺点:在发布最终版本的应用程序时,需要将动态库提供给客服;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385430.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

孤儿进程、僵尸进进程

一、儿进程与僵尸进程 1、基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工…

管道 -pipe

gcc编译器将源代码编译成可执行程序的过程中,需要经过许多中间步骤(预处理、编译、汇编、链接),这些过程实际上是由不同的程序来负责完成的(/usr/bin/gcc、cpp、ccl、as和ld等)。在这个过程的每一个阶段中&…

gdb调试器(一)

在默认情况下,gcc在编译时不会把调试符号插入到最终生成的二进制代码(机器代码)中,因为这样会急剧增加可执行程序的大小。如果需要在编译时生成调试符号的信息,则可以采用-g或-ggdb参数。 gcc在产生调试信息时&#x…

1048. 数字加密(20)

本题要求实现一种数字加密方法。首先固定一个加密用正整数A,对任一正整数B,将其每1位数字与A的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对13取余——这里用J代表10、Q代表11、K代表12;对偶数位&…

网络编程套接字API

uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);int inet_pton(int family, const char *strptr, void *addrptr); 分析: 第一个参数可以是AF_INET或AF_INET6&am…

gdb调试器(二)

Linux下的gdb(GNU Debugger)是一个用来调试C、C程序的调试器(命令行方式的调试器),能够在程序运行期间观察程序的内部结构和内存的使用情况。程序员也可以使用gdb来跟踪程序中的错误,从而减少程序员的工作量…

gdb调试器(三)

File/file 装入想要调试的可执行文件 run(r) 执行当前被调试的程序 kill(k) 终止正在调试的程序 quit(q) 退出gdb shell 使用户不离开gdb就可以执行Linux的shell命令 backtrace(bt) 回溯跟踪(当对代码进行调试时,run后…

IO多路复用之poll

1. poll函数原型: int poll(struct pollfd *fds, nfds_t nfds, int timeout);参数: fds:指向一个结构体数组的第0个元素的指针,每个数组元素都是一个struct pollfd结构,用于指定测试某个给定的fd的条件 nfds&#x…

makefile文件的书写规则(make和makefile)

对于makefile,掌握一个规则,两个变量和三个函数。下面介绍一个规则。 makefile的作用:一个项目代码的管理工具。当一个项目的代码文件数(如.c文件)太多,用gcc编译会太麻烦,如果全部文件一次性编…

100. 相同的树

给定两个二叉树,编写一个函数来检验它们是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入: 1 1 / \ / \ 2 3 2 3 [1,2,3], [1,2,3] 输出: true…

makefile的两个变量(自动变量和普通变量)

(1)普通变量 如: objmain.o add.o sub.o mul.o div.o //将后面的值赋值给obj,obj就是一个普通变量 targetzsx //将zsx赋值给target makefile中已经定义的一些普通变量(通常格式都是大写,类似环境变量,它们都是普通…

【C++ Priemr | 15】虚函数表剖析(二)

一、多重继承&#xff08;无虚函数覆盖&#xff09; 下面&#xff0c;再让我们来看看多重继承中的情况&#xff0c;假设有下面这样一个类的继承关系。注意&#xff1a;子类并没有覆盖父类的函数。 测试代码&#xff1a; class Base1 { public: virtual void f() { cout <…

1074. Reversing Linked List (25)

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K 3, then you must output 3→2→1→6→5→4; if K 4, you must output 4→3→2→1→5→6. Input Spe…

【Leetcode | 47】 222. 完全二叉树的节点个数

给出一个完全二叉树&#xff0c;求出该树的节点个数。 说明&#xff1a; 完全二叉树的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最…

makefile中的两个函数(wildcard和patsubst)

(1) wildcard函数 作用是查找指定目录下指定类型的文件&#xff0c;并最终返回一个环境变量&#xff0c;需要用$取值赋值给另一个环境变量&#xff01;该函数只有一个参数&#xff0c;如取出当前目录下的所有.c文件&#xff0c;并赋值给allc普通变量&#xff1a; allc$(wildc…

231. 2的幂

给定一个整数&#xff0c;编写一个函数来判断它是否是 2 的幂次方。 示例 1: 输入: 1 输出: true 解释: 20 1 示例 2: 输入: 16 输出: true 解释: 24 16 示例 3: 输入: 218 输出: false 解法一&#xff1a; class Solution { public:bool isPowerOfTwo(int n) {return(n >…

C库函数

Linux的系统I/O函数&#xff08;read、write、open、close和 lseek等&#xff09;与C语言的C库函数&#xff08;libc.so库文件中&#xff09;都是相对应的&#xff0c;它们都是动态库函数。如下图所示&#xff0c;C库函数有fopen、fclose、fwrite、fread和fseek等。这些C库函数…

【Leetcode | 48】226. 翻转二叉树

翻转一棵二叉树。 示例&#xff1a; 输入&#xff1a; 4 / \ 2 7 / \ / \ 1 3 6 9 输出&#xff1a; 4 / \ 7 2 / \ / \ 9 6 3 1 备注: 这个问题是受到 Max Howell 的 原问题 启发的 &#xff1a; 谷歌&#xff1a;我们90&#xff05;的…

C库函数与Linux系统函数之间的关系

由上小节知道&#xff0c;C库函数是借助FILE类型的结构体来对文件进行操作的&#xff0c;其本身只是在用户空间&#xff08;I/O缓冲区&#xff09;进行读写操作&#xff0c;而数据在内核与用户空间之间的传递、以及将内核与I/O设备之间的数据传递都是该C库函数进行一系列的系统…

【第十六章】模板实参推断

二、模板显式推断 在C中&#xff0c;若函数模板返回类型需要用户指定&#xff0c;那么在定义函数模板时&#xff0c;模板参数的顺序是很重要的&#xff0c;如下代码&#xff1a; template <typename T1, typename T2, typename T3> //模板一 T1 sum(T2 a, T3 b) {retu…