【Linux】如何将自定义源文件打包并生成动态库

news2024/10/7 8:19:51

在这之前我们已经讲述了如何将自定义源文件打包并生成静态库,本文来带你了解如何打包成为动态库并使用

  • 动态库打包
  • 动态库使用
    • 1.增加环境变量方法
    • 2.配置`.conf`文件
    • 3.创建一个软连接在当前目录
    • 4.创建一个软连接在系统库目录
  • 静态库的加载
  • 动态库的加载

关于源文件的书写,以及相关库的知识的引入在上一篇“【Linux】如何将自定义源文件打包并生成静态库”已经说明过了,本篇就不再过多赘述。

动态库打包

动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码

跟静态库类似,我们也是要打包.o文件,但是我们要增加一个fPIC(产生位置无关码position independent code)选项

[AMY@VM-12-15-centos lesson_13]$ gcc -c -fPIC my_add.c my_sub.c
[AMY@VM-12-15-centos lesson_13]$ ll
total 28
-rw-rw-r-- 1 AMY AMY  110 Jun 25 20:55 my_add.c
-rw-rw-r-- 1 AMY AMY   64 Jun 25 20:47 my_add.h
-rw-rw-r-- 1 AMY AMY 1592 Jun 26 15:33 my_add.o
-rw-rw-r-- 1 AMY AMY  110 Jun 25 20:55 my_sub.c
-rw-rw-r-- 1 AMY AMY   64 Jun 25 20:49 my_sub.h
-rw-rw-r-- 1 AMY AMY 1592 Jun 26 15:33 my_sub.o

.o文件归档生成动态库:

[AMY@VM-12-15-centos lesson_13]$ gcc -shared -o libmymath.so my_add.o my_sub.o

[AMY@VM-12-15-centos lesson_13]$ file libmymath.so
libmymath.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, 
BuildID[sha1]=13ba29aec0c8343949d51a3690896ed7b071f867, not stripped

我们手动创建一个目录,将库文件与头文件放入一个目录下:

[AMY@VM-12-15-centos lesson_13]$ mkdir mylib
[AMY@VM-12-15-centos lesson_13]$ mkdir mylib/lib
[AMY@VM-12-15-centos lesson_13]$ mkdir mylib/include
[AMY@VM-12-15-centos lesson_13]$ mv libmymath.so mylib/lib/
[AMY@VM-12-15-centos lesson_13]$ cp *.h mylib/include/
[AMY@VM-12-15-centos lesson_13]$ tree mylib
mylib
├── include
│   ├── my_add.h
│   └── my_sub.h
└── lib
    └── libmymath.so

2 directories, 3 files

我们将左边的目录归为使用者,右边的目录为开发者,现在我们lesson_13目录下归整好的mylib目录拷贝到test目录下,这一操作相当于,使用者得到了这个静态库
在这里插入图片描述


动态库使用

按照我们上一篇详细讲过的如何使用库操作:

[AMY@VM-12-15-centos test]$ gcc -o mymath main.c -I ./mylib/include -L ./mylib/lib -l mymath

虽然这样我们生成了一个mymath文件,但是我们直接运行:

[AMY@VM-12-15-centos test]$ ls
main.c  mylib  mymath
[AMY@VM-12-15-centos test]$ ./mymath
./mymath: error while loading shared libraries: libmymath.so: 
cannot open shared object file: No such file or directory

错误:./mymath:加载共享库时出现错误:libmymath.so:不能打开共享目标文件原因是没有这样的文件或目录

我们查看一下mymath用于打印程序或者库文件所依赖的共享库列表:

[AMY@VM-12-15-centos test]$ ldd mymath
	linux-vdso.so.1 =>  (0x00007ffdf4deb000)
	libmymath.so => not found
	libc.so.6 => /lib64/libc.so.6 (0x00007f29261ca000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2926598000)

由上面可发现libmymath.so => not found我们在静态库中看不到的现在在动态库能够看到,但是它显示not found找不到这个库文件。

