【程序员的自我修养】7. 动态链接

为什么要动态链接

  • 浪费内存和和磁盘空间
    • 每个程序都得拥有相同的拷贝
  • 程序的发布、更新和部署困难
    • 更新任何一个小的模块,整个程序都需要重新链接

动态链接:将链接的过程推迟到运行时

  • 节省内存
  • 减少物理页面的换入换出、增加CPU的缓存命中率
  • 更新升级方便,各个模块开发相互独立,耦合度更小
  • 可扩展性和兼容性
    • 兼容性体现在能够在操作系统和应用层增加中间层,消除平台的依赖性

动态链接的例子

  • lib.so 保留了完整的符号信息,
  • 链接器在链接时将符号标记为动态符号,在装载时在进行地址重定位
// lib.h
#ifndef __LIB_H__
#define __LIB_H__
void foobar(int i);
#endif
// lib.c
#include <stdio.h>
void foobar(int i) {printf("Printing from lib.so %d\n", i);
}
// program1.c
#include "lib.h"
int main() {foobar(1);return 0;
}
// program2.c
#include "lib.h"
int main() {foobar(2);return 0;
}$ gcc -fPIC -shared -o lib.so lib.c
$ gcc -c program1 program1.c ./lib.so
$ gcc -o program2 program2.c ./lib.so

动态链接程序运行时地址空间分布

$ ./program1 &
[1] 3966895
Printing from lib.so 1
$ cat /proc/3966895/maps
563546b06000-563546b07000 r--p 00000000 fc:02 2601194                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/program1
563546b07000-563546b08000 r-xp 00001000 fc:02 2601194                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/program1
563546b08000-563546b09000 r--p 00002000 fc:02 2601194                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/program1
563546b09000-563546b0a000 r--p 00002000 fc:02 2601194                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/program1
563546b0a000-563546b0b000 rw-p 00003000 fc:02 2601194                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/program1
563547e2e000-563547e4f000 rw-p 00000000 00:00 0                          [heap]
7f4d5c20a000-7f4d5c20d000 rw-p 00000000 00:00 0 
7f4d5c20d000-7f4d5c22f000 r--p 00000000 fc:02 139834                     /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f4d5c22f000-7f4d5c3a7000 r-xp 00022000 fc:02 139834                     /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f4d5c3a7000-7f4d5c3f5000 r--p 0019a000 fc:02 139834                     /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f4d5c3f5000-7f4d5c3f9000 r--p 001e7000 fc:02 139834                     /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f4d5c3f9000-7f4d5c3fb000 rw-p 001eb000 fc:02 139834                     /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f4d5c3fb000-7f4d5c3ff000 rw-p 00000000 00:00 0 
7f4d5c40a000-7f4d5c40b000 r--p 00000000 fc:02 2601193                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/lib.so
7f4d5c40b000-7f4d5c40c000 r-xp 00001000 fc:02 2601193                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/lib.so
7f4d5c40c000-7f4d5c40d000 r--p 00002000 fc:02 2601193                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/lib.so
7f4d5c40d000-7f4d5c40e000 r--p 00002000 fc:02 2601193                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/lib.so
7f4d5c40e000-7f4d5c40f000 rw-p 00003000 fc:02 2601193                    /home/ubuntu/cpp_learn/effective_cpp/xiuyang07/lib.so
7f4d5c40f000-7f4d5c411000 rw-p 00000000 00:00 0 
7f4d5c411000-7f4d5c412000 r--p 00000000 fc:02 130951                     /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f4d5c412000-7f4d5c435000 r-xp 00001000 fc:02 130951                     /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f4d5c435000-7f4d5c43d000 r--p 00024000 fc:02 130951                     /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f4d5c43e000-7f4d5c43f000 r--p 0002c000 fc:02 130951                     /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f4d5c43f000-7f4d5c440000 rw-p 0002d000 fc:02 130951                     /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f4d5c440000-7f4d5c441000 rw-p 00000000 00:00 0 
7fff3218c000-7fff321ad000 rw-p 00000000 00:00 0                          [stack]
7fff321dd000-7fff321e0000 r--p 00000000 00:00 0                          [vvar]
7fff321e0000-7fff321e1000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

lib.so 的装载属性

