Linux:动态链接

news2025/3/10 21:11:27

文章目录

  • 动态链接共享库
    • 静态库的缺点
    • 共享库
    • 共享库是以两种不同的方式来“共享”
      • 第一种:共享这个so文件中的代码和数据
      • 第二种:共享库的.text 节的副本可以被不同的正在运行的进程共享
    • 动态链接过程
  • 动态链接的用武之地和使用场景
    • 分发软件
    • 构建高性能 Web 服务器
  • 动态链接的API/接口介绍
    • dlopen:让程序在运行时加载和链接共享库
    • dlsym:
    • dlclose
    • dlerror
  • 利用dl相关接口动态链接共享库示例
  • 共享库和 Java 本地接口

动态链接共享库

静态库的缺点

研究的静态库解决了许多关于如何让大量相关函数对应用程序可用的问题。然而,静态库仍然有一些明显的缺点。静态库和所有的软件一样,需要定期维护和更新。如果应用程序员想要使用一个库的最新版本,他们必须以某种方式了解到该库的更新情况,然后显式地将他们的程序与更新了的库重新链接。
什么是静态链接?有什么用?

另一个问题是几乎每个C程序都使用标准 I/O 函数,比如 printf scanf。在运行时,这些函数的代码会被复制到每个运行进程的文本段中。在一个运行上百个进程的典型系统上,这将是对稀缺的内存系统资源的极大浪费。(内存的一个有趣属性就是不论系统的内存有多大,它总是一种稀缺资源。磁盘空间和厨房的垃圾桶同样有这种属性。)

共享库

共享库(shared library)是致力于解决静态库缺陷的一个现代创新产物。共享库是一个目标模块,在运行或加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来。这个过程称为动态链接(dynamic linking),是由一个叫做动态链接器(dynamic linker)的程序来执行的。共享库也称为共享目标(shared object),在 Linux 系统中通常用.so后缀来表示。微软的操作系统大量地使用了共享库,它们称为 DLL(动态链接库)。

共享库是以两种不同的方式来“共享”

共享库是以两种不同的方式来“共享”的。

第一种:共享这个so文件中的代码和数据

首先,在任何给定的文件系统中,对于一个库只有一个.so 文件。所有引用该库的可执行目标文件共享这个so文件中的代码和数据,而不是像静态库的内容那样被复制和嵌入到引用它们的可执行的文件中。

第二种:共享库的.text 节的副本可以被不同的正在运行的进程共享

其次,在内存中,一个共享库的.text 节的一个副本可以被不同的正在运行的进程共享。

动态链接过程

图7-16 概括了图7-7 中示例程序的动态链接过程。
在这里插入图片描述

为了构造图 7-6 中示例向量例程的共享库 libvector.so,我们调用编译器驱动程序,给编译器和链接器如下特殊指令:
在这里插入图片描述

-fpic选项指示编译器生成与位置无关的代码
-shared选项指示链接器创建一个共享的目标文件。

一旦创建了这个库,随后就要将它链接到程序中:
在这里插入图片描述
这样就创建了一个可执行目标文件 prog21,而此文件的形式使得它在运行时可以和libvector.so链接。

基本的思路是当创建可执行文件时,静态执行一些链接,然后在程序加载时,动态完成链接过程。认识到这一点是很重要的:

此时,没有任何 lbvector.so的代码和数据节真的被复制到可执行文件 prog21 中。反之,链接器复制了一些重定位和符号表信息,它们使得运行时可以解析对 libvector.so 中代码和数据的引用。当加载器加载和运行可执行文件 prog21 时,加载部分链接的可执行文件 prog21。接着,它注意到 prog21 包含一个.interp 节,这一节包含动态链接器的路径名,动态链接器本身就是一个共享目标(如在 Linux 系统上的 ld-linux.so)加载器不会像它通常所做地那样将控制传递给应用,而是加载和运行这个动态链接器。

然后,动态链接器通过执行下面的重定位完成链接任务:

  • 重定位 libc.so的文本和数据到某个内存段。
  • 重定位 libvector.so 的文本和数据到另一个内存段。
  • 重定位 prog21 中所有对由 libc.so和 ibvector.so定义的符号的引用。

最后,动态链接器将控制传递给应用程序。从这个时刻开始,共享库的位置就固定了,并且在程序执行的过程中都不会改变。

动态链接的用武之地和使用场景

到目前为止,我们已经讨论了在应用程序被加载后执行前时,动态链接器加载和链接共享库的情景。然而,应用程序还可能在它运行时要求动态链接器加载和链接某个共享库,而无需在编译时将那些库链接到应用中。

动态链接是一项强大有用的技术。下面是一些现实世界中的例子:

分发软件

微软 Windows 应用的开发者常常利用共享库来分发软件更新。他们生成一个共享库的新版本,然后用户可以下载,并用它替代当前的版本。下一次他们运行应用程序时,应用将自动链接和加载新的共享库。

构建高性能 Web 服务器