我们现在将我们所能提供的头文件库文件路径,以及库文件的具体名称都提供了,但是为什么这个库文件还是找不到呢?

我们是告诉了库文件头文件的路径以及库名称,但是这些都是告诉给gcc编译器的,当我们把程序编译完以后和gcc已经没有关系了,程序运行起来,操作系统OS和shell也是需要知道库在哪的!!

错误原因:我们的库没有在系统路径下面,OS无法找到

如何告诉操作系统OS我们的库在哪:

1.增加环境变量方法

系统运行时搜索库,除了会在系统固定路径搜索,还会在环境变量中搜索

[AMY@VM-12-15-centos test]$ echo $LD_LIBRARY_PATH
:/home/AMY/.VimForCpp/vim/bundle/YCM.so/el7.x86_64

将库所在的路径添加到LD_LIBRARY_PATH环境变量中

[AMY@VM-12-15-centos test]$ pwd
/home/AMY/zt/test
[AMY@VM-12-15-centos test]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/AMY/zt/test/mylib/lib

添加完以后的环境变量,会多出当前库所在的路径:

[AMY@VM-12-15-centos test]$ echo $LD_LIBRARY_PATH
:/home/AMY/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/AMY/zt/test/mylib/lib

最终结果,我们发现libmymath.so链接上了

[AMY@VM-12-15-centos test]$ ldd mymath
	linux-vdso.so.1 =>  (0x00007ffd06ffe000)
	libmymath.so => /home/AMY/zt/test/mylib/lib/libmymath.so (0x00007f914e427000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f914e059000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f914e629000)

运行结果:
在这里插入图片描述
我们这种添加库的路径到环境变量中的方法,一旦我们重新登陆shell,就会失效,因为每次登陆环境变量会回到默认,我们需要在系统文件中去更改,这个操作很麻烦。

2.配置.conf文件

我们在这个目录下面,将当前库的目录随意写入任意.conf文件

[AMY@VM-12-15-centos test]$ cd /etc/ld.so.conf.d/
[AMY@VM-12-15-centos ld.so.conf.d]$ ll
total 28
-rw-r--r-- 1 root root 26 Dec 16  2020 bind-export-x86_64.conf
-rw-r--r-- 1 root root 19 Aug  9  2019 dyninst-x86_64.conf
-rw-r--r-- 1 root root 24 Nov  5  2020 hcoll.conf
-r--r--r-- 1 root root 63 Dec 19  2020 kernel-3.10.0-1160.11.1.el7.x86_64.conf
-rw-r--r-- 1 root root 17 Oct  2  2020 mariadb-x86_64.conf
-rw-r--r-- 1 root root 22 Nov  5  2020 mxm.conf
-rw-r--r-- 1 root root 24 Nov  5  2020 sharp.conf

我们这里创建一个my.conf文件,然后将之前库的路径写入my.conf之中(我们需要使用sudo来提权,否则会失败)

[AMY@VM-12-15-centos ld.so.conf.d]$ sudo touch my.conf
[AMY@VM-12-15-centos ld.so.conf.d]$ sudo vim my.conf
[AMY@VM-12-15-centos ld.so.conf.d]$ cat my.conf
/home/AMY/zt/test/mylib/lib

我们还需要更新一下配置操作:

[AMY@VM-12-15-centos ld.so.conf.d]$ sudo ldconfig

现在我们就可以运行成功:
在这里插入图片描述
这种写法,我们重新登录还是可以继续正常运行

如果我们想要撤回刚刚的操作只需要删除这个文件,并更新一下:

[AMY@VM-12-15-centos ld.so.conf.d]$ sudo rm my.conf
[AMY@VM-12-15-centos ld.so.conf.d]$ sudo ldconfig

3.创建一个软连接在当前目录

