【Linux指南】动静态库系列(九):动态库如何进入进程地址空间:从磁盘 .so 到共享内存映射
文章目录一、动态库为什么比静态库更常用二、动态库也是文件三、动态库加载的整体流程四、从磁盘 .so 到物理内存五、从物理内存到进程虚拟地址空间六、多个进程如何共享同一个动态库七、共享的是代码不是什么都共享八、为什么动态库加载地址不固定九、使用 /proc 查看动态库映射十、使用 pmap 查看进程映射十一、动态链接和静态链接再对比一次十二、为什么动态库需要后续重定位十三、总结前面我们已经知道动态库.so不是在编译链接阶段完整拷贝进可执行程序而是在程序运行时被动态链接器加载。那么问题来了磁盘上的libxxx.so到底是怎么进入进程地址空间的多个程序都依赖同一个动态库时系统真的会给每个进程都复制一份库代码吗为什么说动态库可以节省内存这篇文章就围绕“动态库如何映射到进程地址空间”展开。一、动态库为什么比静态库更常用静态链接会把用到的库代码合并进可执行文件。这样程序可以独立运行但也带来两个问题可执行文件变大。多个程序使用同一个库时会重复保存同一份代码。假设系统里有 100 个程序都用到了 C 标准库。如果每个程序都把 libc 的代码静态链接进去磁盘和内存都会浪费大量空间。动态库的思路是把公共代码单独放在 .so 文件中 程序运行时再加载 多个进程尽量共享同一份库代码。这就是动态库广泛使用的重要原因。二、动态库也是文件先明确一点动态库不是内存里凭空出现的东西它首先是磁盘上的一个普通文件。例如ls-l/lib64/libc.so.6file/lib64/libc.so.6你会发现它是一个 ELF shared object。所以加载动态库的第一步仍然是文件操作找到 .so 文件 打开 .so 文件 读取 ELF 信息 把需要的 segment 映射进内存只不过这个过程通常由动态链接器和内核协作完成程序员平时不直接感知。三、动态库加载的整体流程一个动态链接程序启动时大致流程如下1. 内核加载主程序 ELF 2. 发现主程序需要动态链接器 3. 动态链接器读取主程序依赖的 .so 列表 4. 找到每个 .so 文件 5. 将 .so 的代码段、数据段等映射到进程地址空间 6. 完成必要的符号解析和重定位 7. 进入程序 main 函数如果第 4 步找不到库就会出现我们前一篇讲的libxxx.so not found如果能找到库下一步就是把库映射到进程地址空间中。四、从磁盘 .so 到物理内存当程序依赖libmyc.so时动态链接器会找到磁盘上的库文件。然后系统会把库中需要加载的 segment 放入物理内存尤其是代码段.text对应的内容。可以先粗略理解为磁盘 libmyc.so - 加载到物理内存中的若干页现代系统很多时候还会用文件映射、按需分页等机制并不是一开始就把整个库所有内容都读入内存。但从理解动态库共享的角度我们先抓住核心库文件的内容最终要对应到物理内存页。五、从物理内存到进程虚拟地址空间进程不能直接使用物理地址。每个进程看到的是自己的虚拟地址空间。所以动态库加载后还需要在当前进程的虚拟地址空间中划出一段区域用来映射这份库。可以理解为进程虚拟地址空间中的一段共享区 - 通过页表 - 映射到物理内存中的 libmyc.so 代码页例如进程 A 中libmyc.so可能映射到0x7f1000000000 ~ 0x7f1000010000这只是进程 A 自己看到的虚拟地址范围。真正的物理内存在哪里进程并不直接关心。CPU 会通过页表完成转换。六、多个进程如何共享同一个动态库假设进程 A 和进程 B 都依赖libmyc.so。进程 A 启动时磁盘 libmyc.so - 物理内存代码页 进程 A 的虚拟共享区 - 映射到这些物理页进程 B 启动时如果系统发现这份库的代码页已经在物理内存中就不必再加载一份完整代码。它只需要给进程 B 分配自己的虚拟共享区 让进程 B 的页表也映射到同一批物理代码页于是形成进程 A 虚拟地址 0x7f1000000000 - 同一份物理库代码 进程 B 虚拟地址 0x7f2000000000 - 同一份物理库代码注意两个进程的虚拟地址可以不同 但它们可以映射到同一份物理内存。这就是动态库节省内存的关键。七、共享的是代码不是什么都共享动态库中并不是所有内容都能随便共享。一般来说只读代码段可以共享 只读数据可以共享 可写数据通常不能直接在进程间共享。原因很简单如果动态库中的全局变量被多个进程共享那进程 A 修改变量会影响进程 B这显然不符合普通进程隔离原则。所以动态库的可写数据部分通常会为每个进程提供独立映射或者通过写时拷贝等机制保证进程隔离。动态库节省内存主要依赖代码段只读可以被多个进程共享。这也是为什么动态库代码要尽量做到位置无关不能随便修改代码段本身。八、为什么动态库加载地址不固定每个进程都有自己的虚拟地址空间。不同进程加载了不同的程序、不同的库地址空间中空闲区域也不同。所以动态链接器不能假设所有进程都把libmyc.so放到同一个虚拟地址。它通常会在当前进程地址空间中选择一段合适的空闲区域把动态库映射进去。这就带来一个关键问题动态库如果被加载到任意地址里面的函数调用和全局变量访问怎么保证正确这就是下一篇 GOT/PIC 要解决的问题。九、使用 /proc 查看动态库映射Linux 提供了/proc/[pid]/maps可以查看进程地址空间映射。先运行一个程序让它保持一段时间./main如果程序很快退出可以在代码中加sleep(100)。然后查看pidof maincat/proc/进程PID/maps你会看到类似7f... r-xp ... /lib64/libc.so.6 7f... r--p ... /lib64/libc.so.6 7f... rw-p ... /lib64/libc.so.6这些行说明libc.so.6的不同部分被映射到了进程虚拟地址空间中并且权限不同r-xp可读可执行通常对应代码段 r--p只读 rw-p可读可写通常对应数据段这能非常直观地看到动态库确实进入了进程地址空间。十、使用 pmap 查看进程映射也可以使用pmap 进程PID它会以更简洁的形式展示进程内存映射。例如pmap$(pidof main)可以看到主程序、堆、栈、动态库等区域。学习动态库时/proc/[pid]/maps是非常有价值的观察工具。十一、动态链接和静态链接再对比一次静态链接库代码在链接阶段进入可执行文件 程序运行时不再找库 多个程序各自包含一份库代码。动态链接可执行文件记录依赖 程序运行时加载 .so 多个进程可以共享同一份库代码物理页。动态链接本质上把一部分链接工作推迟到了程序加载和运行阶段。这带来灵活性也带来复杂性。十二、为什么动态库需要后续重定位动态库被映射到进程地址空间后它的加载地址才真正确定。但库代码中可能需要访问库内函数 库内全局变量 其他动态库函数 主程序中的符号有些地址必须在加载后才能知道。所以动态链接器还要做符号解析和重定位让这些引用指向正确位置。问题是代码段通常是只读且共享的不能每个进程都直接修改代码段里的地址。因此动态链接需要一种更巧妙的机制把可能变化的地址放到可写表中代码通过查表跳转。这张表就是 GOT全局偏移表。十三、总结动态库加载不是简单地“把.so拷贝进进程”。更准确的理解是动态链接器找到 .so 内核把 .so 的 segment 映射进进程虚拟地址空间 多个进程可以通过各自页表映射到同一份物理代码页 动态链接器再完成必要的符号解析和重定位动态库节省内存的关键在于只读代码段可以共享。但动态库加载地址不固定这就要求动态库不能把绝对地址写死在代码里。下一篇我们继续讲 GOT 与 PIC看动态库如何做到“加载到哪里都能运行”。

