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

 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,一经查实,立即删除!

相关文章

网络编程套接字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调试器(三)

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

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

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

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 <…

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

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

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库函数…

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

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

open函数和errno全局变量

&#xff08;1&#xff09;open函数 man man 查看man文档的首页 其中DESCRIPTION部分描述了man文档的每一章的章节内容 第2章System calls为系统调用&#xff0c;即Liunx系统函数。 man 2 open 查看第二章的open函数的详细帮助文件。 open函数用于打开一个已经的文件或者创…

open函数和close函数的使用

学习几个常用的Linux系统I/O函数&#xff1a;open、close、write、read和lseek。注意&#xff0c;系统调用函数必须都考虑返回值。 &#xff08;1&#xff09;open函数的使用 首先&#xff0c;需要包含三个头文件&#xff1a;<sys/types.h> <sys/stat.h> <…

1091. Acute Stroke (30)

One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the results of image analysis in which the core regions are identified in each MRI slice, your job is to calculate the volume of the stroke core. Input Speci…

stat函数(stat、fstat、lstat)

#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> //需包含头文件 有如下三个函数的函数原型&#xff1a; int stat(const char *path, struct stat *buf); 第一个形参&#xff1a;指出文件&#xff08;文件路径&#xff09;&…

【Leetcode | 235】 235. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自己…

CPU和MMU(内存管理单元)

CPU的架构&#xff1a;要求能够理解从源程序到微指令的整个经历过程&#xff1a;存储器的层次结构&#xff08;网络资源下载到硬盘、磁盘缓存、内存、Cache、寄存器&#xff09;&#xff1b;CPU的四大部分&#xff1a;ALU、CU、中断系统和寄存器&#xff1b;程序执行的整个过程…

【C++ Primer | 09】容器适配器

一、stack s.push(): 向栈内压入一个成员&#xff1b; s.pop(): 从栈顶弹出一个成员&#xff1b; s.empty(): 如果栈为空返回true&#xff0c;否则返回false&#xff1b; s.top(): 返回栈顶&#xff0c;但不删除成员&#xff1b; s.size(): 返回栈内元素…

进程控制块PCB(进程描述符)

&#xff08;1&#xff09;PCB 每个进程在内核中都有一个进程控制块&#xff08;PCB&#xff09;来维护进程相关的信息&#xff0c;Linux内核的进程控制块是task_struct结构体。grep -r “task_struct” / 可以查找根目录下&#xff0c;包含task_struct的文件文件。或者 find…

【C++ Primer | 19】控制内存分配

1. 测试代码&#xff1a; #include <iostream> #include <new> #include <cstring> #include <cstdlib> using namespace std;void* operator new(size_t size) {cout << "global Override operator new" << endl;if (void* p…

【第15章】虚函数

一、为什么基类中的析构函数要声明为虚析构函数&#xff1f; 直接的讲&#xff0c;C中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说&#xff0c;如果派生类中申请了内存空间&#xff0c;并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数&am…

【C++ Primer | 08】IO库

一、istringstream类 描述&#xff1a;从流中提取数据&#xff0c;支持 >> 操作 这里字符串可以包括多个单词&#xff0c;单词之间使用空格分开 #include <iostream> #include <sstream> using namespace std; int main() {istringstream istr(&quo…

EXEC函数族的一般规律

事实上&#xff0c;只有execve是真正的系统调用&#xff0c;其它五个函数最终都调用execve&#xff0c;所以execve在man手册第2节&#xff0c;其它函数在man手册第3节。这些函数之间的关系如下图所示。