[AMY@VM-12-15-centos test]$ ln -s ~/zt/test/mylib/lib/libmymath.so libmymath.so
[AMY@VM-12-15-centos test]$ ll
total 20
lrwxrwxrwx 1 AMY AMY   40 Jun 26 21:07 libmymath.so -> /home/AMY/zt/test/mylib/lib/libmymath.so
-rw-rw-r-- 1 AMY AMY  201 Jun 25 21:18 main.c
drwxrwxr-x 4 AMY AMY 4096 Jun 26 15:46 mylib
-rwxrwxr-x 1 AMY AMY 8432 Jun 26 15:58 mymath
[AMY@VM-12-15-centos test]$ ldd mymath
	linux-vdso.so.1 =>  (0x00007ffd531ef000)
	libmymath.so (0x00007fed48430000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fed48062000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fed48632000)

这样程序可以直接运行:
在这里插入图片描述

4.创建一个软连接在系统库目录

我们还可以将软连接建立在系统库目录中:

[AMY@VM-12-15-centos test]$ sudo ln -s ~/zt/test/mylib/lib/libmymath.so /lib64/libmymath.so
//下面是链接查看
[AMY@VM-12-15-centos test]$ ls /lib64/libmymath.so -l
lrwxrwxrwx 1 root root 40 Jun 26 21:12 /lib64/libmymath.so -> /home/AMY/zt/test/mylib/lib/libmymath.so

在系统库的目录下就具备一个软连接指向我们创建的库的路径,这样我们的libmymath.so就有了链接

[AMY@VM-12-15-centos test]$ ldd mymath
	linux-vdso.so.1 =>  (0x00007ffd4b161000)
	libmymath.so => /lib64/libmymath.so (0x00007f2bb759f000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f2bb71d1000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2bb77a1000)

静态库的加载

静态库是可在编译时链接到可执行文件的目标文件的集合。这意味着静态库中的代码将复制到可执行文件中,然后可执行文件可以在不存在静态库的情况下运行。

Linux 静态库的加载过程分为两步:

  • 链接器将静态库链接到可执行文件。此过程涉及解析静态库中的所有符号,并将代码从静态库复制到可执行文件中。
  • 然后加载并执行可执行文件。加载可执行文件时,操作系统会将静态库从磁盘加载到内存中。

静态库的优点:
它们比动态库更快,因为静态库中的代码被复制到可执行文件中。它们比动态库小,因为它们不需要包含有关如何在运行时加载库的任何信息。

静态库的缺点:
如果不重新编译可执行文件,则无法更新它们。它们可以使可执行文件更大。


动态库的加载

动态库是在运行时加载到内存中的库。这意味着动态库中的代码不会复制到可执行文件中,并且只有在存在动态库时,可执行文件才能运行。

Linux 动态库的加载过程:

  • 操作系统会在预定义的搜索路径中查找动态库。查找到以后将其加载到内存中,加载过程中会分配内存,并将动态库的代码和数据段读入内存中。此时,动态库还没有关联到任何一个进程,因此这段内存是只读的。
  • 在动态库加载到内存中后,还需要进行重定位。这是因为动态库中的函数和变量引用的地址是相对地址,需要根据实际的内存地址进行修正。这个过程会使用到内存中的页表,将动态库的相对地址映射到实际的内存地址上。
  • 在重定位完成后,动态库就可以被映射到进程的地址空间中。这个过程会使用到虚拟内存机制,将动态库的代码和数据段映射到进程的地址空间中。这个过程会使用到页表,将动态库的虚拟地址映射到实际的物理地址上。
  • 一旦动态库被映射到进程的地址空间中,就可以通过调用动态库中的函数来使用其中的功能了。

动态库的优点:

  1. 节省内存:动态库在运行时才会被加载到内存中,而在程序未运行时并不会占用内存。
  2. 可以共享:动态库可以在多个进程之间共享,因为它们的代码是在运行时才被加载。这样可以减少磁盘空间的占用,提高系统效率。
  3. 可以动态更新:动态库可以在运行时被更新,而不需要重新编译整个程序。这样可以方便地修复程序中的错误,或者升级程序中的功能。