相关新闻

双指针,滑动窗口

双指针,滑动窗口

1,数组划分 将一组数据划分为不同的区间 解决这一类题用双指针算法,利用数组下标来充当指针 常见的双指针有两种形式,一种是对撞指针,一种是左右指针。 对撞指针:一般用于顺序结构中,也称左右指针。 •…

2026/9/30 13:50:08 阅读更多 →
基于YOLO的猫情绪识别:3200张宠物行为数据集构建与训练实践

基于YOLO的猫情绪识别:3200张宠物行为数据集构建与训练实践

做宠物摄像头项目时,我卡在一个很朴素的问题上:猫到底处于什么状态?如果只是“有猫/没猫”,用现成人脸检测模型就行,但客户要的是“放松、警觉、紧张、害怕、玩耍”这种细粒度情绪反馈。翻遍公开数据集,猫狗…

2026/9/30 13:50:08 阅读更多 →
基于LSTM的航班延误预测:从序列特征工程到模型落地

基于LSTM的航班延误预测:从序列特征工程到模型落地

简介:这份PDF文档聚焦民航领域的航班延误预测问题,面向从事数据建模、机器学习应用及空管运行优化的技术人员与研究者。文档以循环神经网络为核心,系统讲解RNN与LSTM单元相混合的深度学习算法设计思路,并结合民航空管历史真实数据…