许多 Web 服务器生成动态内容,比如个性化的 Web 页面、账户余额和广告标语。早期的 Web 服务器通过使用 fork 和 execve 创建一个子进程,并在该子进程的上下文中运行 CGI程序来生成动态内容。

然而,现代高性能的 Web 服务器可以使用基于动态链接的更有效和完善的方法来生成动态内容。其思路是将每个生成动态内容的函数打包在共享库中。当一个来自 Web 浏览器的请求到达时,服务器动态地加载和链接适当的函数,然后直接调用它,而不是使用 fork 和execve 在子进程的上下文中运行函数。函数会一直缓存在服务器的地址空间中,所以只要一个简单的函数调用的开销就可以处理随后的请求了。这对一个繁忙的网站来说是有很大影响的。更进一步地说,在运行时无需停止服务器,就可以更新已存在的函数,以及添加新的函数。

动态链接的API/接口介绍

dlopen:让程序在运行时加载和链接共享库

Linux系统为动态链接器提供了一个简单的接口,允许应用程序在运行时加载和链接共享库。
在这里插入图片描述
dlopen 函数加载和链接共享库 filename。用已用带 RTLD_GLOBAL 选项打开了的库解析 filename中的外部符号。如果当前可执行文件是带-rdynamic 选项编译的,那么对符号解析而言,它的全局符号也是可用的。

flag 参数必须要么包括 RTLD_NOW,该标志告诉链接器立即解析对外部符号的引用,要么包括 RTLD_LAZY 标志,该标志指示链接器推迟符号解析直到执行来自库中的代码。这两个值中的任意一个都可以和 RTLD_GLOBAL标志取或。

dlsym:

在这里插入图片描述
dlsym函数的输入是一个指向前面已经打开了的共享库的句柄和一个 symbol 名字,如果该符号存在,就返回符号的地址,否则返回 NULL。

dlclose

在这里插入图片描述
如果没有其他共享库还在使用这个共享库,dlclose 函数就卸载该共享库

dlerror

在这里插入图片描述
dlerror 函数返回一个字符串,它描述的是调用 dlopen、dlsym 或者 dlclose 函数时发生的最近的错误,如果没有错误发生,就返回 NULL。

利用dl相关接口动态链接共享库示例

图7-17 展示了如何利用这个接口动态链接我们的 lbvector.so 共享库,然后调用它的 addvec 函数。要编译这个程序,我们可以用下面的方式调用 GCC:
在这里插入图片描述

代码:
在这里插入图片描述
在这里插入图片描述

共享库和 Java 本地接口

Java定义了一个标准调用规则,叫做Java 本地接口(Java Native Interface,JNI),它允许Java程序调用“本地的”C和C++ 函数。

JNI的基本思想是将本地C函数(如 foo)编译到一个共享库中(如 foo.so)。当一个正在运行的 Java 程序试图调用函数 foo 时,Java 解释器利用 dlopen 接口(或者与其类似的接口)动态链接和加载 foo.so,然后再调用 foo。

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

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

相关文章

初识Docker-什么是docker

Docker是一个快速交付应用、运行应用的技术 目录 一、Docker 二、运用场景 一、什么是Docker?它的作用是什么? Docker如何解决大型项目依赖关系复杂,不同组件依赖的兼容性问题? Docker允许开发中将应用、依赖、函数库、配置一起打包&…

服装店收银系统 一种私域运营的神器

私域运营是指通过建立和管理自己的客户数据库来实现精细化营销和客户关系管理。服装店收银系统是门店私域运营的神器之一,服装店收银系统可以帮助店主收集客户的购买信息、消费偏好等数据,从而更好地了解客户需求并进行个性化营销。 以下是一些服装店收银…

用Minikube 搭建一个单机k8s玩玩

Minikube 介绍 Minikube是一款单机搭建和管理Kubernetes集群的工具。与Kind 类似,但是个人认为比Kind 好用 Minikube 安装 mac如果安装了 Homebrew,直接执行以下命令安装minikube brew install minikubemac没有安装Homebrew,需要到官网下载选择系统配置…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextInput输入框组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextInput输入框组件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、TextInput 接口 TextInput(value?:{placeholder?: ResourceStr, tex…

HackTheBox - Medium - Linux - Jupiter

Jupiter Jupiter 是一台中等难度的 Linux 机器,它有一个使用 PostgreSQL 数据库的 Grafana 实例,该数据库在权限上过度扩展,容易受到 SQL 注入的影响,因此容易受到远程代码执行的影响。一旦站稳脚跟,就会注意到一个名…

被有道云笔记成功劝退拥抱Joplin(Joplin使用过程遇到的问题)

本人职业程序员,培训讲师(技术类)、活动主持人,对多端阅读是有些需求的,平时习惯墨水平板、手机和笔记本电脑登录着有道云笔记。其实本人对内容比较重视,对有道云笔记提供的什么AI服务、PDF转Word等功能是没…

企业级“RAS”的数据平台如何炼成?

从“看报表”到“数据分析结果直接投入运营”,数字化正在深入企业经营,数据系统正在成为核心生产系统。相应的,企业对“作业挂了”、“系统崩了”、“算不出来”的容忍度越来越低——只有足够稳定、可靠、专业的数据系统,才能及时…

虾皮跨境电商物流:打造高效便捷的全球供应链解决方案

随着全球化的推进和电子商务的蓬勃发展,跨境电商物流成为了越来越多商家和消费者关注的焦点。虾皮(Shopee)作为一家领先的电商平台,不仅提供了丰富多样的商品选择,还致力于为卖家和消费者提供高效便捷的跨境电商物流服…

WiFi+蓝牙物联网定制方案——五大核心难点

WiFi蓝牙物联网定制方案可以根据具体需求进行定制: 1、设备连接方案:采用WiFi和蓝牙技术,将物联网设备与智能手机、平板电脑等设备进行连接,实现数据传输和远程控制。 2、数据传输方案:通过WiFi和蓝牙技术,…

Android平台RTMP推送|轻量级RTSP服务能力封装代码实现

好多开发者问我们,有没有针对Android平台RTMP直播推送、轻量级RTSP服务模块的进一步封装,可以更便捷的调用大牛直播SDK接口。 为此,我们分享下我们针对Android平台SmartPublisher做的二次封装代码: package com.daniulive.smartp…

OpenCV | 告别人工目检:深度学习技术引领工业品缺陷检测新时代

文章目录 机器视觉缺陷检测工业上常见缺陷检测方法内容简介作者简介目录读者对象如何阅读本书获取方式 机器视觉 机器视觉是使用各种工业相机,结合传感器跟电气信号实现替代传统人工,完成对象识别、计数、测量、缺陷检测、引导定位与抓取等任务。其中工…

用BEVformer来卷自动驾驶-1

之所以是-1,是因为大概率1篇文章写不完,但是又不知道应该用几篇来说事,先写着看 按照惯例,上论文地址:2203.17270v1.pdf (arxiv.org) 什么是BEV, Birds -Eye-View的意思,就是鸟瞰 比如稍微传统一些的自动驾驶,大部分的实现。如果靠纯CV的方案的话,那么基本…

electron使用electron-builder进行MacOS的 打包、签名、公证、上架、自动更新

一、前言 由于electron在macOS下的坑太多,本文不可能把所有的问题都列出来,也不可能把所有的解决方案贴出来;本文也不太会讲解每一个配置点为什么要这么设置的原因,因为有些点我也说不清,我尽可能会说明的。所以&…

【排序算法】C语言实现选择排序与冒泡排序

文章目录 🚀前言🚀冒泡排序✈️冒泡排序的逻辑✈️冒泡排序coding 🚀选择排序✈️选择排序的逻辑✈️选择排序coding 🚀前言 这里是阿辉算法与数据结构专栏的第一篇文章,咱们就从排序算法开始讲起,排序算法…

【python】进阶--->网络编程(二)

一、分层模型 OSI/RM(开放系统互联参考模型) 是由国际标准化组织提出来的一种网络互联模型,成为所有的销售商都能实现的开放网络模型.(OSI模型提供我们理解网络协议的内部运作) OSI模型将网络通信工作分为7层,每一层为上一层服务,并为上一层提供一个访问的接口或者界面. 越下…

【数字图像处理】实验一 图像基本运算

图像基本运算 一、实验内容: 1. 熟悉和掌握利用Matlab工具进行数字图像的读、写、显示等数字图像处理基本步骤。 2. 熟练掌握各种图像点运算的基本原理及方法。 3. 能够从深刻理解点运算,并能够思考拓展到一定的应用领…

【爬虫软件】孔夫子二手书采集

项目演示 孔网爬取图书信息 目录结构 [ |-- api-ms-win-core-synch-l1-2-0.dll, |-- api-ms-win-core-sysinfo-l1-1-0.dll, |-- api-ms-win-core-timezone-l1-1-0.dll, |-- api-ms-win-core-util-l1-1-0.dll, |-- api-ms-win-crt-conio-l1-1-0.dll, |-- api…

【matlab】绘制横状双组渐变柱状图

【matlab】绘制横状双组渐变柱状图

Frida07 - dexdump核心源码分析

项目地址 https://github.com/hluwa/frida-dexdump 代码解析 项目中的核心函数是 searchDex: function searchDex(deepSearch) {var result [];Process.enumerateRanges(r--).forEach(function (range) {try {....} catch (e) {}});return result; }里面用了一…

OpenCV-Python(19):Canny边缘检测

目录 学习目标 Canny 边缘检测原理 1.噪声抑制(噪声去除) 2.梯度计算 3.非极大值抑制 4.双阈值检测(滞后阈值) 5.边缘连接 Canny 边缘检测步骤 Canny 边缘检测的OpenCV实现 不同阈值的边缘检测效果 学习目标 了解Canny边缘检测的概念学习掌握函数cv2.Canny()的用法 …