动态库的缺点:

  1. 运行时开销:动态库在运行时需要进行加载和链接,这会增加一些运行时的开销。
  2. 难以分发:由于动态库需要在运行时动态加载,因此在分发程序时需要同时分发动态库,这可能会增加分发的难度。

如有错误或者不清楚的地方欢迎私信或者评论指出🚀🚀

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

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

相关文章

使用Maven创建Java Web项目

环境 windows环境 jdk8 maven3.6 IDEA2022 步骤 1.新建maven工程 使用IDEA工具,File->New->Project->选择项目目录,填写项目名称,选择对应选项,其中Create Git repository可不勾选,如下图所示&#xff…

怎样将递归函数转为非递归函数

一道非常不错的面试题:不支持递归的程序语言如何实现递归程序? 之所以说这道题好,是因为: 首先,它不是纯粹考概念和死记硬背,求职者在回答问题之前需要进行一定的思考; 其次,这道题…

phar协议文件包含

实验目的 通过本实验,了解php封装伪协议,掌握phar协议文件包含的用法 实验环境 操作机:kali 靶机:Windows 2007 实验地址:http://靶机ip/exp/include2/phar/phar1/ 用户名:college 密码:360C…

Script file ‘D:\Anaconda365\Scripts\conda-script.py‘ is not present

运行anaconda,出现错误,找不到conda-script.py, 解决途径: 用everything查找电脑上的conda-script.py文件, 将查到的codna-script.py文件放入Script文件夹完美解决。 再从运行conda list,就不报错了。

监控系统Zabbix

zabbix概述 作为一个运维,需要会使用监控系统查看服务器状态以及网站流量指标,利用监控系统的数据去了解上线发布的结果,和网站的健康状态。 利用一个优秀的监控软件,我们可以: 通过一个友好的界面进行浏览整个网站…

前端Vue自定义精美上下滚动通告栏组件 常用于展示公告信息 上下滚动跑马灯 上下滚动广播

前端Vue自定义精美上下滚动通告栏组件 常用于展示公告信息 上下滚动跑马灯 上下滚动广播,下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13318 效果图如下: # cc-noticeBar #### 使用方法 使用方法 <!-- 默认颜色#333公告栏 -…

YoloV5/YoloV7改进---注意力机制:SRM,卷积神经网络再校准模块,性能优于SE、GE

目录 1.SRM介绍 ​编辑 2.SRM引入到yolov5 2.1 加入common.py中&#xff1a; 2.2 加入yolo.py中&#xff1a; 2.3 yolov5s_SRM.yaml 2.4 yolov5s_SRM1.yaml 3.YOLOv5/YOLOv7魔术师专栏介绍 1.SRM介绍 论文&#xff1a;https://openaccess.thecvf.com/content…

设计模式7:装饰者模式

目录 装饰者模式是要解决什么问题&#xff1f;装饰者模式在JDK中有哪些实际应用&#xff1f;装饰者模式在Android SDK中有哪些实际应用&#xff1f;装饰者模式和适配器模式的区别是什么&#xff1f;装饰者模式和代理模式的区别是什么&#xff1f; 装饰者模式是要解决什么问题&a…

基于matlab使用单类全卷积数据描述异常检测网络检测药丸图像上的缺陷(附源码)

一、前言 此示例演示如何使用单类全卷积数据描述 &#xff08;FCDD&#xff09; 异常检测网络检测药丸图像上的缺陷。 异常检测的一个关键目标是让人类观察者能够理解为什么经过训练的网络将图像分类为异常。FCDD支持e可解释的分类&#xff0c;它用证明神经网络如何达到其分类…

Python快速将多个文件夹内的文件移动至一个文件夹内

在日常办公中生活中&#xff0c;我们经常需要将多个文件夹内的文件如&#xff1a;(图片png,jpg,jpeg&#xff0c;word文档&#xff0c;Excel,PPT等等)&#xff0c;需要将这个文件夹内的文件移动至同一个文件夹内&#xff0c;如果我们复制粘贴的话&#xff0c;将会非常的繁琐以及…

Impala3.4源码阅读笔记(七)解析ScanNode(上)

前言 本文为笔者个人阅读Apache Impala源码时的笔记&#xff0c;仅代表我个人对代码的理解&#xff0c;个人水平有限&#xff0c;文章可能存在理解错误、遗漏或者过时之处。如果有任何错误或者有更好的见解&#xff0c;欢迎指正。 正文 我们知道Impala执行一条SQL的主要流程…

在vscode中配置git bash终端

将以下配置添加到vscode中的settings.json中 "terminal.integrated.profiles.windows": {"PowerShell": {"source": "PowerShell","icon": "terminal-powershell"},"Command Prompt": {"path"…

【C++】类和对象(中篇)----->六大默认成员函数

目录 一、类的6个默认成员函数 二、构造函数 1、概念 2、特性 三、析构函数 1、概念 2、特性 四、拷贝构造函数 1、概念 2、特征 五、赋值运算符重载 1、运算符重载 2、值运算符重载 2.1 赋值运算符重载格式 2.2 赋值运算符只能重载成类的成员函数不能重载成全局函数 2.3…

使用postman发请求报错Error: connect ECONNREFUSED 127.0.0.1:33210

原因&#xff1a;代理服务器问题 解决&#xff1a; 两种方案任选其一 1.电脑网络设置&#xff0c;关闭代理服务器 2.postman 的设置proxy 取消勾选

Mac中VSCode配置vue项目环境

一、下载VSCode 进入VSCode官网&#xff0c;下载Mac版安装包 设置中文: vscode导航栏view -> Command Palette -> 输入Configure Display Language -> 选择简体中文 -> 重启 二、下载node.js 下载地址&#xff1a;node.js官网&#xff0c;建议下载长期维护版本…

交叉编译paho带SSL

1.新建文件夹 /home/yiweijiao/woke_lab/paho 2.解压paho.mqtt.c到/home/yiweijiao/woke_lab/paho/paho.mqtt.c 3.新建文件夹/home/yiweijiao/woke_lab/paho/openssl_lib 将已经交叉编译好的openssl复制到这里 4.cd /home/yiweijiao/woke_lab/paho/paho.mqtt.c 新建文件夹…

hive和datax數據採集數量對不上

hive和datax數據採集數量對不上 對數據的時候發現有些對不上&#xff0c;在hive中 staff_id DF67B3FC-02DD-4142-807A-DF4A75A4A22E’的數據只有1033 而在mysql中發現staff_id DF67B3FC-02DD-4142-807A-DF4A75A4A22E’的數據有4783條記錄&#xff08;昨天的記錄是4781&#…

控制哈威比例多路阀放大板

控制各种不带电气位移反馈的HAWE哈威多路比例阀PSV系列、PSVF系列等比例电磁铁。 比例多路阀用于控制液压执行元件的运动方向的运动方向和运动速度(无级地,并且不取决于负载).为此,可使多个执行元件同时并相互独立地以不同的速度和压力工作,直到所有部分流量的总和达到泵的流量…

leetcode 404. 左叶子之和

2023.7.6 这道题关键就是要判断某个节点是否为左叶子节点&#xff0c;但是必须要靠他的父节点来判断&#xff0c;逻辑就是其父节点的左孩子不为空 并且 父节点的左孩子的左孩子和右孩子都为空&#xff0c;此时该节点就是左叶子了。 下面用两种迭代法求解&#xff1a; 队列&…

聚观早报|比亚迪在巴西建工厂;国产Model系列贡献约半数交付量

今日要闻&#xff1a;比亚迪在巴西建三座工厂&#xff1b;小米对华为锁屏专利发起无效宣告请求&#xff1b;国产Model系列贡献约半数交付量&#xff1b;杨澜公司回应数百万财产被冻结&#xff1b;雅虎公司计划重新上市 比亚迪在巴西建三座工厂 7 月 5 日消息&#xff0c;据比亚…