$ readelf -l lib.so Elf file type is DYN (Shared object file)
Entry point 0x1080
There are 11 program headers, starting at offset 64Program Headers:Type           Offset             VirtAddr           PhysAddrFileSiz            MemSiz              Flags  AlignLOAD           0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000560 0x0000000000000560  R      0x1000LOAD           0x0000000000001000 0x0000000000001000 0x00000000000010000x000000000000017d 0x000000000000017d  R E    0x1000LOAD           0x0000000000002000 0x0000000000002000 0x00000000000020000x00000000000000dc 0x00000000000000dc  R      0x1000LOAD           0x0000000000002e10 0x0000000000003e10 0x0000000000003e100x0000000000000220 0x0000000000000228  RW     0x1000DYNAMIC        0x0000000000002e20 0x0000000000003e20 0x0000000000003e200x00000000000001c0 0x00000000000001c0  RW     0x8NOTE           0x00000000000002a8 0x00000000000002a8 0x00000000000002a80x0000000000000020 0x0000000000000020  R      0x8NOTE           0x00000000000002c8 0x00000000000002c8 0x00000000000002c80x0000000000000024 0x0000000000000024  R      0x4GNU_PROPERTY   0x00000000000002a8 0x00000000000002a8 0x00000000000002a80x0000000000000020 0x0000000000000020  R      0x8GNU_EH_FRAME   0x000000000000201c 0x000000000000201c 0x000000000000201c0x000000000000002c 0x000000000000002c  R      0x4GNU_STACK      0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000  RW     0x10GNU_RELRO      0x0000000000002e10 0x0000000000003e10 0x0000000000003e100x00000000000001f0 0x00000000000001f0  R      0x1Section to Segment mapping:Segment Sections...00     .note.gnu.property .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 01     .init .plt .plt.got .plt.sec .text .fini 02     .rodata .eh_frame_hdr .eh_frame 03     .init_array .fini_array .dynamic .got .got.plt .data .bss 04     .dynamic 05     .note.gnu.property 06     .note.gnu.build-id 07     .note.gnu.property 08     .eh_frame_hdr 09     10     .init_array .fini_array .dynamic .got 

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

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

相关文章

LeetCode--88

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并后数组…

ChatGPT实战100例 - (13) 写一个属于自己的 ChatGPT 新版 WebUI

文章目录 ChatGPT实战100例 - (13) 写一个属于自己的 ChatGPT 新版 WebUI一、ChatGPT(OpenAI)的新版API调用1.1 环境变量配置与调用1.2 新版api调用1.3 命令行流式输出二、Gradio制作自己的聊天WebUIChatGPT实战100例 - (13) 写一个属于自己的 ChatGPT 新版 WebUI 今时不同往日…

某赛通电子文档安全管理系统 UploadFileList 任意文件读取漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

用VsCode写python

1.创建一个文件夹 2.创建.py文件 print("Hello World") print("*"*10) 4.运行 在终端版本fileName python3 app.py

线性代数:线性方程组

目录 一、线性方程组概念 二、消元法求线性方程组 三、系数阵的秩与线性方程组的解 无解 唯一解 无数解 相关定理 一、线性方程组概念 二、消元法求线性方程组 三、系数阵的秩与线性方程组的解 无解 唯一解 无数解 相关定理

Redis -- hash哈希

马行软地易失蹄&#xff0c;人贪安逸易失志。 目录 关于Redis的hash hash命令 hset hget hexists hdel hkeys hvals hgetall hmget hlen hsetnx hash计数 hincrby hincrbyfloat 小结 关于Redis的hash 几乎所有的主流编程语言都提供了哈希&#xff08;hash&a…

移动机器人激光SLAM导航(三):Hector SLAM 篇

参考引用 Hector_Mapping ROS-Wiki从零开始搭二维激光SLAM机器人工匠阿杰wpr_simulation 移动机器人激光SLAM导航&#xff08;文章链接汇总&#xff09; 1. 基于滤波器的 SLAM 问题 1.1 什么是 SLAM 什么是SLAM SLAM 就是为了构建地图用的&#xff0c;这个地图可以保存下来&…

SpringBoot集成Redisson实现限流(二)

1. 简介 Springboot集成Redisson默认的限流器为令牌桶型限流器&#xff0c;底层是通过lua脚本去实现的。 通过lua脚本我们可以去实现一个滑动窗口限流器&#xff0c;利用ZSET格式数据就可以轻松实现。 springboot集成Redisson就不做讲解&#xff0c;可以参考&#xff1a;sprin…

将word中插入的zotero文献转为latex引用样式

在word中&#xff0c;可以使用zotero插件插入和管理参考文献。 例如&#xff1a; 若需要将这段内容移植到latex&#xff0c;就需要将对应的引用编号用\cite{}替换。手动替换非常麻烦且容易出错。要实现自动转换&#xff0c;可在zotero中定制一种新的引文格式&#xff0c;自动将…

第二十三天| 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

Leetcode 669. 修剪二叉搜索树 题目链接&#xff1a;669 修剪二叉搜索树 题干&#xff1a;给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元…

常见的6种软件测试用例设计方法

常见的软件测试用例设计方法&#xff0c;个人认为主要是下面这6种&#xff1a; 流程图法&#xff08;也叫场景法&#xff09;等价类划分法边界值分析判定表正交法错误推测法 这6种常见方法中&#xff0c;我分别按照定义、应用场景、使用步骤、案例讲解这4个部分进行讲解。 所…

实习|基于SSM的实习管理系统设计与实现(源码+数据库+文档)

实习管理系统目录 目录 基于SSM的实习管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能介绍 &#xff08;1&#xff09;管理员登录 &#xff08;2&#xff09;实训方向管理 &#xff08;3&#xff09;公告信息管理 &#xff08;4&#xff0…

C++——STL标准模板库——常用算法归纳

使用标准模板库提供的算法需要包含头文件&#xff1a;algorithm&#xff0c;其中包含了遍历、查找、排序、拷贝和替换等算法。当容器储存内置数据类型可使用STL提供函数对象&#xff0c;当容器储存自定义数据类型时需要自定义数据对象或者函数用于提供自定义数据类型的比较、计…

STM32MP135开发板助力电力行业,IEC61850协议移植笔记

1.概述 IEC61850是变电站自动化系统&#xff08;SAS&#xff09;中通信系统和分散能源&#xff08;DER&#xff09;管理的国际标准。它通过标准的实现&#xff0c;实现了智能变电站的工程运作标准化。使得智能变电站的工程实施变得规范、统一和透明&#xff0c;在电力和储能系…

go语言-用channel控制goroutine的退出

用channel控制goroutine的退出 本文简要介绍了&#xff0c;如何用channel控制goroutine的退出的基本方法 for-range主动停止goruitine package mainimport ("fmt""sync""time" )/* Go并发编程模型&#xff1a;主动停止goroutine 方法一&#…

(java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~

目录 冒泡排序(BubbleSort)&#xff1a; 代码详解&#xff1a; 冒泡排序的优化&#xff1a; 选择排序(SelectSort)&#xff1a; 代码详解&#xff1a; 插入排序&#xff08;InsertSort&#xff09;&#xff1a; 代码详解&#xff1a; 希尔排序(ShellSort)&#xff1a; 法一…

Java中的常用API

常用API Object类浅克隆与深克隆 ObjectsObjects中的equals 包装类StringBuilder和StringBufferStringBuilder是可变字符串对象StringBuffer线程安全案例![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/87649c20e6464113a42aee5f16f1ee22.png) StringJoiner Object…

关于ZYZ旋转和XYZ旋转

ZYZ旋转和XYZ旋转 概述1、XYZ旋转2、ZYZ旋转 概述 以下公式默认为右手坐标系&#xff1b;ZYZ通常可以避免死解情况&#xff0c;因此在六轴末端解算时常被用到&#xff1b;参考文章 1、XYZ旋转 XYZ旋转一般是绕固定轴旋转(外旋)&#xff0c;旋转矩阵的构成为&#xff1a;RzRy…

软考 系统分析师系列知识点之需求管理(3)

接前一篇文章&#xff1a;软考 系统分析师系列知识点之需求管理&#xff08;2&#xff09; 所属章节&#xff1a; 第11章. 软件需求工程 第8节. 需求管理 11.8.4 需求跟踪 根据IEEE的定义&#xff0c;可跟踪性包含两个层面的含义&#xff1a;一个是开发过程的两个或多个产品之…

无广告iOS获取设备UDID 简单方便快捷

ps&#xff1a; 为啥不用蒲公英了&#xff0c;就是因为有广告了&#xff0c;获取个UDID还安装游戏&#xff0c;真恶心?&#xff0c;所以找了新的获取UDID都方法&#xff0c;网页直接获取就可以&#xff0c;不会安装软件。 UDID 是一种 iOS 设备的特殊识别码。除序号之外&…