2026/9/30 13:50:08 阅读更多 →

最新新闻

TensorFlow 2024实战:安装避坑与工业级部署全攻略

TensorFlow 2024实战:安装避坑与工业级部署全攻略

如果你现在问我,TensorFlow 还值不值得花时间学,我的回答会跟两年前不太一样。这两年生成式AI大爆发,PyTorch在论文和实验室里几乎是统治级的存在,很多新人甚至直接跳过TensorFlow。但真正落到生产环境、落到底层硬件优化、落到移…

2026/9/30 15:16:32 阅读更多 →
无人机辅助旅行商问题求解:Transformer与POMO深度强化学习实践

无人机辅助旅行商问题求解:Transformer与POMO深度强化学习实践

简介:这是一份面向物流运筹优化与深度强化学习研究者的学术论文PDF,聚焦旅行商问题与无人机(TSP-D)的协同路径规划,提出融合注意力编码器与LSTM解码器的混合模型,解决传统注意力模型难以协调卡车与无人机多…

2026/9/30 15:16:32 阅读更多 →
LLM Agent 长期记忆架构设计:MCP 协议集成与 Docker 部署实战

LLM Agent 长期记忆架构设计:MCP 协议集成与 Docker 部署实战

1. 从“hindsight”说起:为什么我们需要给 Agent 装上“后视之明”“hindsight”这个词本身很有意思,字面意思是“事后的洞察力”,也就是我们常说的“后见之明”。放在 LLM Agent 的语境里,它指向一个非常具体且要命的问题&#x…

2026/9/30 15:16:32 阅读更多 →
AI代码生成实战:从Prompt到PLC编程,规范与避坑指南

AI代码生成实战:从Prompt到PLC编程,规范与避坑指南

最近大半年,我一直在一线写代码,也一直在折腾 AI 代码生成。从最开始拿它补全几个函数,到后来直接让它写完整的模块、生成单元测试,再到把 AI 拉进工控项目里写 PLC 程序,这一路下来,最大的感受就八个字&am…

2026/9/30 15:16:32 阅读更多 →
大数据架构性能优化:从硬件选型到查询调优的完整链路

大数据架构性能优化:从硬件选型到查询调优的完整链路

做大数据架构性能优化这些年,我最大的感受是: 大多数系统的性能问题,在硬件下单的那一刻就已经注定了 。机器到了、集群搭好之后再去调参、改SQL、加缓存,都是在给当初的选型失误买单。所以我一直认为,"大数据架…

2026/9/30 15:16:32 阅读更多 →
SpringBoot+Vue医院后台管理系统:从架构到部署的毕设实战指南

SpringBoot+Vue医院后台管理系统:从架构到部署的毕设实战指南

做毕设选型这件事,我见过太多同学在SpringBootVue这套组合上反复纠结。说实话,医院后台管理系统几乎是Java全栈学习路上最值得动手做一遍的项目类型,因为它的业务边界清晰、模块划分天然、权限模型典型,而且完全踩中了SpringBoot、…

2026/9/30 15:15:29 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/30 13:14:22 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/30 13:14:49 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →